1- import pytest
2- from unittest import mock
31from pathlib import Path
4- from mpflash .mpremoteboard import MPRemoteBoard
2+ from unittest import mock
3+
4+ import pytest
5+
56from mpflash .flash .uf2 import flash_uf2
7+ from mpflash .mpremoteboard import MPRemoteBoard
68
79
810@pytest .fixture
@@ -11,6 +13,8 @@ def mock_mcu():
1113 mcu .port = "rp2"
1214 mcu .board = "test_board"
1315 mcu .serialport = "COM3"
16+ mcu .run_command = mock .Mock () # Add run_command method
17+ mcu .wait_for_restart = mock .Mock () # Add wait_for_restart method
1418 return mcu
1519
1620
@@ -28,7 +32,10 @@ def mock_erase_file():
2832def mock_destination ():
2933 destination = mock .Mock (spec = Path )
3034 destination .exists .return_value = True
31- # (destination / "INFO_UF2.TXT").exists.return_value = True
35+ # Mock the path operation (destination / "INFO_UF2.TXT").exists()
36+ info_file = mock .Mock ()
37+ info_file .exists .return_value = True
38+ destination .__truediv__ = mock .Mock (return_value = info_file )
3239 return destination
3340
3441
@@ -64,9 +71,64 @@ def test_flash_uf2_board_not_in_bootloader(mock_mcu, mock_fw_file):
6471# assert result == mock_mcu
6572
6673
74+ def test_flash_uf2_erase_fallback_samd (mock_mcu , mock_fw_file , mock_destination ):
75+ """Test that SAMD port uses mpremote rm -r :/ for erase after flashing"""
76+ mock_mcu .port = "samd"
77+ mock_mcu .run_command .return_value = (0 , ["" ]) # Successful erase
78+
79+ with (
80+ mock .patch ("mpflash.flash.uf2.waitfor_uf2" , return_value = mock_destination ),
81+ mock .patch ("mpflash.flash.uf2.copy_firmware_to_uf2" ),
82+ mock .patch ("mpflash.flash.uf2.dismount_uf2_linux" ),
83+ mock .patch ("mpflash.flash.uf2.get_board_id" , return_value = "test_board_id" ),
84+ ):
85+ result = flash_uf2 (mock_mcu , mock_fw_file , erase = True )
86+
87+ # Verify that run_command was called with rm -r :/ after flashing
88+ mock_mcu .run_command .assert_called_with (["rm" , "-r" , ":/" ], timeout = 30 , resume = True )
89+ assert result == mock_mcu
90+
91+
92+ def test_flash_uf2_erase_fallback_failed (mock_mcu , mock_fw_file , mock_destination ):
93+ """Test that failed mpremote erase is logged but doesn't stop flashing"""
94+ mock_mcu .port = "samd"
95+ mock_mcu .run_command .return_value = (1 , ["Error message" ]) # Failed erase
96+
97+ with (
98+ mock .patch ("mpflash.flash.uf2.waitfor_uf2" , return_value = mock_destination ),
99+ mock .patch ("mpflash.flash.uf2.copy_firmware_to_uf2" ),
100+ mock .patch ("mpflash.flash.uf2.dismount_uf2_linux" ),
101+ mock .patch ("mpflash.flash.uf2.get_board_id" , return_value = "test_board_id" ),
102+ ):
103+ result = flash_uf2 (mock_mcu , mock_fw_file , erase = True )
104+
105+ # Verify that run_command was called with rm -r :/ after flashing
106+ mock_mcu .run_command .assert_called_with (["rm" , "-r" , ":/" ], timeout = 30 , resume = True )
107+ # Should still complete flashing even if erase failed
108+ assert result == mock_mcu
109+
110+
67111def test_flash_uf2_erase_not_supported (mock_mcu , mock_fw_file ):
68112 mock_mcu .port = "unsupported_erase_port"
69113 with mock .patch ("mpflash.flash.uf2.waitfor_uf2" , return_value = None ):
70114 with pytest .raises (KeyError ):
71115 result = flash_uf2 (mock_mcu , mock_fw_file , erase = True )
72116 assert result is None
117+
118+
119+ def test_flash_uf2_no_erase_command_when_erase_false (mock_mcu , mock_fw_file , mock_destination ):
120+ """Test that mpremote rm command is not called when erase=False"""
121+ mock_mcu .port = "samd"
122+ mock_mcu .run_command = mock .Mock ()
123+
124+ with (
125+ mock .patch ("mpflash.flash.uf2.waitfor_uf2" , return_value = mock_destination ),
126+ mock .patch ("mpflash.flash.uf2.copy_firmware_to_uf2" ),
127+ mock .patch ("mpflash.flash.uf2.dismount_uf2_linux" ),
128+ mock .patch ("mpflash.flash.uf2.get_board_id" , return_value = "test_board_id" ),
129+ ):
130+ result = flash_uf2 (mock_mcu , mock_fw_file , erase = False )
131+
132+ # Verify that run_command was NOT called
133+ mock_mcu .run_command .assert_not_called ()
134+ assert result == mock_mcu
0 commit comments