def test_micropython_mode_find_device_darwin_remove_extraneous_devices(): """ Check that if on OS X, only one version of the same device is shown, as OS X shows every device on two different ports. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.valid_boards = [(0x0D28, 0x0204, None, "micro:bit")] mock_port = mock.MagicMock() mock_port.portName = mock.MagicMock(return_value="tty.usbserial-XXX") mock_port.productIdentifier = mock.MagicMock(return_value=0x0204) mock_port.vendorIdentifier = mock.MagicMock(return_value=0x0D28) mock_port.serialNumber = mock.MagicMock(return_value="123456") mock_port2 = mock.MagicMock() mock_port2.portName = mock.MagicMock(return_value="cu.usbserial-XXX") mock_port2.productIdentifier = mock.MagicMock(return_value=0x0204) mock_port2.vendorIdentifier = mock.MagicMock(return_value=0x0D28) mock_port2.serialNumber = mock.MagicMock(return_value="123456") device = Device( mock_port2.vendorIdentifier(), mock_port2.productIdentifier(), "/dev/" + mock_port2.portName(), mock_port2.serialNumber(), "ARM", "BBC micro:bit", "microbit", None, ) with mock.patch("sys.platform", "darwin"), mock.patch("os.name", "posix"), mock.patch( "mu.modes.base.QSerialPortInfo.availablePorts", return_value=[mock_port, mock_port2], ): assert mm.find_devices() == [device]
def test_micropython_mode_remove_plotter(): """ Ensure the plotter is removed and data is saved as a CSV file in the expected directory. """ editor = mock.MagicMock() view = mock.MagicMock() view.plotter_pane.raw_data = [1, 2, 3] mm = MicroPythonMode(editor, view) mm.plotter = mock.MagicMock() mock_mkdir = mock.MagicMock() mock_open = mock.mock_open() mock_csv_writer = mock.MagicMock() mock_csv = mock.MagicMock() mock_csv.writer.return_value = mock_csv_writer with mock.patch('mu.modes.base.os.path.exists', return_value=False), \ mock.patch('mu.modes.base.os.makedirs', mock_mkdir), \ mock.patch('builtins.open', mock_open), \ mock.patch('mu.modes.base.csv', mock_csv): mm.remove_plotter() assert mm.plotter is None view.remove_plotter.assert_called_once_with() dd = os.path.join(mm.workspace_dir(), 'data_capture') mock_mkdir.assert_called_once_with(dd) mock_csv_writer.writerows.\ assert_called_once_with(view.plotter_pane.raw_data)
def test_micropython_mode_find_device(): """ Ensure it's possible to detect a device and return the expected port. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mock_port = mock.MagicMock() for vid, pid, manufacturer, board_name in mm.valid_boards: mock_port.vid = vid mock_port.productIdentifier = mock.MagicMock(return_value=pid) mock_port.vendorIdentifier = mock.MagicMock(return_value=vid) mock_port.manufacturer = mock.MagicMock(return_value=manufacturer) mock_port.portName = mock.MagicMock(return_value="COM0") mock_port.serialNumber = mock.MagicMock(return_value="12345") mock_os = mock.MagicMock() mock_os.name = "nt" mock_sys = mock.MagicMock() mock_sys.platform = "win32" device = Device( mock_port.vendorIdentifier(), mock_port.productIdentifier(), mock_port.portName(), mock_port.serialNumber(), "micro:bit", board_name, None, ) with mock.patch( "mu.modes.base.QSerialPortInfo.availablePorts", return_value=[mock_port], ), mock.patch("mu.modes.base.os", mock_os), mock.patch("mu.modes.base.sys", mock_sys): assert mm.find_devices() == [device]
def test_micropython_mode_add_repl_already_exists(): """ Ensure the editor raises a RuntimeError if the repl already exists. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.repl = True with pytest.raises(RuntimeError): mm.add_repl()
def test_micropython_activate(): """ Ensure the device selector is shown when MicroPython-mode is activated. """ editor = mock.MagicMock() view = mock.MagicMock() view.show_device_selector = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.activate() view.show_device_selector.assert_called_once_with()
def test_micropython_mode_port_path_nt(): """ Ensure the correct path for a port_name is returned if the platform is nt. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) with mock.patch('os.name', 'nt'): assert mm.port_path('COM0') == "COM0"
def test_micropython_mode_port_path_unknown(): """ If the platform is unknown, raise NotImplementedError. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) with mock.patch('os.name', 'foo'): with pytest.raises(NotImplementedError): mm.port_path('bar')
def test_micropython_mode_remove_repl_is_none(): """ If there's no repl to remove raise a RuntimeError. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.repl = None with pytest.raises(RuntimeError): mm.remove_repl()
def test_micropython_mode_port_path_posix(): """ Ensure the correct path for a port_name is returned if the platform is posix. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) with mock.patch('os.name', 'posix'): assert mm.port_path('tty1') == "/dev/tty1"
def test_micropython_mode_find_device_no_ports(): """ There are no connected devices so return None. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) with mock.patch('mu.modes.base.QSerialPortInfo.availablePorts', return_value=[]): assert mm.find_device() == (None, None)
def test_micropython_mode_toggle_repl_on(): """ There is no repl, so toggle on. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.add_repl = mock.MagicMock() mm.repl = None mm.toggle_repl(None) assert mm.add_repl.call_count == 1
def test_micropython_mode_toggle_repl_off(): """ There is a repl, so toggle off. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.remove_repl = mock.MagicMock() mm.repl = True mm.toggle_repl(None) assert mm.remove_repl.call_count == 1
def test_micropython_mode_toggle_plotter_on(): """ There is no plotter, so toggle on. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.add_plotter = mock.MagicMock() mm.plotter = None mm.toggle_plotter(None) assert mm.add_plotter.call_count == 1
def test_micropython_mode_toggle_plotter_off(): """ There is a plotter, so toggle off. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.remove_plotter = mock.MagicMock() mm.plotter = True mm.toggle_plotter(None) assert mm.remove_plotter.call_count == 1
def test_micropython_mode_remove_plotter_active_repl(): """ When removing the plotter, if the repl is active, retain the connection. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.connection = mock.MagicMock() mm.repl = True mm.remove_plotter() assert mm.plotter is False assert mm.connection is not None
def test_micropython_mode_add_repl_exception(): """ Ensure that any non-IOError based exceptions are logged. """ editor = mock.MagicMock() view = mock.MagicMock() ex = Exception("BOOM") view.add_micropython_repl = mock.MagicMock(side_effect=ex) mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=("COM0", "12345")) with mock.patch("mu.modes.base.logger", return_value=None) as logger: mm.add_repl() logger.error.assert_called_once_with(ex)
def test_micropython_on_data_flood(): """ Ensure that the REPL is removed before calling the base on_data_flood method. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.remove_repl = mock.MagicMock() with mock.patch('builtins.super') as mock_super: mm.on_data_flood() mm.remove_repl.assert_called_once_with() mock_super().on_data_flood.assert_called_once_with()
def test_micropython_mode_remove_repl(): """ If there is a repl, make sure it's removed as expected and the state is updated. """ editor = mock.MagicMock() view = mock.MagicMock() view.remove_repl = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.repl = True mm.remove_repl() assert view.remove_repl.call_count == 1 assert mm.repl is False
def test_micropython_mode_add_plotter_exception(): """ Ensure that any non-IOError based exceptions are logged. """ editor = mock.MagicMock() view = mock.MagicMock() ex = Exception('BOOM') view.add_micropython_plotter = mock.MagicMock(side_effect=ex) mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=('COM0', '12345')) with mock.patch('mu.modes.base.logger', return_value=None) as logger: mm.add_plotter() logger.error.assert_called_once_with(ex)
def test_micropython_mode_find_microbit_no_device(): """ None of the connected devices is a valid board so return None. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mock_port = mock.MagicMock() mock_port = mock.MagicMock() mock_port.productIdentifier = mock.MagicMock(return_value=666) mock_port.vendorIdentifier = mock.MagicMock(return_value=999) with mock.patch('mu.modes.base.QSerialPortInfo.availablePorts', return_value=[mock_port, ]): assert mm.find_device() is None
def test_micropython_mode_add_plotter_no_port(): """ If it's not possible to find a connected micro:bit then ensure a helpful message is enacted. """ editor = mock.MagicMock() view = mock.MagicMock() view.show_message = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=(None, None)) mm.add_plotter() assert view.show_message.call_count == 1 message = 'Could not find an attached device.' assert view.show_message.call_args[0][0] == message
def test_micropython_mode_add_repl_no_port(): """ If it's not possible to find a connected micro:bit then ensure a helpful message is enacted. """ editor = mock.MagicMock() editor.current_device = None view = mock.MagicMock() view.show_message = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.add_repl() assert view.show_message.call_count == 1 message = "Could not find an attached device." assert view.show_message.call_args[0][0] == message
def test_micropython_mode_remove_plotter_disconnects(): """ Ensure that connections are closed when plotter is closed. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.repl = False mm.plotter = True mock_repl_connection = mock.MagicMock() mm.connection = mock_repl_connection mm.remove_plotter() mock_repl_connection.close.assert_called_once_with() assert mm.connection is None
def test_micropython_mode_add_plotter(): """ Nothing goes wrong so check the _view.add_micropython_plotter gets the expected argument. """ editor = mock.MagicMock() view = mock.MagicMock() view.show_message = mock.MagicMock() view.add_micropython_plotter = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=('COM0', '12345')) with mock.patch('os.name', 'nt'): mm.add_plotter() assert view.show_message.call_count == 0 assert view.add_micropython_plotter.call_args[0][0] == 'COM0'
def test_micropython_mode_add_repl(): """ Nothing goes wrong so check the _view.add_micropython_repl gets the expected argument. """ editor = mock.MagicMock() view = mock.MagicMock() view.show_message = mock.MagicMock() view.add_micropython_repl = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=("COM0", "12345")) with mock.patch("os.name", "nt"): mm.add_repl() assert view.show_message.call_count == 0 assert view.add_micropython_repl.call_args[0][0] == "COM0"
def test_micropython_mode_remove_repl_and_disconnect(): """ If there is a repl, make sure it's removed as expected and the state is updated. Disconnect any open serial connection. """ editor = mock.MagicMock() view = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.repl = True mm.plotter = False mock_repl_connection = mock.MagicMock() mm.connection = mock_repl_connection mm.remove_repl() mock_repl_connection.close.assert_called_once_with() assert mm.connection is None
def test_micropython_mode_add_plotter_ioerror(): """ Sometimes when attempting to connect to the device there is an IOError because it's still booting up or connecting to the host computer. In this case, ensure a useful message is displayed. """ editor = mock.MagicMock() view = mock.MagicMock() view.show_message = mock.MagicMock() ex = IOError('BOOM') view.add_micropython_plotter = mock.MagicMock(side_effect=ex) mm = MicroPythonMode(editor, view) mm.find_device = mock.MagicMock(return_value=('COM0', '123456')) mm.add_plotter() assert view.show_message.call_count == 1 assert view.show_message.call_args[0][0] == str(ex)
def test_micropython_mode_add_plotter_exception(microbit): """ Ensure that any non-IOError based exceptions are logged. """ editor = mock.MagicMock() editor.current_device = microbit view = mock.MagicMock() ex = Exception("BOOM") mm = MicroPythonMode(editor, view) mock_repl_connection = mock.MagicMock() mock_repl_connection.open = mock.MagicMock(side_effect=ex) mock_connection_class = mock.MagicMock(return_value=mock_repl_connection) with mock.patch("mu.modes.base.logger", return_value=None) as logger: with mock.patch("mu.modes.base.REPLConnection", mock_connection_class): mm.add_plotter() logger.error.assert_called_once_with(ex)
def test_micropython_mode_add_repl_no_force_interrupt(): """ Nothing goes wrong so check the _view.add_micropython_repl gets the expected arguments (including the flag so no keyboard interrupt is called). """ editor = mock.MagicMock() view = mock.MagicMock() view.show_message = mock.MagicMock() view.add_micropython_repl = mock.MagicMock() mm = MicroPythonMode(editor, view) mm.force_interrupt = False mm.find_device = mock.MagicMock(return_value=('COM0', '12345')) with mock.patch('os.name', 'nt'): mm.add_repl() assert view.show_message.call_count == 0 assert view.add_micropython_repl.call_args[0][0] == 'COM0' assert view.add_micropython_repl.call_args[0][2] is False
def test_micropython_mode_add_plotter(microbit): """ Nothing goes wrong so check the _view.add_micropython_plotter gets the expected argument. """ editor = mock.MagicMock() editor.current_device = microbit view = mock.MagicMock() view.show_message = mock.MagicMock() view.add_micropython_plotter = mock.MagicMock() mm = MicroPythonMode(editor, view) mock_repl_connection = mock.MagicMock() mock_connection_class = mock.MagicMock(return_value=mock_repl_connection) with mock.patch("mu.modes.base.REPLConnection", mock_connection_class): mm.add_plotter() view.show_message.assert_not_called() assert view.add_micropython_plotter.call_args[0][1] == mock_repl_connection mock_repl_connection.open.assert_called_once_with()