def test_copy_main_with_python_script(): """ If copy_main is called and there's something in self.python_script, then use microfs to write it to the device's on-board filesystem, followed by a soft-reboot. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) mm.python_script = 'import love' with mock.patch('mu.modes.microbit.microfs') as mock_microfs: mock_microfs.execute.return_value = ('', '') mm.copy_main() serial = mock_microfs.get_serial() expected = [ "fd = open('main.py', 'wb')", "f = fd.write", "f('import love')", "fd.close()", ] mock_microfs.execute.assert_called_once_with(expected, serial) serial.write.call_count == 2 assert serial.write.call_args_list[0][0][0] == b'import microbit\r\n' assert serial.write.call_args_list[1][0][0] == b'microbit.reset()\r\n' # The script is re-set to empty. assert mm.python_script == ''
def test_copy_main_with_python_script_encounters_device_error(): """ If the device returns an error, then copy_main should raise an IOError. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) with mock.patch("mu.modes.microbit.microfs") as mock_microfs: mock_microfs.execute.return_value = ("", "BANG!") with pytest.raises(IOError): mm.copy_main("import love")
def test_copy_main_no_python_script(): """ If copy_main is called and there's nothing in provided script, then don't do anything. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) with mock.patch("mu.modes.microbit.microfs") as mock_microfs: mm.copy_main("") assert mock_microfs.execute.call_count == 0
def test_flash_forced_with_attached_device_as_not_windows( microbit_old_firmware, ): """ Ensure the expected calls are made to DeviceFlasher and a helpful status message is enacted as if not on Windows. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": "1.0", "version": ( "micro:bit v0.0.9-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01" ), "machine": "micro:bit with nRF51822", } mock_timer = mock.MagicMock() mock_timer_class = mock.MagicMock(return_value=mock_timer) mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch( "mu.modes.microbit.uflash.find_microbit", return_value="bar" ), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info ), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True ), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class ), mock.patch( "mu.modes.microbit.sys.platform", "linux" ), mock.patch( "mu.modes.microbit.QTimer", mock_timer_class ): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit_old_firmware mm = MicrobitMode(editor, view) mm.set_buttons = mock.MagicMock() mm.copy_main = mock.MagicMock() mm.flash() assert mm.flash_timer == mock_timer assert editor.show_status_message.call_count == 1 mm.set_buttons.assert_called_once_with(flash=False) mock_flasher_class.assert_called_once_with(["bar"], b"", None) assert mock_flasher.finished.connect.call_count == 0 mock_timer.timeout.connect.assert_called_once_with(mm.flash_finished) mock_timer.setSingleShot.assert_called_once_with(True) mock_timer.start.assert_called_once_with(10000) mock_flasher.on_flash_fail.connect.assert_called_once_with( mm.flash_failed ) mock_flasher.start.assert_called_once_with() assert mm.python_script == b"foo"
def test_flash_device_has_latest_firmware_encounters_serial_problem_unix( microbit, ): """ If copy_main encounters an IOError on unix-y, revert to old-school flashing. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": uflash.MICROPYTHON_VERSION, "version": ( "micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01" ), "machine": "micro:bit with nRF51822", } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) mock_timer = mock.MagicMock() mock_timer_class = mock.MagicMock(return_value=mock_timer) with mock.patch( "mu.modes.microbit.uflash.find_microbit", return_value="bar" ), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info ), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True ), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class ), mock.patch( "mu.modes.microbit.QTimer", mock_timer_class ), mock.patch( "mu.modes.microbit.sys.platform", "linux" ): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit mm = MicrobitMode(editor, view) mm.flash_failed = mock.MagicMock() error = IOError("bang") mm.copy_main = mock.MagicMock(side_effect=error) mm.set_buttons = mock.MagicMock() mm.flash() mm.copy_main.assert_called_once_with() mock_flasher_class.assert_called_once_with(["bar"], b"foo", None) mock_flasher.on_flash_fail.connect.assert_called_once_with( mm.flash_failed ) mock_flasher.start.assert_called_once_with() assert mm.flash_timer == mock_timer mock_timer.timeout.connect.assert_called_once_with(mm.flash_finished) mock_timer.setSingleShot.assert_called_once_with(True) mock_timer.start.assert_called_once_with(10000)
def test_flash_forced_with_attached_device_as_not_windows(): """ Ensure the expected calls are made to DeviceFlasher and a helpful status message is enacted as if not on Windows. """ version_info = { 'sysname': 'microbit', 'nodename': 'microbit', 'release': '1.0', 'version': ("micro:bit v0.0.9-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01"), 'machine': 'micro:bit with nRF51822', } mock_timer = mock.MagicMock() mock_timer_class = mock.MagicMock(return_value=mock_timer) mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch('mu.modes.microbit.uflash.find_microbit', return_value='bar'),\ mock.patch('mu.modes.microbit.microfs.find_microbit', return_value=('COM0', '12345')),\ mock.patch('mu.modes.microbit.microfs.version', return_value=version_info),\ mock.patch('mu.modes.microbit.os.path.exists', return_value=True),\ mock.patch('mu.modes.microbit.DeviceFlasher', mock_flasher_class), \ mock.patch('mu.modes.microbit.sys.platform', 'linux'), \ mock.patch('mu.modes.microbit.QTimer', mock_timer_class): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value='foo') view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = '' mm = MicrobitMode(editor, view) mm.set_buttons = mock.MagicMock() mm.copy_main = mock.MagicMock() mm.flash() assert mm.flash_timer == mock_timer assert editor.show_status_message.call_count == 1 mm.set_buttons.assert_called_once_with(flash=False) mock_flasher_class.assert_called_once_with([ 'bar', ], b'', None) assert mock_flasher.finished.connect.call_count == 0 mock_timer.timeout.connect.assert_called_once_with(mm.flash_finished) mock_timer.setSingleShot.assert_called_once_with(True) mock_timer.start.assert_called_once_with(10000) mock_flasher.on_flash_fail.connect.\ assert_called_once_with(mm.flash_failed) mock_flasher.start.assert_called_once_with() assert mm.python_script == b'foo'
def test_flash_device_has_latest_firmware_encounters_serial_problem_unix(): """ If copy_main encounters an IOError on unix-y, revert to old-school flashing. """ version_info = { 'sysname': 'microbit', 'nodename': 'microbit', 'release': uflash.MICROPYTHON_VERSION, 'version': ("micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01"), 'machine': 'micro:bit with nRF51822', } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) mock_timer = mock.MagicMock() mock_timer_class = mock.MagicMock(return_value=mock_timer) with mock.patch('mu.modes.microbit.uflash.find_microbit', return_value='bar'),\ mock.patch('mu.modes.microbit.microfs.version', return_value=version_info),\ mock.patch('mu.modes.microbit.os.path.exists', return_value=True),\ mock.patch('mu.modes.microbit.DeviceFlasher', mock_flasher_class), \ mock.patch('mu.modes.microbit.QTimer', mock_timer_class), \ mock.patch('mu.modes.microbit.sys.platform', 'linux'): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value='foo') view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = '' mm = MicrobitMode(editor, view) mm.find_device = mock.MagicMock(return_value=('bar', '12345')) mm.flash_failed = mock.MagicMock() error = IOError('bang') mm.copy_main = mock.MagicMock(side_effect=error) mm.set_buttons = mock.MagicMock() mm.flash() mm.copy_main.assert_called_once_with() mock_flasher_class.assert_called_once_with([ 'bar', ], b'foo', None) mock_flasher.on_flash_fail.connect.\ assert_called_once_with(mm.flash_failed) mock_flasher.start.assert_called_once_with() assert mm.flash_timer == mock_timer mock_timer.timeout.connect.assert_called_once_with(mm.flash_finished) mock_timer.setSingleShot.assert_called_once_with(True) mock_timer.start.assert_called_once_with(10000)
def test_flash_with_attached_device_has_old_firmware(microbit): """ If the device has some unknown old firmware, force flash it. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": "1.0", "version": ("v1.9.2-34-gd64154c73 on 2017-09-01"), "machine": "micro:bit with nRF51822", } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch("mu.modes.microbit.uflash.find_microbit", return_value="/path/microbit"), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash_and_send = mock.MagicMock(side_effect=mm.flash_and_send) mm.flash() assert mm.flash_thread == mock_flasher assert editor.show_status_message.call_count == 1 mm.set_buttons.assert_called_once_with(flash=False, repl=False, files=False, plotter=False) mm.flash_and_send.assert_called_once_with(b"foo", "/path/microbit") mock_flasher_class.assert_called_once_with("/path/microbit", path_to_runtime=None, python_script=None) mock_flasher.finished.connect.assert_called_once_with( mm.flash_finished) mock_flasher.on_flash_fail.connect.assert_called_once_with( mm.flash_failed) mock_flasher.start.assert_called_once_with()
def test_flash_with_attached_device_has_old_firmware(): """ If the device has some unknown old firmware, force flash it. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": "1.0", "version": ("v1.9.2-34-gd64154c73 on 2017-09-01"), "machine": "micro:bit with nRF51822", } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch( "mu.modes.microbit.uflash.find_microbit", return_value="bar" ), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info ), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True ), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class ), mock.patch( "mu.modes.microbit.sys.platform", "win32" ): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" mm = MicrobitMode(editor, view) mm.find_device = mock.MagicMock(return_value=("bar", "990112345")) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash() assert mm.flash_thread == mock_flasher assert editor.show_status_message.call_count == 1 mm.set_buttons.assert_called_once_with(flash=False) mock_flasher_class.assert_called_once_with(["bar"], b"", None) mock_flasher.finished.connect.assert_called_once_with( mm.flash_finished ) mock_flasher.on_flash_fail.connect.assert_called_once_with( mm.flash_failed ) mock_flasher.start.assert_called_once_with()
def test_flash_with_attached_device_has_latest_firmware_encounters_problem( microbit, ): """ If copy_main encounters a non-IOError, handle in a helpful manner. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": uflash.MICROPYTHON_VERSION, "version": ( "micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01" ), "machine": "micro:bit with nRF51822", } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch( "mu.modes.microbit.uflash.find_microbit", return_value="bar" ), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info ), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True ), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class ), mock.patch( "mu.modes.microbit.sys.platform", "win32" ): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit mm = MicrobitMode(editor, view) mm.flash_failed = mock.MagicMock() error = ValueError("bang") mm.copy_main = mock.MagicMock(side_effect=error) mm.set_buttons = mock.MagicMock() mm.flash() assert mock_flasher_class.call_count == 0 mm.copy_main.assert_called_once_with() mm.flash_failed.assert_called_once_with(error)
def test_flash_finished_copy_main(): """ Ensure state is set back as expected when the flashing thread is finished. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) mm.python_script = 'foo' mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash_thread = mock.MagicMock() mm.flash_timer = mock.MagicMock() mm.flash_finished() mm.set_buttons.assert_called_once_with(flash=True) editor.show_status_message.assert_called_once_with("Finished flashing.") assert mm.flash_thread is None assert mm.flash_timer is None mm.copy_main.assert_called_once_with()
def test_flash_with_attached_device_has_old_firmware(): """ If the device has some unknown old firmware, force flash it. """ version_info = { 'sysname': 'microbit', 'nodename': 'microbit', 'release': '1.0', 'version': ("v1.9.2-34-gd64154c73 on 2017-09-01"), 'machine': 'micro:bit with nRF51822', } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch('mu.modes.microbit.uflash.find_microbit', return_value='bar'),\ mock.patch('mu.modes.microbit.microfs.find_microbit', return_value=('bar', '12345')),\ mock.patch('mu.modes.microbit.microfs.version', return_value=version_info),\ mock.patch('mu.modes.microbit.os.path.exists', return_value=True),\ mock.patch('mu.modes.microbit.DeviceFlasher', mock_flasher_class), \ mock.patch('mu.modes.microbit.sys.platform', 'win32'): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value='foo') view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = '' mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash() assert mm.flash_thread == mock_flasher assert editor.show_status_message.call_count == 1 mm.set_buttons.assert_called_once_with(flash=False) mock_flasher_class.assert_called_once_with([ 'bar', ], b'', None) mock_flasher.finished.connect.\ assert_called_once_with(mm.flash_finished) mock_flasher.on_flash_fail.connect.\ assert_called_once_with(mm.flash_failed) mock_flasher.start.assert_called_once_with()
def test_flash_with_attached_device_has_latest_firmware_encounters_problem(): """ If copy_main encounters an error, handle in a helpful manner. """ version_info = { 'sysname': 'microbit', 'nodename': 'microbit', 'release': uflash.MICROPYTHON_VERSION, 'version': ("micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01"), 'machine': 'micro:bit with nRF51822', } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch('mu.modes.microbit.uflash.find_microbit', return_value='bar'),\ mock.patch('mu.modes.microbit.microfs.find_microbit', return_value=('bar', '12345')),\ mock.patch('mu.modes.microbit.microfs.version', return_value=version_info),\ mock.patch('mu.modes.microbit.os.path.exists', return_value=True),\ mock.patch('mu.modes.microbit.DeviceFlasher', mock_flasher_class), \ mock.patch('mu.modes.microbit.sys.platform', 'win32'): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value='foo') view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = '' mm = MicrobitMode(editor, view) mm.flash_failed = mock.MagicMock() error = IOError('bang') mm.copy_main = mock.MagicMock(side_effect=error) mm.set_buttons = mock.MagicMock() mm.flash() assert mock_flasher_class.call_count == 0 mm.copy_main.assert_called_once_with() mm.flash_failed.assert_called_once_with(error)
def test_flash_finished_no_copy(): """ Ensure state is set back as expected when the flashing thread is finished. If no python_script is set, then copy_main is NOT called. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash_thread = mock.MagicMock() mm.flash_finished() mm.set_buttons.assert_called_once_with(flash=True, repl=True, files=True, plotter=True) editor.show_status_message.assert_called_once_with("Finished flashing.") assert mm.flash_thread is None assert mm.copy_main.call_count == 0
def test_flash_with_attached_device_has_latest_firmware(microbit): """ There's NO need to use the DeviceFlasher if the board already has the latest firmware. In which case, just call copy_main. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": uflash.MICROPYTHON_VERSION, "version": ( "micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01" ), "machine": "micro:bit with nRF51822", } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch( "mu.modes.microbit.uflash.find_microbit", return_value="bar" ), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info ), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True ), mock.patch( "mu.modes.microbit.DeviceFlasher", mock_flasher_class ), mock.patch( "mu.modes.microbit.sys.platform", "win32" ): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash() assert mock_flasher_class.call_count == 0 mm.copy_main.assert_called_once_with()
def test_flash_with_attached_device_has_latest_firmware(): """ There's NO need to use the DeviceFlasher if the board already has the latest firmware. In which case, just call copy_main. """ version_info = { 'sysname': 'microbit', 'nodename': 'microbit', 'release': uflash.MICROPYTHON_VERSION, 'version': ("micro:bit v0.1.0-b'e10a5ff' on 2018-6-8; MicroPython " "v1.9.2-34-gd64154c73 on 2017-09-01"), 'machine': 'micro:bit with nRF51822', } mock_flasher = mock.MagicMock() mock_flasher_class = mock.MagicMock(return_value=mock_flasher) with mock.patch('mu.modes.microbit.uflash.find_microbit', return_value='bar'),\ mock.patch('mu.modes.microbit.microfs.find_microbit', return_value=('bar', '12345')),\ mock.patch('mu.modes.microbit.microfs.version', return_value=version_info),\ mock.patch('mu.modes.microbit.os.path.exists', return_value=True),\ mock.patch('mu.modes.microbit.DeviceFlasher', mock_flasher_class), \ mock.patch('mu.modes.microbit.sys.platform', 'win32'): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value='foo') view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = '' mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash() assert mock_flasher_class.call_count == 0 mm.copy_main.assert_called_once_with()
def test_flash_finished_copy_main_encounters_error(): """ If copy_main encounters an error, flash_failed is called. """ view = mock.MagicMock() editor = mock.MagicMock() mm = MicrobitMode(editor, view) mm.flash_failed = mock.MagicMock() mm.python_script = 'foo' error = IOError('boom') mm.copy_main = mock.MagicMock(side_effect=error) mm.set_buttons = mock.MagicMock() mm.flash_thread = mock.MagicMock() mm.flash_timer = mock.MagicMock() mm.flash_finished() mm.set_buttons.assert_called_once_with(flash=True) editor.show_status_message.assert_called_once_with("Finished flashing.") assert mm.flash_thread is None assert mm.flash_timer is None mm.copy_main.assert_called_once_with() mm.flash_failed.assert_called_once_with(error)
def test_flash_with_attached_device_has_latest_firmware_v2(microbit): """ There's NO need to use the DeviceFlasher if the board already has the latest firmware. In which case, just call copy_main. """ version_info = { "sysname": "microbit", "nodename": "microbit", "release": uflash.MICROPYTHON_V2_VERSION, "version": ("micro:bit v2.0.0-beta.3+d6c01d0 on 2020-12-21; " "MicroPython v1.13 on 2020-12-21"), "machine": "micro:bit with nRF52833", } with mock.patch("mu.modes.microbit.uflash.find_microbit", return_value="/path/microbit"), mock.patch( "mu.modes.microbit.microfs.version", return_value=version_info), mock.patch( "mu.modes.microbit.os.path.exists", return_value=True): view = mock.MagicMock() view.current_tab.text = mock.MagicMock(return_value="foo") view.show_message = mock.MagicMock() editor = mock.MagicMock() editor.minify = False editor.microbit_runtime = "" editor.current_device = microbit mm = MicrobitMode(editor, view) mm.copy_main = mock.MagicMock() mm.set_buttons = mock.MagicMock() mm.flash_start = mock.MagicMock() mm.flash() assert mm.flash_start.call_count == 0 mm.copy_main.assert_called_once_with(b"foo")