def test_start_and_stop(self): ''' Basic start and stop test. ''' mock_monitor = mock() mock_device = mock() when(mock_device).get_vendor_id().thenReturn(0) when(mock_device).get_product_id().thenReturn(0) controller = DeviceController(mock_device, usb_transfer_types.RAW, mock_monitor, logger=self._logger) controller.start() self.assertTrue(controller.running) controller.stop() self.assertFalse(controller.running)
def test_stop_and_stop_again(self): ''' Trying to stop twice must not fail. ''' mock_device = mock() when(mock_device).get_vendor_id().thenReturn(0) when(mock_device).get_product_id().thenReturn(0) when(mock_device).is_opened().thenReturn(True) mock_monitor = mock() controller = DeviceController(mock_device, usb_transfer_types.RAW, mock_monitor, logger=self._logger) controller.start() self.assertTrue(controller.running) controller.stop() self.assertFalse(controller.running) controller.stop() self.assertFalse(controller.running)
def test_start_with_device_disconnected(self): ''' Test that the add event does not get invoked on start-up. ''' event = Event() event.clear() def _add_handler(): self._logger.debug('Invoked') event.set() mock_monitor = MockDeviceMonitor(dormant=True) mock_device = mock() when(mock_device).get_vendor_id().thenReturn(0) when(mock_device).get_product_id().thenReturn(0) when(mock_device).is_open().thenReturn(False) # Execute controller = DeviceController(mock_device, usb_transfer_types.RAW, mock_monitor, add_event_handler=_add_handler, logger=self._logger) controller.start() self.assertTrue(controller.running) event.wait(0.1) controller.stop() self.assertFalse(controller.running) # The event must not have been raised self.assertFalse(event.is_set(), 'Add handler must not be invoked') # Verify mocks inorder.verify(mock_device, times=1).get_vendor_id() inorder.verify(mock_device, times=1).get_product_id() inorder.verify(mock_device, times=1).open() # Once on start-up and once on shutdown # But, it seems mockito needs it to be verified twice, otherwise # the verify.close will fail. inorder.verify(mock_device, times=2).is_open() inorder.verify(mock_device, times=2).is_open() inorder.verify(mock_device, times=0).close()
def test_without_handlers_must_still_open_and_close_device(self): ''' Test that, without handlers, the device gets opened and closed. ''' # Setup mock_monitor = MockDeviceMonitor(dormant=True) mock_device = mock() when(mock_device).get_vendor_id().thenReturn(0) when(mock_device).get_product_id().thenReturn(0) when(mock_device).is_open().thenReturn(True) controller = DeviceController(mock_device, usb_transfer_types.RAW, mock_monitor, logger=self._logger) # Execute controller.start() self.assertTrue(controller.running) controller.stop() self.assertFalse(controller.running) # Verify mocks verify(mock_device, times=1).open() verify(mock_device, times=1).close()
def test_manually_with_different_device_modules_and_managers(self): ''' Manual testing: Blink all lights a few times. You must be able to connect and disconnect the device while executing. It doesn't really matter whether the device is initially connected or disconnected. ''' # Overriding the default log level so that the instructions are clear # and not obfuscated by the many debug messages. self._logger.setLevel('INFO') # You must enable only one of these use_module = 'pyusb' #use_module = 'teensyrawhid' # And one of these use_monitor = 'pyudev' #use_monitor = 'polling_device_manager' # Basics vendor_id = 0x16c0 product_id = 0x0486 add_timeout_message = 'The add event must have been invoked' remove_timeout_message = 'The remove event must have been invoked' iterations = 3 event_delay = 30 blink_delay = 0.5 running = False # Trick to get past the closure: The pointer of the states dictionary # can't changed, but its data can. :-) states = {'paused': True} # Select the module to test if use_module == 'pyusb': interface_number = 1 device = whatsthatlight.devices.PyUsbDevice(vendor_id, product_id, interface_number) elif use_module == 'teensyrawhid': usage_page = 0xffc9 usage = 0x0004 device = whatsthatlight.devices.TeensyDevice(vendor_id, product_id, usage_page, usage) else: raise Exception('Invalid USB device module specified') # Select the device manager to test if use_monitor == 'pyudev': monitor = PyUdevDeviceMonitor(vendor_id, product_id, pyudev, logger=self._logger) elif use_monitor == 'polling': monitor = None else: raise Exception('Invalid device manager specified') # Execution controllers add_event = Event() remove_event = Event() paused_event = Event() add_event.clear() remove_event.clear() paused_event.clear() # Handlers and helpers def _add_handler(): states['paused'] = False paused_event.set() add_event.set() self._logger.debug('Invoked') def _remove_handler(): paused_event.clear() states['paused'] = True remove_event.set() self._logger.debug('Invoked') def _run(): self._logger.debug('Entering run loop') toggle = True while running: if states['paused']: self._logger.debug('Pausing run loop') paused_event.wait(event_delay) self._logger.debug('Resuming run loop') # No point asserting sent data if the device gets # disconnected while communicating with it -- it's # likely to fail. if toggle: success = (controller.send('red=on\n') and controller.send('green=on\n') and controller.send('yellow=on\n')) self._logger.debug('All on: {0}'.format(success)) else: success = (controller.send('red=off\n') and controller.send('green=off\n') and controller.send('yellow=off\n')) self._logger.debug('All off: {0}'.format(success)) toggle = not toggle sleep(blink_delay) self._logger.debug('Exiting run loop') # Setup thread = Thread(target=_run) controller = DeviceController(device, usb_transfer_types.RAW, monitor, add_event_handler=_add_handler, remove_event_handler=_remove_handler, logger=self._logger) # Start everything controller.start() self.assertTrue(controller.running) running = True thread.start() # Ensure a clean shutdown as to not hang the test unnecessarily try: i = 0 while i < iterations: # Wait until device connected self._logger.info('Waiting for device to be connected') add_event.wait(event_delay) self.assert_(add_event.is_set(), add_timeout_message) add_event.clear() # Wait until device disconnected self._logger.info('Waiting for device to be disconnected') remove_event.wait(event_delay) self.assert_(remove_event.is_set(), remove_timeout_message) remove_event.clear() # Next iteration i += 1 except AssertionError: raise finally: # Stop everything running = False thread.join() controller.stop() self.assertFalse(controller.running)
def test_add_remove_handler_must_be_invoked(self): ''' Test that the add and remove handlers get invoked. ''' # Basics vendor_id_str = '0a1b' vendor_id = int(vendor_id_str, 16) product_id_str = '2c3d' product_id = int(product_id_str, 16) # Execution controllers add_event = Event() remove_event = Event() add_event.clear() remove_event.clear() # Event handlers def _add_handler(): self._logger.debug('Invoked') add_event.set() def _remove_handler(): self._logger.debug('Invoked') remove_event.set() mock_device = mock() when(mock_device).get_vendor_id().thenReturn(vendor_id) when(mock_device).get_product_id().thenReturn(product_id) # pyudev provide the values as hex strings, without the 0x prefix mock_pyudev.vendor_id = vendor_id_str mock_pyudev.model_id = product_id_str mock_pyudev.dormant = False mock_pyudev.delay = 0.1 wait_delay = mock_pyudev.delay * 2 # This VID and PID must match the above mock_monitor = PyUdevDeviceMonitor(vendor_id, product_id, udev_module=mock_pyudev, logger=self._logger) controller = DeviceController(mock_device, usb_transfer_types.RAW, mock_monitor, add_event_handler=_add_handler, remove_event_handler=_remove_handler, logger=self._logger) controller.start() self.assertTrue(controller.running) # Wait for the handlers to be invoked add_event.wait(wait_delay) remove_event.wait(wait_delay) # Shut down controller.stop() self.assertFalse(controller.running) # Test after stopping so that we don't hang the test if an # assertion failed self.assertTrue(add_event.is_set(), 'Add handler must not be invoked') self.assertTrue(remove_event.is_set(), 'Remove handler must not be invoked') verify(mock_device, times=2).open() verify(mock_device, times=1).close()