670b917b4b
This change creates unit tests for the hardwaremap.py module. It achieves 98% coverage. Signed-off-by: Lukasz Mrugala <lukaszx.mrugala@intel.com>
723 lines
19 KiB
Python
723 lines
19 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2023 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
"""
|
|
Tests for hardwaremap.py classes' methods
|
|
"""
|
|
|
|
import mock
|
|
import pytest
|
|
import sys
|
|
|
|
from pathlib import Path
|
|
|
|
from twisterlib.hardwaremap import(
|
|
DUT,
|
|
HardwareMap
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def mocked_hm():
|
|
duts = [
|
|
DUT(platform='p1', id=1, serial='s1', product='pr1', connected=True),
|
|
DUT(platform='p2', id=2, serial='s2', product='pr2', connected=False),
|
|
DUT(platform='p3', id=3, serial='s3', product='pr3', connected=True),
|
|
DUT(platform='p4', id=4, serial='s4', product='pr4', connected=False),
|
|
DUT(platform='p5', id=5, serial='s5', product='pr5', connected=True),
|
|
DUT(platform='p6', id=6, serial='s6', product='pr6', connected=False),
|
|
DUT(platform='p7', id=7, serial='s7', product='pr7', connected=True),
|
|
DUT(platform='p8', id=8, serial='s8', product='pr8', connected=False)
|
|
]
|
|
|
|
hm = HardwareMap(env=mock.Mock())
|
|
hm.duts = duts
|
|
hm.detected = duts[:5]
|
|
|
|
return hm
|
|
|
|
|
|
TESTDATA_1 = [
|
|
(
|
|
{},
|
|
{'baud': 115200, 'lock': mock.ANY, 'flash_timeout': 60},
|
|
'<None (None) on None>'
|
|
),
|
|
(
|
|
{
|
|
'id': 'dummy id',
|
|
'serial': 'dummy serial',
|
|
'serial_baud': 4400,
|
|
'platform': 'dummy platform',
|
|
'product': 'dummy product',
|
|
'serial_pty': 'dummy serial pty',
|
|
'connected': True,
|
|
'runner_params': ['dummy', 'runner', 'params'],
|
|
'pre_script': 'dummy pre script',
|
|
'post_script': 'dummy post script',
|
|
'post_flash_script': 'dummy post flash script',
|
|
'runner': 'dummy runner',
|
|
'flash_timeout': 30,
|
|
'flash_with_test': True
|
|
},
|
|
{
|
|
'lock': mock.ANY,
|
|
'id': 'dummy id',
|
|
'serial': 'dummy serial',
|
|
'baud': 4400,
|
|
'platform': 'dummy platform',
|
|
'product': 'dummy product',
|
|
'serial_pty': 'dummy serial pty',
|
|
'connected': True,
|
|
'runner_params': ['dummy', 'runner', 'params'],
|
|
'pre_script': 'dummy pre script',
|
|
'post_script': 'dummy post script',
|
|
'post_flash_script': 'dummy post flash script',
|
|
'runner': 'dummy runner',
|
|
'flash_timeout': 30,
|
|
'flash_with_test': True
|
|
},
|
|
'<dummy platform (dummy product) on dummy serial>'
|
|
),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'kwargs, expected_dict, expected_repr',
|
|
TESTDATA_1,
|
|
ids=['no information', 'full information']
|
|
)
|
|
def test_dut(kwargs, expected_dict, expected_repr):
|
|
d = DUT(**kwargs)
|
|
|
|
assert d.available
|
|
assert d.counter == 0
|
|
|
|
d.available = False
|
|
d.counter = 1
|
|
|
|
assert not d.available
|
|
assert d.counter == 1
|
|
|
|
assert d.to_dict() == expected_dict
|
|
assert d.__repr__() == expected_repr
|
|
|
|
|
|
TESTDATA_2 = [
|
|
('ghm.yaml', mock.ANY, mock.ANY, [], mock.ANY, mock.ANY, mock.ANY, 0,
|
|
True, True, False, False, False, False, []),
|
|
(None, False, 'hm.yaml', [], mock.ANY, mock.ANY, mock.ANY, 0,
|
|
False, False, True, True, False, False, []),
|
|
(None, True, 'hm.yaml', [], mock.ANY, mock.ANY, ['fix'], 1,
|
|
False, False, True, False, False, True, ['p1', 'p3', 'p5', 'p7']),
|
|
(None, True, 'hm.yaml', ['pX'], mock.ANY, mock.ANY, ['fix'], 1,
|
|
False, False, True, False, False, True, ['pX']),
|
|
(None, True, None, ['p'], 's', None, ['fix'], 1,
|
|
False, False, False, False, True, True, ['p']),
|
|
(None, True, None, ['p'], None, 'spty', ['fix'], 1,
|
|
False, False, False, False, True, True, ['p']),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'generate_hardware_map, device_testing, hardware_map, platform,' \
|
|
' device_serial, device_serial_pty, fixtures,' \
|
|
' return_code, expect_scan, expect_save, expect_load,' \
|
|
' expect_dump, expect_add_device, expect_fixtures, expected_platforms',
|
|
TESTDATA_2,
|
|
ids=['generate hardware map', 'existing hardware map',
|
|
'device testing with hardware map, no platform',
|
|
'device testing with hardware map with platform',
|
|
'device testing with device serial',
|
|
'device testing with device serial pty']
|
|
)
|
|
def test_hardwaremap_discover(
|
|
caplog,
|
|
mocked_hm,
|
|
generate_hardware_map,
|
|
device_testing,
|
|
hardware_map,
|
|
platform,
|
|
device_serial,
|
|
device_serial_pty,
|
|
fixtures,
|
|
return_code,
|
|
expect_scan,
|
|
expect_save,
|
|
expect_load,
|
|
expect_dump,
|
|
expect_add_device,
|
|
expect_fixtures,
|
|
expected_platforms
|
|
):
|
|
def mock_load(*args):
|
|
mocked_hm.platform = platform
|
|
|
|
mocked_hm.scan = mock.Mock()
|
|
mocked_hm.save = mock.Mock()
|
|
mocked_hm.load = mock.Mock(side_effect=mock_load)
|
|
mocked_hm.dump = mock.Mock()
|
|
mocked_hm.add_device = mock.Mock()
|
|
|
|
mocked_hm.options.device_flash_with_test = True
|
|
mocked_hm.options.device_flash_timeout = 15
|
|
mocked_hm.options.pre_script = 'dummy pre script'
|
|
mocked_hm.options.platform = platform
|
|
mocked_hm.options.device_serial = device_serial
|
|
mocked_hm.options.device_serial_pty = device_serial_pty
|
|
mocked_hm.options.device_testing = device_testing
|
|
mocked_hm.options.hardware_map = hardware_map
|
|
mocked_hm.options.persistent_hardware_map = mock.Mock()
|
|
mocked_hm.options.generate_hardware_map = generate_hardware_map
|
|
mocked_hm.options.fixture = fixtures
|
|
|
|
returncode = mocked_hm.discover()
|
|
|
|
assert returncode == return_code
|
|
|
|
if expect_scan:
|
|
mocked_hm.scan.assert_called_once_with(
|
|
persistent=mocked_hm.options.persistent_hardware_map
|
|
)
|
|
if expect_save:
|
|
mocked_hm.save.assert_called_once_with(
|
|
mocked_hm.options.generate_hardware_map
|
|
)
|
|
if expect_load:
|
|
mocked_hm.load.assert_called_once_with(
|
|
mocked_hm.options.hardware_map
|
|
)
|
|
if expect_dump:
|
|
mocked_hm.dump.assert_called_once_with(
|
|
connected_only=True
|
|
)
|
|
if expect_add_device:
|
|
mocked_hm.add_device.assert_called_once()
|
|
|
|
if expect_fixtures:
|
|
assert all(
|
|
[all(
|
|
[fixture in dut.fixtures for fixture in fixtures]
|
|
) for dut in mocked_hm.duts]
|
|
)
|
|
|
|
assert sorted(expected_platforms) == sorted(mocked_hm.options.platform)
|
|
|
|
|
|
def test_hardwaremap_summary(capfd, mocked_hm):
|
|
selected_platforms = ['p0', 'p1', 'p6', 'p7']
|
|
|
|
mocked_hm.summary(selected_platforms)
|
|
|
|
expected = """
|
|
Hardware distribution summary:
|
|
|
|
| Board | ID | Counter |
|
|
|---------|------|-----------|
|
|
| p1 | 1 | 0 |
|
|
| p7 | 7 | 0 |
|
|
"""
|
|
|
|
out, err = capfd.readouterr()
|
|
sys.stdout.write(out)
|
|
sys.stderr.write(err)
|
|
|
|
assert expected in out
|
|
|
|
|
|
TESTDATA_3 = [
|
|
(True),
|
|
(False)
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'is_pty',
|
|
TESTDATA_3,
|
|
ids=['pty', 'not pty']
|
|
)
|
|
def test_hardwaremap_add_device(is_pty):
|
|
hm = HardwareMap(env=mock.Mock())
|
|
|
|
serial = 'dummy'
|
|
platform = 'p0'
|
|
pre_script = 'dummy pre script'
|
|
hm.add_device(serial, platform, pre_script, is_pty)
|
|
|
|
assert len(hm.duts) == 1
|
|
if is_pty:
|
|
assert hm.duts[0].serial_pty == 'dummy' if is_pty else None
|
|
assert hm.duts[0].serial is None
|
|
else:
|
|
assert hm.duts[0].serial_pty is None
|
|
assert hm.duts[0].serial == 'dummy'
|
|
|
|
|
|
def test_hardwaremap_load():
|
|
map_file = \
|
|
"""
|
|
- id: id0
|
|
platform: p0
|
|
product: pr0
|
|
runner: r0
|
|
flash_with_test: True
|
|
flash_timeout: 15
|
|
baud: 14400
|
|
fixtures:
|
|
- dummy fixture 1
|
|
- dummy fixture 2
|
|
connected: True
|
|
serial: 'dummy'
|
|
- id: id1
|
|
platform: p1
|
|
product: pr1
|
|
runner: r1
|
|
connected: True
|
|
serial_pty: 'dummy'
|
|
- id: id2
|
|
platform: p2
|
|
product: pr2
|
|
runner: r2
|
|
connected: True
|
|
"""
|
|
map_filename = 'map-file.yaml'
|
|
|
|
builtin_open = open
|
|
|
|
def mock_open(*args, **kwargs):
|
|
if args[0] == map_filename:
|
|
return mock.mock_open(read_data=map_file)(*args, **kwargs)
|
|
return builtin_open(*args, **kwargs)
|
|
|
|
hm = HardwareMap(env=mock.Mock())
|
|
hm.options.device_flash_timeout = 30
|
|
hm.options.device_flash_with_test = False
|
|
|
|
with mock.patch('builtins.open', mock_open):
|
|
hm.load(map_filename)
|
|
|
|
expected = {
|
|
'id0': {
|
|
'platform': 'p0',
|
|
'product': 'pr0',
|
|
'runner': 'r0',
|
|
'flash_timeout': 15,
|
|
'flash_with_test': True,
|
|
'baud': 14400,
|
|
'fixtures': ['dummy fixture 1', 'dummy fixture 2'],
|
|
'connected': True,
|
|
'serial': 'dummy',
|
|
'serial_pty': None,
|
|
},
|
|
'id1': {
|
|
'platform': 'p1',
|
|
'product': 'pr1',
|
|
'runner': 'r1',
|
|
'flash_timeout': 30,
|
|
'flash_with_test': False,
|
|
'baud': 115200,
|
|
'fixtures': [],
|
|
'connected': True,
|
|
'serial': None,
|
|
'serial_pty': 'dummy',
|
|
},
|
|
}
|
|
|
|
for dut in hm.duts:
|
|
assert dut.id in expected
|
|
assert all([getattr(dut, k) == v for k, v in expected[dut.id].items()])
|
|
|
|
|
|
TESTDATA_4 = [
|
|
(
|
|
True,
|
|
'Linux',
|
|
['<p1 (pr1) on s1>', '<p2 (pr2) on s2>', '<p3 (pr3) on s3>',
|
|
'<p4 (pr4) on s4>', '<p5 (pr5) on s5>',
|
|
'<unknown (TI product) on /dev/serial/by-id/basic-file1>',
|
|
'<unknown (product123) on dummy device>',
|
|
'<unknown (unknown) on /dev/serial/by-id/basic-file2-link>']
|
|
),
|
|
(
|
|
True,
|
|
'nt',
|
|
['<p1 (pr1) on s1>', '<p2 (pr2) on s2>', '<p3 (pr3) on s3>',
|
|
'<p4 (pr4) on s4>', '<p5 (pr5) on s5>',
|
|
'<unknown (TI product) on /dev/serial/by-id/basic-file1>',
|
|
'<unknown (product123) on dummy device>',
|
|
'<unknown (unknown) on /dev/serial/by-id/basic-file2>']
|
|
),
|
|
(
|
|
False,
|
|
'Linux',
|
|
['<p1 (pr1) on s1>', '<p2 (pr2) on s2>', '<p3 (pr3) on s3>',
|
|
'<p4 (pr4) on s4>', '<p5 (pr5) on s5>',
|
|
'<unknown (TI product) on /dev/serial/by-id/basic-file1>',
|
|
'<unknown (product123) on dummy device>',
|
|
'<unknown (unknown) on /dev/serial/by-id/basic-file2>']
|
|
)
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'persistent, system, expected_reprs',
|
|
TESTDATA_4,
|
|
ids=['linux persistent map', 'no map (not linux)', 'no map (nonpersistent)']
|
|
)
|
|
def test_hardwaremap_scan(
|
|
caplog,
|
|
mocked_hm,
|
|
persistent,
|
|
system,
|
|
expected_reprs
|
|
):
|
|
def mock_resolve(path):
|
|
if str(path).endswith('-link'):
|
|
return Path(str(path)[:-5])
|
|
return path
|
|
|
|
def mock_iterdir(path):
|
|
return [
|
|
Path(path / 'basic-file1'),
|
|
Path(path / 'basic-file2-link')
|
|
]
|
|
|
|
mocked_hm.manufacturer = ['dummy manufacturer', 'Texas Instruments']
|
|
mocked_hm.runner_mapping = {
|
|
'dummy runner': ['product[0-9]+',],
|
|
'other runner': ['other TI product', 'TI product']
|
|
}
|
|
|
|
comports_mock = [
|
|
mock.Mock(
|
|
manufacturer='wrong manufacturer',
|
|
location='wrong location',
|
|
serial_number='wrong number',
|
|
product='wrong product',
|
|
device='wrong device'
|
|
),
|
|
mock.Mock(
|
|
manufacturer='dummy manufacturer',
|
|
location='dummy location',
|
|
serial_number='dummy number',
|
|
product=None,
|
|
device='/dev/serial/by-id/basic-file2'
|
|
),
|
|
mock.Mock(
|
|
manufacturer='dummy manufacturer',
|
|
location='dummy location',
|
|
serial_number='dummy number',
|
|
product='product123',
|
|
device='dummy device'
|
|
),
|
|
mock.Mock(
|
|
manufacturer='Texas Instruments',
|
|
location='serial1',
|
|
serial_number='TI1',
|
|
product='TI product',
|
|
device='TI device1'
|
|
),
|
|
mock.Mock(
|
|
manufacturer='Texas Instruments',
|
|
location='serial0',
|
|
serial_number='TI0',
|
|
product='TI product',
|
|
device='/dev/serial/by-id/basic-file1'
|
|
),
|
|
]
|
|
|
|
with mock.patch('platform.system', return_value=system), \
|
|
mock.patch('serial.tools.list_ports.comports',
|
|
return_value=comports_mock), \
|
|
mock.patch('twisterlib.hardwaremap.Path.resolve',
|
|
autospec=True, side_effect=mock_resolve), \
|
|
mock.patch('twisterlib.hardwaremap.Path.iterdir',
|
|
autospec=True, side_effect=mock_iterdir):
|
|
mocked_hm.scan(persistent)
|
|
|
|
assert sorted([d.__repr__() for d in mocked_hm.detected]) == \
|
|
sorted(expected_reprs)
|
|
|
|
assert 'Scanning connected hardware...' in caplog.text
|
|
assert 'Unsupported device (wrong manufacturer): %s' % comports_mock[0] \
|
|
in caplog.text
|
|
|
|
|
|
TESTDATA_5 = [
|
|
(
|
|
None,
|
|
[{
|
|
'platform': 'p1',
|
|
'id': 1,
|
|
'runner': mock.ANY,
|
|
'serial': 's1',
|
|
'product': 'pr1',
|
|
'connected': True
|
|
},
|
|
{
|
|
'platform': 'p2',
|
|
'id': 2,
|
|
'runner': mock.ANY,
|
|
'serial': 's2',
|
|
'product': 'pr2',
|
|
'connected': False
|
|
},
|
|
{
|
|
'platform': 'p3',
|
|
'id': 3,
|
|
'runner': mock.ANY,
|
|
'serial': 's3',
|
|
'product': 'pr3',
|
|
'connected': True
|
|
},
|
|
{
|
|
'platform': 'p4',
|
|
'id': 4,
|
|
'runner': mock.ANY,
|
|
'serial': 's4',
|
|
'product': 'pr4',
|
|
'connected': False
|
|
},
|
|
{
|
|
'platform': 'p5',
|
|
'id': 5,
|
|
'runner': mock.ANY,
|
|
'serial': 's5',
|
|
'product': 'pr5',
|
|
'connected': True
|
|
}]
|
|
),
|
|
(
|
|
'',
|
|
[{
|
|
'serial': 's1',
|
|
'baud': 115200,
|
|
'platform': 'p1',
|
|
'connected': True,
|
|
'id': 1,
|
|
'product': 'pr1',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's2',
|
|
'baud': 115200,
|
|
'platform': 'p2',
|
|
'id': 2,
|
|
'product': 'pr2',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's3',
|
|
'baud': 115200,
|
|
'platform': 'p3',
|
|
'connected': True,
|
|
'id': 3,
|
|
'product': 'pr3',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's4',
|
|
'baud': 115200,
|
|
'platform': 'p4',
|
|
'id': 4,
|
|
'product': 'pr4',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's5',
|
|
'baud': 115200,
|
|
'platform': 'p5',
|
|
'connected': True,
|
|
'id': 5,
|
|
'product': 'pr5',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
}]
|
|
),
|
|
(
|
|
"""
|
|
- id: 4
|
|
platform: p4
|
|
product: pr4
|
|
connected: True
|
|
serial: s4
|
|
- id: 0
|
|
platform: p0
|
|
product: pr0
|
|
connected: True
|
|
serial: s0
|
|
- id: 10
|
|
platform: p10
|
|
product: pr10
|
|
connected: False
|
|
serial: s10
|
|
- id: 5
|
|
platform: p5-5
|
|
product: pr5-5
|
|
connected: True
|
|
serial: s5-5
|
|
""",
|
|
[{
|
|
'id': 0,
|
|
'platform': 'p0',
|
|
'product': 'pr0',
|
|
'connected': False,
|
|
'serial': None
|
|
},
|
|
{
|
|
'id': 4,
|
|
'platform': 'p4',
|
|
'product': 'pr4',
|
|
'connected': True,
|
|
'serial': 's4'
|
|
},
|
|
{
|
|
'id': 5,
|
|
'platform': 'p5-5',
|
|
'product': 'pr5-5',
|
|
'connected': False,
|
|
'serial': None
|
|
},
|
|
{
|
|
'id': 10,
|
|
'platform': 'p10',
|
|
'product': 'pr10',
|
|
'connected': False,
|
|
'serial': None
|
|
},
|
|
{
|
|
'serial': 's1',
|
|
'baud': 115200,
|
|
'platform': 'p1',
|
|
'connected': True,
|
|
'id': 1,
|
|
'product': 'pr1',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's2',
|
|
'baud': 115200,
|
|
'platform': 'p2',
|
|
'id': 2,
|
|
'product': 'pr2',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's3',
|
|
'baud': 115200,
|
|
'platform': 'p3',
|
|
'connected': True,
|
|
'id': 3,
|
|
'product': 'pr3',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
},
|
|
{
|
|
'serial': 's5',
|
|
'baud': 115200,
|
|
'platform': 'p5',
|
|
'connected': True,
|
|
'id': 5,
|
|
'product': 'pr5',
|
|
'lock': mock.ANY,
|
|
'flash_timeout': 60
|
|
}]
|
|
),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'hwm, expected_dump',
|
|
TESTDATA_5,
|
|
ids=['no map', 'empty map', 'map exists']
|
|
)
|
|
def test_hardwaremap_save(mocked_hm, hwm, expected_dump):
|
|
read_mock = mock.mock_open(read_data=hwm)
|
|
write_mock = mock.mock_open()
|
|
|
|
def mock_open(filename, mode):
|
|
if mode == 'r':
|
|
return read_mock()
|
|
elif mode == 'w':
|
|
return write_mock()
|
|
|
|
|
|
mocked_hm.load = mock.Mock()
|
|
mocked_hm.dump = mock.Mock()
|
|
|
|
open_mock = mock.Mock(side_effect=mock_open)
|
|
dump_mock = mock.Mock()
|
|
|
|
with mock.patch('os.path.exists', return_value=hwm is not None), \
|
|
mock.patch('builtins.open', open_mock), \
|
|
mock.patch('twisterlib.hardwaremap.yaml.dump', dump_mock):
|
|
mocked_hm.save('hwm.yaml')
|
|
|
|
dump_mock.assert_called_once_with(expected_dump, mock.ANY, Dumper=mock.ANY,
|
|
default_flow_style=mock.ANY)
|
|
|
|
|
|
TESTDATA_6 = [
|
|
(
|
|
['p1', 'p3', 'p5', 'p7'],
|
|
[],
|
|
True,
|
|
True,
|
|
"""
|
|
| Platform | ID | Serial device |
|
|
|------------|------|-----------------|
|
|
| p1 | 1 | s1 |
|
|
| p3 | 3 | s3 |
|
|
| p5 | 5 | s5 |
|
|
"""
|
|
),
|
|
(
|
|
[],
|
|
['?', '??', '???'],
|
|
False,
|
|
False,
|
|
"""
|
|
| ? | ?? | ??? |
|
|
|-----|------|-------|
|
|
| p1 | 1 | s1 |
|
|
| p2 | 2 | s2 |
|
|
| p3 | 3 | s3 |
|
|
| p4 | 4 | s4 |
|
|
| p5 | 5 | s5 |
|
|
| p6 | 6 | s6 |
|
|
| p7 | 7 | s7 |
|
|
| p8 | 8 | s8 |
|
|
"""
|
|
),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'filtered, header, connected_only, detected, expected_out',
|
|
TESTDATA_6,
|
|
ids=['detected no header', 'all with header']
|
|
)
|
|
def test_hardwaremap_dump(
|
|
capfd,
|
|
mocked_hm,
|
|
filtered,
|
|
header,
|
|
connected_only,
|
|
detected,
|
|
expected_out
|
|
):
|
|
mocked_hm.dump(filtered, header, connected_only, detected)
|
|
|
|
out, err = capfd.readouterr()
|
|
sys.stdout.write(out)
|
|
sys.stderr.write(err)
|
|
|
|
assert out.strip() == expected_out.strip()
|