summaryrefslogtreecommitdiff
path: root/test/hil/test_hil_select.py
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-07-31 23:17:36 +0700
committerGitHub <[email protected]>2026-07-31 23:17:36 +0700
commitf3021b337fcea154b898489c417d428c92f88e92 (patch)
tree7bcbffce06f8e7cf1217fc8749aeffa4cd1b64a0 /test/hil/test_hil_select.py
parenteef5af86aa26fe3d72e41156a586a6ed3ffce9f8 (diff)
test/hil: fold openocd_wch into openocd, verify per board, resolve firmware by flasher extension (#3804)
test/hil: one openocd flasher, per-board verify and firmware extension The four WCH boards move to `openocd`, leaving one flasher for all. `verify` is now a per-board opt-out, not dropped fleet-wide: WCH cannot read flash back over the WCH-Link sdi transport; the other seven openocd boards can, and say so explicitly. FLASHER_SUFFIX decides each flasher's extension once — find_firmware returns the full path and the flashers pass it through, so a build with only the wrong artifact is skipped rather than failed mid-flash. --skip-flash bypasses the filter. rescue_openocd() power-on-resets a wedged RP2040/RP2350 via its Rescue DP from the flash retry; the probe has no reset line. Drops unused openocd_adi, stflash, wlink_rs and uniflash, parks the unstable ra6m5_ek, and tests that every roster flasher name dispatches.
Diffstat (limited to 'test/hil/test_hil_select.py')
-rw-r--r--test/hil/test_hil_select.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/test/hil/test_hil_select.py b/test/hil/test_hil_select.py
index 6a2bf6210..5e6b16759 100644
--- a/test/hil/test_hil_select.py
+++ b/test/hil/test_hil_select.py
@@ -9,6 +9,7 @@ import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import hil_flash
import hil_select
from hil_examples import device_tests, dual_tests, host_test
@@ -26,6 +27,19 @@ def real_rosters():
return rosters
+def roster_flashers():
+ """(roster path, board) for every board in the live rosters, `boards-skip`
+ included: a parked board's flasher name must still dispatch, so that unparking it
+ is not what discovers the name went stale."""
+ for name in ('tinyusb.json', 'hfp.json'):
+ path = os.path.join(REPO, 'test/hil', name)
+ with open(path) as f:
+ cfg = json.load(f)
+ for key in ('boards', 'boards-skip'):
+ for b in cfg.get(key, []):
+ yield f'test/hil/{name}', b
+
+
def on_roster(tc, *names):
"""The subset of `names` currently in the live rig rosters, skipping the test
when none are. Parking/unparking a board is routine rig maintenance and must not
@@ -538,5 +552,30 @@ class TestPortWithoutFamilyIsFull(unittest.TestCase):
self.assertTrue(any('no board family' in r for r in s['reasons']), s['reasons'])
+class TestRosterFlashersDispatch(unittest.TestCase):
+ """hil_test and hil_pool_check resolve a board's flasher with a bare
+ getattr(hil_flash, f'flash_{name}'), and hil_test does it inside a redirect_stdout —
+ so a renamed or typo'd roster name raises an AttributeError whose output is swallowed,
+ with nothing pointing at the roster as the thing to edit. Renaming a flash_*/reset_*
+ pair without updating every roster must fail here instead."""
+
+ def test_flash_and_reset_exist_for_every_roster_flasher(self):
+ for path, board in roster_flashers():
+ name = board['flasher']['name'].lower()
+ for fn in (f'flash_{name}', f'reset_{name}'):
+ self.assertTrue(callable(getattr(hil_flash, fn, None)),
+ f'{path}: {board["name"]} uses flasher "{name}" '
+ f'but hil_flash.{fn} does not exist')
+
+ def test_firmware_suffix_known_for_every_roster_flasher(self):
+ """find_firmware falls back to accepting .elf-or-.bin when a flasher is missing
+ from FLASHER_SUFFIX, silently restoring the mismatch that map exists to catch."""
+ for path, board in roster_flashers():
+ name = board['flasher']['name'].lower()
+ self.assertIn(name, hil_flash.FLASHER_SUFFIX,
+ f'{path}: {board["name"]} uses flasher "{name}" '
+ f'with no hil_flash.FLASHER_SUFFIX entry')
+
+
if __name__ == '__main__':
unittest.main(verbosity=1)