blob: 7cc20e7e23c1bbb96342a5d1e5364d93675c6343 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2023 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
'''
This test file contains tests for platform.py module of twister
'''
from contextlib import nullcontext
from unittest import mock
import pytest
from pykwalify.errors import SchemaError
from twisterlib.platform import Platform, Simulator, generate_platforms
TESTDATA_1 = [
(
"""\
identifier: dummy empty
arch: arc
""",
{
'name': 'dummy empty',
'arch': 'arc',
'twister': True,
'ram': 128,
'timeout_multiplier': 1.0,
'ignore_tags': [],
'only_tags': [],
'default': False,
'binaries': [],
'flash': 512,
'supported': set(),
'vendor': '',
'tier': -1,
'type': 'na',
'simulators': [],
'supported_toolchains': [],
'env': [],
'env_satisfied': True
},
'<dummy empty on arc>'
),
(
"""\
identifier: dummy full
arch: riscv
twister: true
ram: 1024
testing:
timeout_multiplier: 2.0
ignore_tags:
- tag1
- tag2
only_tags:
- tag3
default: true
binaries:
- dummy.exe
- dummy.bin
flash: 4096
supported:
- ble
- netif:openthread
- gpio
vendor: vendor1
tier: 1
type: unit
simulation:
- name: nsim
exec: nsimdrv
toolchain:
- zephyr
- llvm
env:
- dummynonexistentvar
""",
{
'name': 'dummy full',
'arch': 'riscv',
'twister': True,
'ram': 1024,
'timeout_multiplier': 2.0,
'ignore_tags': ['tag1', 'tag2'],
'only_tags': ['tag3'],
'default': True,
'binaries': ['dummy.exe', 'dummy.bin'],
'flash': 4096,
'supported': set(['ble', 'netif', 'openthread', 'gpio']),
'vendor': 'vendor1',
'tier': 1,
'type': 'unit',
'simulators': [Simulator({'name': 'nsim', 'exec': 'nsimdrv'})],
'supported_toolchains': ['zephyr', 'llvm', 'cross-compile'],
'env': ['dummynonexistentvar'],
'env_satisfied': False
},
'<dummy full on riscv>'
),
]
# This test is disabled because the Platform loading was changed significantly.
# The test should be updated to reflect the new implementation.
@pytest.mark.parametrize(
'platform_text, expected_data, expected_repr',
TESTDATA_1,
ids=['almost empty specification', 'full specification']
)
def xtest_platform_load(platform_text, expected_data, expected_repr):
platform = Platform()
with mock.patch('builtins.open', mock.mock_open(read_data=platform_text)):
platform.load('dummy.yaml')
for k, v in expected_data.items():
if not hasattr(platform, k):
assert False, f'No key {k} in platform {platform}'
att = getattr(platform, k)
if isinstance(v, list) and not isinstance(att, list):
assert False, f'Value mismatch in key {k} in platform {platform}'
if isinstance(v, list):
assert sorted(att) == sorted(v)
else:
assert att == v
assert platform.__repr__() == expected_repr
TESTDATA_2 = [
(
['m0'],
None,
{
'p1e1/s1', 'p1e2/s1', 'p2/s1', 'p3@A/s2/c1', 'p3@B/s2/c1',
},
),
(
['m0', 'm1'],
None,
{
'p1e1/s1', 'p1e2/s1', 'p2/s1', 'p3@A/s2/c1', 'p3@B/s2/c1',
'p1e1/s1/v1', 'p1e1/s1/v2', 'p1e2/s1/v1', 'p2/s1/v1',
},
),
(
['m0', 'm1', 'm2'],
None,
{
'p1e1/s1', 'p1e2/s1', 'p2/s1', 'p3@A/s2/c1', 'p3@B/s2/c1',
'p1e1/s1/v1', 'p1e1/s1/v2', 'p1e2/s1/v1', 'p2/s1/v1',
'p3@A/s2/c2', 'p3@B/s2/c2', 'p4/s1',
},
),
(
['m0', 'm3'],
Exception("Duplicate platform identifier p1e1/s1 found"),
None,
),
(
['m0', 'm1', 'm4'],
Exception("Duplicate platform identifier p1e2/s1/v1 found"),
None,
),
(
['m0', 'm5'],
SchemaError(), # Unknown message as this is raised externally
None,
),
]
@pytest.mark.parametrize(
'roots, expected_exception, expected_platform_names',
TESTDATA_2,
ids=[
'default board root',
'1 extra board root',
'2 extra board roots',
'1 extra board root, duplicate platform',
'2 extra board roots, duplicate platform',
'1 extra board root, malformed yaml',
]
)
def test_generate_platforms(
tmp_path,
roots,
expected_exception,
expected_platform_names,
):
tmp_files = {
'm0/boards/zephyr/p1/board.yml': """\
boards:
- name: p1e1
vendor: zephyr
socs:
- name: s1
- name: p1e2
vendor: zephyr
socs:
- name: s1
""",
'm0/boards/zephyr/p1/twister.yaml': """\
type: native
arch: x86
variants:
p1e1:
twister: False
p1e2:
sysbuild: True
""",
'm0/boards/zephyr/p2/board.yml': """\
boards:
- name: p2
vendor: zephyr
socs:
- name: s1
""",
'm0/boards/zephyr/p2/p2.yaml': """\
identifier: p2/s1
type: sim
arch: x86
vendor: vendor2
testing:
default: True
""",
'm0/boards/arm/p3/board.yml': """\
board:
name: p3
vendor: arm
revision:
format: letter
default: "A"
revisions:
- name: "A"
- name: "B"
socs:
- name: s2
""",
'm0/boards/arm/p3/twister.yaml': """\
type: unit
arch: arm
vendor: vendor3
sysbuild: True
variants:
p3/s2/c1:
testing:
timeout_multiplier: 2.71828
p3@B/s2/c1:
testing:
timeout_multiplier: 3.14159
""",
'm0/soc/zephyr/soc.yml': """\
family:
- name: zephyr
series:
- name: zephyr_testing
socs:
- name: s1
- name: s2
cpuclusters:
- name: c1
""",
'm1/boards/zephyr/p1e1/board.yml': """\
board:
extend: p1e1
variants:
- name: v1
qualifier: s1
- name: v2
qualifier: s1
""",
'm1/boards/zephyr/p1e1/twister.yaml': """\
variants:
p1e1/s1/v1:
testing:
default: True
""",
'm1/boards/zephyr/p1e2/board.yml': """\
board:
extend: p1e2
variants:
- name: v1
qualifier: s1
""",
'm1/boards/zephyr/p2/board.yml': """\
board:
extend: p2
variants:
- name: v1
qualifier: s1
""",
'm1/boards/zephyr/p2/p2_s1_v1.yaml': """\
identifier: p2/s1/v1
""",
'm2/boards/misc/board.yml': """\
boards:
- extend: p3
- name: p4
vendor: misc
socs:
- name: s1
""",
'm2/boards/misc/twister.yaml': """\
type: qemu
arch: riscv
vendor: vendor4
simulation:
- name: qemu
variants:
p3@A/s2/c2:
sysbuild: False
""",
'm2/soc/zephyr/soc.yml': """\
socs:
- extend: s2
cpuclusters:
- name: c2
""",
'm3/boards/zephyr/p1e1/board.yml': """\
board:
extend: p1e1
""",
'm3/boards/zephyr/p1e1/twister.yaml': """\
variants:
p1e1/s1:
name: Duplicate Platform
""",
'm4/boards/zephyr/p1e2/board.yml': """\
board:
extend: p2
""",
'm4/boards/zephyr/p1e2/p1e2_s1_v1.yaml': """\
identifier: p1e2/s1/v1
""",
'm5/boards/zephyr/p2/p2-2.yaml': """\
testing:
ć#@%!#!#^#@%@:1.0
identifier: p2_2
type: sim
arch: x86
vendor: vendor2
""",
'm5/boards/zephyr/p2/board.yml': """\
board:
extend: p2
""",
}
for filename, content in tmp_files.items():
(tmp_path / filename).parent.mkdir(parents=True, exist_ok=True)
(tmp_path / filename).write_text(content)
roots = list(map(tmp_path.joinpath, roots))
with pytest.raises(type(expected_exception)) if \
expected_exception else nullcontext() as exception:
platforms = list(generate_platforms(board_roots=roots, soc_roots=roots, arch_roots=roots))
if expected_exception:
if expected_exception.args:
assert str(expected_exception) == str(exception.value)
return
platform_names = {platform.name for platform in platforms}
assert len(platforms) == len(platform_names)
assert platform_names == expected_platform_names
expected_data = {
'p1e1/s1': {
'aliases': ['p1e1/s1', 'p1e1'],
# m0/boards/zephyr/p1/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p1/twister.yaml (base + variant)
'twister': False,
'arch': 'x86',
'type': 'native',
},
'p1e2/s1': {
'aliases': ['p1e2/s1', 'p1e2'],
# m0/boards/zephyr/p1/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p1/twister.yaml (base + variant)
'sysbuild': True,
'arch': 'x86',
'type': 'native',
},
'p1e1/s1/v1': {
'aliases': ['p1e1/s1/v1'],
# m0/boards/zephyr/p1/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p1/twister.yaml (base)
# m1/boards/zephyr/p1e1/twister.yaml (variant)
'default': True,
'arch': 'x86',
'type': 'native',
},
'p1e1/s1/v2': {
'aliases': ['p1e1/s1/v2'],
# m0/boards/zephyr/p1/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p1/twister.yaml (base)
'arch': 'x86',
'type': 'native',
},
'p1e2/s1/v1': {
'aliases': ['p1e2/s1/v1'],
# m0/boards/zephyr/p1/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p1/twister.yaml (base)
'arch': 'x86',
'type': 'native',
},
'p2/s1': {
'aliases': ['p2/s1', 'p2'],
# m0/boards/zephyr/p2/board.yml
'vendor': 'zephyr',
# m0/boards/zephyr/p2/p2.yaml
'default': True,
'arch': 'x86',
'type': 'sim',
},
'p2/s1/v1': {
'aliases': ['p2/s1/v1'],
# m0/boards/zephyr/p2/board.yml
'vendor': 'zephyr',
# m1/boards/zephyr/p2/p2_s1_v1.yaml
},
'p3@A/s2/c1': {
'aliases': ['p3@A/s2/c1', 'p3/s2/c1'],
# m0/boards/arm/p3/board.yml
'vendor': 'arm',
# m0/boards/arm/p3/twister.yaml (base + variant)
'sysbuild': True,
'timeout_multiplier': 2.71828,
'arch': 'arm',
'type': 'unit',
},
'p3@B/s2/c1': {
'aliases': ['p3@B/s2/c1'],
# m0/boards/arm/p3/board.yml
'vendor': 'arm',
# m0/boards/arm/p3/twister.yaml (base + variant)
'sysbuild': True,
'timeout_multiplier': 3.14159,
'arch': 'arm',
'type': 'unit',
},
'p3@A/s2/c2': {
'aliases': ['p3@A/s2/c2', 'p3/s2/c2'],
# m0/boards/arm/p3/board.yml
'vendor': 'arm',
# m0/boards/arm/p3/twister.yaml (base)
# m2/boards/misc/twister.yaml (variant)
'sysbuild': False,
'arch': 'arm',
'type': 'unit',
},
'p3@B/s2/c2': {
'aliases': ['p3@B/s2/c2'],
# m0/boards/arm/p3/board.yml
'vendor': 'arm',
# m0/boards/arm/p3/twister.yaml (base)
'sysbuild': True,
'arch': 'arm',
'type': 'unit',
},
'p4/s1': {
'aliases': ['p4/s1', 'p4'],
# m2/boards/misc/board.yml
'vendor': 'misc',
# m2/boards/misc/twister.yaml (base)
'arch': 'riscv',
'type': 'qemu',
'simulators': [Simulator({'name': 'qemu'})],
'simulation': 'qemu',
},
}
init_platform = Platform()
for platform in platforms:
expected_platform_data = expected_data[platform.name]
for attr, default in vars(init_platform).items():
if attr in {'name', 'normalized_name', 'supported_toolchains'}:
continue
expected = expected_platform_data.get(attr, default)
actual = getattr(platform, attr, None)
assert expected == actual, \
f"expected '{platform}.{attr}' to be '{expected}', was '{actual}'"