def test_configure_gpios(self):
        Device.pin_factory.reset()
        controls = mock.Mock()
        config = {}
        controller = GpioController(config, controls)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': GpioConfig().deserialize("pull_up,150")}
        controller.configure_gpios()
        for gpio in range(27):
            self.assertIsNone(controller.gpios[gpio])
        self.assertIsNotNone(controller.gpios[27])
        self.assertTrue(controller.gpios[27].pull_up)
        self.assertEqual(1, controller.gpios[27].hold_time)
        self.assertFalse(controller.gpios[27].hold_repeat)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': GpioConfig().deserialize("pull_down")}
        controller.configure_gpios()
        for gpio in range(27):
            self.assertIsNone(controller.gpios[gpio])
        self.assertIsNotNone(controller.gpios[27])
        self.assertFalse(controller.gpios[27].pull_up)
        self.assertEqual(1, controller.gpios[27].hold_time)
        self.assertFalse(controller.gpios[27].hold_repeat)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': GpioConfig().deserialize("none")}
        controller.configure_gpios()
        for gpio in range(27):
            self.assertIsNone(controller.gpios[gpio])
        self.assertIsNotNone(controller.gpios[27])
        self.assertIsNone(controller.gpios[27].pull_up)
        self.assertEqual(1, controller.gpios[27].hold_time)
        self.assertFalse(controller.gpios[27].hold_repeat)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': GpioConfig().deserialize("none_invert")}
        controller.configure_gpios()
        for gpio in range(27):
            self.assertIsNone(controller.gpios[gpio])
        self.assertIsNotNone(controller.gpios[27])
        self.assertIsNone(controller.gpios[27].pull_up)
        self.assertEqual(1, controller.gpios[27].hold_time)
        self.assertFalse(controller.gpios[27].hold_repeat)
    def test_configure_button(self):
        controls = mock.Mock()
        config = {}
        controller = GpioController(config, controls)

        # no config set, should pass without changes
        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {}
        controller.configure_button(27, 'when_held')
        controller.configure_button(27, 'when_released')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': None}
        controller.configure_button(27, 'when_released')
        controller.configure_button(27, 'when_held')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {'gpio27': ''}
        controller.configure_button(27, 'when_released')
        controller.configure_button(27, 'when_held')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.config = {
            'gpio27.when_pressed': FunctionConfig().deserialize('play_pause')
        }
        controller.configure_button(27, 'when_held')
        with self.assertRaises(ValueError):
            controller.configure_button(27, 'when_pressed')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.config = {
            'gpio0.when_pressed': FunctionConfig().deserialize('unknown_fn')
        }
        with self.assertRaises(ValueError):
            controller.configure_button(0, 'when_pressed')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.config = {
            'gpio0.when_pressed': FunctionConfig().deserialize('play_pause')
        }
        controller.configure_button(0, 'when_pressed')
        self.assertIsNotNone(controller.gpios[0].when_pressed)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.gpios[0].when_pressed = lambda x: x
        controller.config = {
            'gpio0.when_pressed': FunctionConfig().deserialize('play_pause')
        }
        with self.assertRaises(ValueError):
            controller.configure_button(0, 'when_pressed')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.config = {
            'gpio0.when_held': FunctionConfig().deserialize(' play_pause ')
        }
        controller.configure_button(0, 'when_held')
        self.assertIsNotNone(controller.gpios[0].when_held)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.gpios[0].when_held = lambda x: x
        controller.config = {
            'gpio0.when_held': FunctionConfig().deserialize('play_pause')
        }
        with self.assertRaises(ValueError):
            controller.configure_button(0, 'when_held')

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.config = {
            'gpio0.when_released': FunctionConfig().deserialize(' play_pause ')
        }
        controller.configure_button(0, 'when_released')
        self.assertIsNotNone(controller.gpios[0].when_released)

        Device.pin_factory.reset()
        controller.gpios = [None] * 28
        controller.gpios[0] = Button(0)
        controller.gpios[0].when_released = lambda x: x
        controller.config = {
            'gpio0.when_released': FunctionConfig().deserialize('play_pause')
        }
        with self.assertRaises(ValueError):
            controller.configure_button(0, 'when_released')