diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index aeb252f872060f..9ec0eade2153ca 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -460,14 +460,20 @@ def monitor_serial(self, ser, halt_event, harness): def device_is_available(self, instance): device = instance.platform.name fixture = instance.testsuite.harness_config.get("fixture") - dut_found = False + duts_found = [] for d in self.duts: if fixture and fixture not in map(lambda f: f.split(sep=':')[0], d.fixtures): continue if d.platform != device or (d.serial is None and d.serial_pty is None): continue - dut_found = True + duts_found.append(d) + + if not duts_found: + raise TwisterException(f"No device to serve as {device} platform.") + + # Select an available DUT with less failures + for d in sorted(duts_found, key=lambda _dut: _dut.failures): d.lock.acquire() avail = False if d.available: @@ -480,9 +486,6 @@ def device_is_available(self, instance): if avail: return d - if not dut_found: - raise TwisterException(f"No device to serve as {device} platform.") - return None def make_dut_available(self, dut): diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index ec4db7859c5804..b857ae3cc20a48 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -738,6 +738,7 @@ def test_devicehandler_monitor_serial( fixtures=[], platform='dummy_platform', available=1, + failures=0, counter_increment=mock.Mock(), counter=0 ), @@ -745,6 +746,7 @@ def test_devicehandler_monitor_serial( fixtures=['dummy fixture'], platform='another_platform', available=1, + failures=0, counter_increment=mock.Mock(), counter=0 ), @@ -754,6 +756,7 @@ def test_devicehandler_monitor_serial( serial_pty=None, serial=None, available=1, + failures=0, counter_increment=mock.Mock(), counter=0 ), @@ -762,12 +765,73 @@ def test_devicehandler_monitor_serial( platform='dummy_platform', serial_pty=mock.Mock(), available=1, + failures=0, + counter_increment=mock.Mock(), + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=1, + failures=0, counter_increment=mock.Mock(), counter=0 ) ], 3 ), + ( + 'dummy_platform', + 'dummy fixture', + [ + mock.Mock( + fixtures=[], + platform='dummy_platform', + available=1, + failures=0, + counter_increment=mock.Mock(), + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='another_platform', + available=1, + failures=0, + counter_increment=mock.Mock(), + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=None, + serial=None, + available=1, + failures=0, + counter_increment=mock.Mock(), + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=1, + failures=1, + counter_increment=mock.Mock(), + counter=0 + ), + mock.Mock( + fixtures=['dummy fixture'], + platform='dummy_platform', + serial_pty=mock.Mock(), + available=1, + failures=0, + counter_increment=mock.Mock(), + counter=0 + ) + ], + 4 + ), ( 'dummy_platform', 'dummy fixture', @@ -783,6 +847,7 @@ def test_devicehandler_monitor_serial( platform='dummy_platform', serial_pty=mock.Mock(), counter_increment=mock.Mock(), + failures=0, available=0 ), mock.Mock( @@ -790,6 +855,7 @@ def test_devicehandler_monitor_serial( platform='dummy_platform', serial_pty=mock.Mock(), counter_increment=mock.Mock(), + failures=0, available=0 ), mock.Mock( @@ -797,6 +863,7 @@ def test_devicehandler_monitor_serial( platform='dummy_platform', serial=mock.Mock(), counter_increment=mock.Mock(), + failures=0, available=0 ), mock.Mock( @@ -804,6 +871,7 @@ def test_devicehandler_monitor_serial( platform='dummy_platform', serial=mock.Mock(), counter_increment=mock.Mock(), + failures=0, available=0 ) ], @@ -814,7 +882,9 @@ def test_devicehandler_monitor_serial( @pytest.mark.parametrize( 'platform_name, fixture, duts, expected', TESTDATA_10, - ids=['one good dut', 'exception - no duts', 'no available duts'] + ids=['two good duts, select the first one', + 'two duts, the first was failed once, select the second not failed', + 'exception - no duts', 'no available duts'] ) def test_devicehandler_device_is_available( mocked_instance,