scripts: twisterlib: Enable multiple simulator support in twister
This change introduces the ability in twister to select which emulation/simulation tool to use on the command line. If none is specified, it will select the first in the list. Signed-off-by: Wilfried Chauveau <wilfried.chauveau@arm.com>
This commit is contained in:
parent
f0646d3da4
commit
7cc70f01f1
14 changed files with 193 additions and 89 deletions
|
@ -151,7 +151,23 @@ name:
|
|||
type:
|
||||
Type of the board or configuration, currently we support 2 types: mcu, qemu
|
||||
simulation:
|
||||
Simulator used to simulate the platform, e.g. qemu.
|
||||
Simulator(s) used to simulate the platform, e.g. qemu.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
simulation:
|
||||
- name: qemu
|
||||
- name: armfvp
|
||||
exec: FVP_Some_Platform
|
||||
- name: custom
|
||||
exec: AnotherBinary
|
||||
|
||||
By default, tests will be executed using the first entry in the simulation array. Another
|
||||
simulation can be selected with ``--simulation <simulation_name>``.
|
||||
The ``exec`` attribute is optional. If it is set but the required simulator is not available, the
|
||||
tests will be built only.
|
||||
If it is not set and the required simulator is not available the tests will fail to run.
|
||||
The simulation name must match one of the element of ``SUPPORTED_EMU_PLATFORMS``.
|
||||
arch:
|
||||
Architecture of the board
|
||||
toolchain:
|
||||
|
@ -919,8 +935,9 @@ To use this type of simulation, add the following properties to
|
|||
|
||||
.. code-block:: yaml
|
||||
|
||||
simulation: custom
|
||||
simulation_exec: <name_of_emu_binary>
|
||||
simulation:
|
||||
- name: custom
|
||||
exec: <name_of_emu_binary>
|
||||
|
||||
This tells Twister that the board is using a custom emulator called ``<name_of_emu_binary>``,
|
||||
make sure this binary exists in the PATH.
|
||||
|
|
20
scripts/pylib/twister/twisterlib/constants.py
Normal file
20
scripts/pylib/twister/twisterlib/constants.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
SUPPORTED_SIMS = [
|
||||
"mdb-nsim",
|
||||
"nsim",
|
||||
"renode",
|
||||
"qemu",
|
||||
"tsim",
|
||||
"armfvp",
|
||||
"xt-sim",
|
||||
"native",
|
||||
"custom",
|
||||
"simics",
|
||||
]
|
||||
SUPPORTED_SIMS_IN_PYTEST = ['native', 'qemu']
|
||||
SUPPORTED_SIMS_WITH_EXEC = ['nsim', 'mdb-nsim', 'renode', 'tsim', 'native', 'simics', 'custom']
|
|
@ -20,6 +20,7 @@ from importlib import metadata
|
|||
from pathlib import Path
|
||||
from typing import Generator, List
|
||||
|
||||
from twisterlib.constants import SUPPORTED_SIMS
|
||||
from twisterlib.coverage import supported_coverage_formats
|
||||
|
||||
logger = logging.getLogger('twister')
|
||||
|
@ -71,7 +72,7 @@ def norm_path(astring):
|
|||
return newstring
|
||||
|
||||
|
||||
def add_parse_arguments(parser = None):
|
||||
def add_parse_arguments(parser = None) -> argparse.ArgumentParser:
|
||||
if parser is None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
|
@ -180,6 +181,13 @@ Artificially long but functional example:
|
|||
--device-testing
|
||||
""")
|
||||
|
||||
run_group_option.add_argument(
|
||||
"--simulation", dest="sim_name", choices=SUPPORTED_SIMS,
|
||||
help="Selects which simulation to use. Must match one of the names defined in the board's "
|
||||
"manifest. If multiple simulator are specified in the selected board and this "
|
||||
"argument is not passed, then the first simulator is selected.")
|
||||
|
||||
|
||||
device.add_argument("--device-serial",
|
||||
help="""Serial device for accessing the board
|
||||
(e.g., /dev/ttyACM0)
|
||||
|
@ -811,7 +819,7 @@ structure in the main Zephyr tree: boards/<vendor>/<board_name>/""")
|
|||
return parser
|
||||
|
||||
|
||||
def parse_arguments(parser, args, options = None, on_init=True):
|
||||
def parse_arguments(parser: argparse.ArgumentParser, args, options = None, on_init=True) -> argparse.Namespace:
|
||||
if options is None:
|
||||
options = parser.parse_args(args)
|
||||
|
||||
|
@ -958,7 +966,7 @@ def strip_ansi_sequences(s: str) -> str:
|
|||
|
||||
class TwisterEnv:
|
||||
|
||||
def __init__(self, options, default_options=None) -> None:
|
||||
def __init__(self, options : argparse.Namespace, default_options=None) -> None:
|
||||
self.version = "Unknown"
|
||||
self.toolchain = None
|
||||
self.commit_date = "Unknown"
|
||||
|
|
|
@ -49,9 +49,6 @@ except ImportError as capture_error:
|
|||
logger = logging.getLogger('twister')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
SUPPORTED_SIMS = ["mdb-nsim", "nsim", "renode", "qemu", "tsim", "armfvp", "xt-sim", "native", "custom", "simics"]
|
||||
SUPPORTED_SIMS_IN_PYTEST = ['native', 'qemu']
|
||||
|
||||
|
||||
def terminate_process(proc):
|
||||
"""
|
||||
|
@ -242,6 +239,7 @@ class BinaryHandler(Handler):
|
|||
self.terminate(proc)
|
||||
|
||||
def _create_command(self, robot_test):
|
||||
|
||||
if robot_test:
|
||||
keywords = os.path.join(self.options.coverage_basedir, 'tests/robot/common.robot')
|
||||
elf = os.path.join(self.build_dir, "zephyr/zephyr.elf")
|
||||
|
@ -263,8 +261,14 @@ class BinaryHandler(Handler):
|
|||
"--variable", "RESC:@" + resc,
|
||||
"--variable", "UART:" + uart]
|
||||
elif self.call_make_run:
|
||||
command = [self.generator_cmd, "-C", self.get_default_domain_build_dir(), "run"]
|
||||
if self.options.sim_name:
|
||||
target = f"run_{self.options.sim_name}"
|
||||
else:
|
||||
target = "run"
|
||||
|
||||
command = [self.generator_cmd, "-C", self.get_default_domain_build_dir(), target]
|
||||
elif self.instance.testsuite.type == "unit":
|
||||
assert self.binary, "Missing binary in unit testsuite."
|
||||
command = [self.binary]
|
||||
else:
|
||||
binary = os.path.join(self.get_default_domain_build_dir(), "zephyr", "zephyr.exe")
|
||||
|
|
|
@ -20,10 +20,10 @@ from pytest import ExitCode
|
|||
from twisterlib.reports import ReportStatus
|
||||
from twisterlib.error import ConfigurationError, StatusAttributeError
|
||||
from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED
|
||||
from twisterlib.handlers import Handler, terminate_process, SUPPORTED_SIMS_IN_PYTEST
|
||||
from twisterlib.handlers import Handler, terminate_process
|
||||
from twisterlib.statuses import TwisterStatus
|
||||
from twisterlib.testinstance import TestInstance
|
||||
|
||||
from twisterlib.constants import SUPPORTED_SIMS_IN_PYTEST
|
||||
|
||||
logger = logging.getLogger('twister')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
|
|
@ -2,16 +2,43 @@
|
|||
# vim: set syntax=python ts=4 :
|
||||
#
|
||||
# Copyright (c) 2018-2022 Intel Corporation
|
||||
# Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import scl
|
||||
from twisterlib.environment import ZEPHYR_BASE
|
||||
from twisterlib.constants import SUPPORTED_SIMS
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('twister')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
class Simulator:
|
||||
"""Class representing a simulator"""
|
||||
|
||||
def __init__(self, data: dict[str, str]):
|
||||
assert "name" in data
|
||||
assert data["name"] in SUPPORTED_SIMS
|
||||
self.name = data["name"]
|
||||
self.exec = data.get("exec")
|
||||
|
||||
def is_runnable(self) -> bool:
|
||||
return not bool(self.exec) or bool(shutil.which(self.exec))
|
||||
|
||||
def __str__(self):
|
||||
return f"Simulator(name: {self.name}, exec: {self.exec})"
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Simulator):
|
||||
return self.name == other.name and self.exec == other.exec
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class Platform:
|
||||
"""Class representing metadata for a particular platform
|
||||
|
||||
|
@ -46,8 +73,8 @@ class Platform:
|
|||
self.vendor = ""
|
||||
self.tier = -1
|
||||
self.type = "na"
|
||||
self.simulation = "na"
|
||||
self.simulation_exec = None
|
||||
self.simulators: list[Simulator] = []
|
||||
self.simulation: str = "na"
|
||||
self.supported_toolchains = []
|
||||
self.env = []
|
||||
self.env_satisfied = True
|
||||
|
@ -103,8 +130,12 @@ class Platform:
|
|||
self.vendor = board.vendor
|
||||
self.tier = variant_data.get("tier", data.get("tier", self.tier))
|
||||
self.type = variant_data.get('type', data.get('type', self.type))
|
||||
self.simulation = variant_data.get('simulation', data.get('simulation', self.simulation))
|
||||
self.simulation_exec = variant_data.get('simulation_exec', data.get('simulation_exec', self.simulation_exec))
|
||||
|
||||
self.simulators = [Simulator(data) for data in variant_data.get('simulation', data.get('simulation', self.simulators))]
|
||||
default_sim = self.simulator_by_name(None)
|
||||
if default_sim:
|
||||
self.simulation = default_sim.name
|
||||
|
||||
self.supported_toolchains = variant_data.get("toolchain", data.get("toolchain", []))
|
||||
if self.supported_toolchains is None:
|
||||
self.supported_toolchains = []
|
||||
|
@ -138,5 +169,11 @@ class Platform:
|
|||
if not os.environ.get(env, None):
|
||||
self.env_satisfied = False
|
||||
|
||||
def simulator_by_name(self, sim_name: str | None) -> Simulator | None:
|
||||
if sim_name:
|
||||
return next(filter(lambda s: s.name == sim_name, iter(self.simulators)), None)
|
||||
else:
|
||||
return next(iter(self.simulators), None)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s on %s>" % (self.name, self.arch)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
# Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from __future__ import annotations
|
||||
|
@ -31,8 +33,8 @@ class Quarantine:
|
|||
for quarantine_file in quarantine_list:
|
||||
self.quarantine.extend(QuarantineData.load_data_from_yaml(quarantine_file))
|
||||
|
||||
def get_matched_quarantine(self, testname, platform, architecture, simulation):
|
||||
qelem = self.quarantine.get_matched_quarantine(testname, platform, architecture, simulation)
|
||||
def get_matched_quarantine(self, testname, platform, architecture, simulator):
|
||||
qelem = self.quarantine.get_matched_quarantine(testname, platform, architecture, simulator)
|
||||
if qelem:
|
||||
logger.debug('%s quarantined with reason: %s' % (testname, qelem.comment))
|
||||
return qelem.comment
|
||||
|
@ -111,7 +113,7 @@ class QuarantineData:
|
|||
scenario: str,
|
||||
platform: str,
|
||||
architecture: str,
|
||||
simulation: str) -> QuarantineElement | None:
|
||||
simulator_name: str) -> QuarantineElement | None:
|
||||
"""Return quarantine element if test is matched to quarantine rules"""
|
||||
for qelem in self.qlist:
|
||||
matched: bool = False
|
||||
|
@ -125,7 +127,7 @@ class QuarantineData:
|
|||
and (matched := _is_element_matched(architecture, qelem.re_architectures)) is False):
|
||||
continue
|
||||
if (qelem.simulations
|
||||
and (matched := _is_element_matched(simulation, qelem.re_simulations)) is False):
|
||||
and (matched := _is_element_matched(simulator_name, qelem.re_simulations)) is False):
|
||||
continue
|
||||
|
||||
if matched:
|
||||
|
|
|
@ -11,7 +11,6 @@ import os
|
|||
import hashlib
|
||||
import random
|
||||
import logging
|
||||
import shutil
|
||||
import glob
|
||||
import csv
|
||||
|
||||
|
@ -28,8 +27,11 @@ from twisterlib.handlers import (
|
|||
QEMUHandler,
|
||||
QEMUWinHandler,
|
||||
DeviceHandler,
|
||||
)
|
||||
from twisterlib.constants import (
|
||||
SUPPORTED_SIMS,
|
||||
SUPPORTED_SIMS_IN_PYTEST,
|
||||
SUPPORTED_SIMS_WITH_EXEC,
|
||||
)
|
||||
|
||||
logger = logging.getLogger('twister')
|
||||
|
@ -211,12 +213,13 @@ class TestInstance:
|
|||
|
||||
options = env.options
|
||||
common_args = (options, env.generator_cmd, not options.disable_suite_name_check)
|
||||
simulator = self.platform.simulator_by_name(options.sim_name)
|
||||
if options.device_testing:
|
||||
handler = DeviceHandler(self, "device", *common_args)
|
||||
handler.call_make_run = False
|
||||
handler.ready = True
|
||||
elif self.platform.simulation != "na":
|
||||
if self.platform.simulation == "qemu":
|
||||
elif simulator:
|
||||
if simulator.name == "qemu":
|
||||
if os.name != "nt":
|
||||
handler = QEMUHandler(self, "qemu", *common_args)
|
||||
else:
|
||||
|
@ -224,10 +227,9 @@ class TestInstance:
|
|||
handler.args.append(f"QEMU_PIPE={handler.get_fifo()}")
|
||||
handler.ready = True
|
||||
else:
|
||||
handler = SimulationHandler(self, self.platform.simulation, *common_args)
|
||||
handler = SimulationHandler(self, simulator.name, *common_args)
|
||||
handler.ready = simulator.is_runnable()
|
||||
|
||||
if self.platform.simulation_exec and shutil.which(self.platform.simulation_exec):
|
||||
handler.ready = True
|
||||
elif self.testsuite.type == "unit":
|
||||
handler = BinaryHandler(self, "unit", *common_args)
|
||||
handler.binary = os.path.join(self.build_dir, "testbinary")
|
||||
|
@ -242,21 +244,23 @@ class TestInstance:
|
|||
|
||||
# Global testsuite parameters
|
||||
def check_runnable(self,
|
||||
options,
|
||||
hardware_map=None):
|
||||
options: TwisterEnv,
|
||||
hardware_map=None):
|
||||
|
||||
enable_slow = options.enable_slow
|
||||
filter = options.filter
|
||||
fixtures = options.fixture
|
||||
device_testing = options.device_testing
|
||||
simulation = options.sim_name
|
||||
|
||||
simulator = self.platform.simulator_by_name(simulation)
|
||||
if os.name == 'nt':
|
||||
# running on simulators is currently supported only for QEMU on Windows
|
||||
if self.platform.simulation not in ('na', 'qemu'):
|
||||
if (not simulator) or simulator.name not in ('na', 'qemu'):
|
||||
return False
|
||||
|
||||
# check presence of QEMU on Windows
|
||||
if self.platform.simulation == 'qemu' and 'QEMU_BIN_PATH' not in os.environ:
|
||||
if simulator.name == 'qemu' and 'QEMU_BIN_PATH' not in os.environ:
|
||||
return False
|
||||
|
||||
# we asked for build-only on the command line
|
||||
|
@ -269,20 +273,20 @@ class TestInstance:
|
|||
return False
|
||||
|
||||
target_ready = bool(self.testsuite.type == "unit" or \
|
||||
self.platform.type == "native" or \
|
||||
(self.platform.simulation in SUPPORTED_SIMS and \
|
||||
self.platform.simulation not in self.testsuite.simulation_exclude) or device_testing)
|
||||
self.platform.type == "native" or \
|
||||
(simulator and simulator.name in SUPPORTED_SIMS and \
|
||||
simulator.name not in self.testsuite.simulation_exclude) or \
|
||||
device_testing)
|
||||
|
||||
# check if test is runnable in pytest
|
||||
if self.testsuite.harness == 'pytest':
|
||||
target_ready = bool(filter == 'runnable' or self.platform.simulation in SUPPORTED_SIMS_IN_PYTEST)
|
||||
target_ready = bool(filter == 'runnable' or simulator and simulator.name in SUPPORTED_SIMS_IN_PYTEST)
|
||||
|
||||
SUPPORTED_SIMS_WITH_EXEC = ['nsim', 'mdb-nsim', 'renode', 'tsim', 'native', 'simics', 'custom']
|
||||
if filter != 'runnable' and \
|
||||
self.platform.simulation in SUPPORTED_SIMS_WITH_EXEC and \
|
||||
self.platform.simulation_exec:
|
||||
if not shutil.which(self.platform.simulation_exec):
|
||||
target_ready = False
|
||||
simulator and \
|
||||
simulator.name in SUPPORTED_SIMS_WITH_EXEC and \
|
||||
not simulator.is_runnable():
|
||||
target_ready = False
|
||||
|
||||
testsuite_runnable = self.testsuite_runnable(self.testsuite, fixtures)
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# vim: set syntax=python ts=4 :
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
# Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import os
|
||||
import sys
|
||||
|
@ -14,7 +16,6 @@ from collections import OrderedDict
|
|||
from itertools import islice
|
||||
import logging
|
||||
import copy
|
||||
import shutil
|
||||
import random
|
||||
import snippets
|
||||
from pathlib import Path
|
||||
|
@ -95,7 +96,7 @@ class TestPlan:
|
|||
SAMPLE_FILENAME = 'sample.yaml'
|
||||
TESTSUITE_FILENAME = 'testcase.yaml'
|
||||
|
||||
def __init__(self, env=None):
|
||||
def __init__(self, env: Namespace):
|
||||
|
||||
self.options = env.options
|
||||
self.env = env
|
||||
|
@ -123,6 +124,7 @@ class TestPlan:
|
|||
self.levels = []
|
||||
self.test_config = {}
|
||||
|
||||
self.name = "unnamed"
|
||||
|
||||
def get_level(self, name):
|
||||
level = next((l for l in self.levels if l.name == name), None)
|
||||
|
@ -157,8 +159,9 @@ class TestPlan:
|
|||
if inherit:
|
||||
for inherted_level in inherit:
|
||||
_inherited = self.get_level(inherted_level)
|
||||
assert _inherited, "Unknown inherited level {inherted_level}"
|
||||
_inherited_scenarios = _inherited.scenarios
|
||||
level_scenarios = _level.scenarios
|
||||
level_scenarios = _level.scenarios if _level else []
|
||||
level_scenarios.extend(_inherited_scenarios)
|
||||
|
||||
def find_subtests(self):
|
||||
|
@ -627,8 +630,9 @@ class TestPlan:
|
|||
|
||||
def handle_quarantined_tests(self, instance: TestInstance, plat: Platform):
|
||||
if self.quarantine:
|
||||
simulator = plat.simulator_by_name(self.options)
|
||||
matched_quarantine = self.quarantine.get_matched_quarantine(
|
||||
instance.testsuite.id, plat.name, plat.arch, plat.simulation
|
||||
instance.testsuite.id, plat.name, plat.arch, simulator.name if simulator is not None else 'na'
|
||||
)
|
||||
if matched_quarantine and not self.options.quarantine_verify:
|
||||
instance.add_filter("Quarantine: " + matched_quarantine, Filters.QUARANTINE)
|
||||
|
@ -773,7 +777,7 @@ class TestPlan:
|
|||
platform_filter = _platforms
|
||||
platforms = list(filter(lambda p: p.name in platform_filter, self.platforms))
|
||||
elif emu_filter:
|
||||
platforms = list(filter(lambda p: p.simulation != 'na', self.platforms))
|
||||
platforms = list(filter(lambda p: bool(p.simulator_by_name(self.options.sim_name)), self.platforms))
|
||||
elif vendor_filter:
|
||||
platforms = list(filter(lambda p: p.vendor in vendor_filter, self.platforms))
|
||||
logger.info(f"Selecting platforms by vendors: {','.join(vendor_filter)}")
|
||||
|
@ -786,10 +790,8 @@ class TestPlan:
|
|||
# the default platforms list. Default platforms should always be
|
||||
# runnable.
|
||||
for p in _platforms:
|
||||
if p.simulation and p.simulation_exec:
|
||||
if shutil.which(p.simulation_exec):
|
||||
platforms.append(p)
|
||||
else:
|
||||
sim = p.simulator_by_name(self.options.sim_name)
|
||||
if (not sim) or sim.is_runnable():
|
||||
platforms.append(p)
|
||||
else:
|
||||
platforms = self.platforms
|
||||
|
@ -931,7 +933,8 @@ class TestPlan:
|
|||
instance.add_filter("Not enough RAM", Filters.PLATFORM)
|
||||
|
||||
if ts.harness:
|
||||
if ts.harness == 'robot' and plat.simulation != 'renode':
|
||||
sim = plat.simulator_by_name(self.options.sim_name)
|
||||
if ts.harness == 'robot' and sim and sim.name != 'renode':
|
||||
instance.add_filter("No robot support for the selected platform", Filters.SKIP)
|
||||
|
||||
if ts.depends_on:
|
||||
|
@ -999,7 +1002,7 @@ class TestPlan:
|
|||
# to run a test once per unique (arch, simulation) platform.
|
||||
if not ignore_platform_key and hasattr(ts, 'platform_key') and len(ts.platform_key) > 0:
|
||||
key_fields = sorted(set(ts.platform_key))
|
||||
keys = [getattr(plat, key_field) for key_field in key_fields]
|
||||
keys = [getattr(plat, key_field, None) for key_field in key_fields]
|
||||
for key in keys:
|
||||
if key is None or key == 'na':
|
||||
instance.add_filter(
|
||||
|
@ -1054,7 +1057,8 @@ class TestPlan:
|
|||
|
||||
elif emulation_platforms:
|
||||
self.add_instances(instance_list)
|
||||
for instance in list(filter(lambda inst: not inst.platform.simulation != 'na', instance_list)):
|
||||
for instance in list(filter(lambda inst: not
|
||||
inst.platform.simulator_by_name(self.options.sim_name), instance_list)):
|
||||
instance.add_filter("Not an emulated platform", Filters.CMD_LINE)
|
||||
elif vendor_platforms:
|
||||
self.add_instances(instance_list)
|
||||
|
|
|
@ -30,22 +30,28 @@ schema;platform-schema:
|
|||
type: str
|
||||
enum: ["mcu", "qemu", "sim", "unit", "native"]
|
||||
"simulation":
|
||||
type: str
|
||||
enum:
|
||||
[
|
||||
"qemu",
|
||||
"simics",
|
||||
"xt-sim",
|
||||
"renode",
|
||||
"nsim",
|
||||
"mdb-nsim",
|
||||
"tsim",
|
||||
"armfvp",
|
||||
"native",
|
||||
"custom",
|
||||
]
|
||||
"simulation_exec":
|
||||
type: str
|
||||
type: seq
|
||||
seq:
|
||||
- type: map
|
||||
mapping:
|
||||
"name":
|
||||
type: str
|
||||
required: true
|
||||
enum:
|
||||
[
|
||||
"qemu",
|
||||
"simics",
|
||||
"xt-sim",
|
||||
"renode",
|
||||
"nsim",
|
||||
"mdb-nsim",
|
||||
"tsim",
|
||||
"armfvp",
|
||||
"native",
|
||||
"custom",
|
||||
]
|
||||
"exec":
|
||||
type: str
|
||||
"arch":
|
||||
type: str
|
||||
enum:
|
||||
|
|
|
@ -443,6 +443,7 @@ def test_binaryhandler_create_command(
|
|||
options = SimpleNamespace()
|
||||
options.enable_valgrind = enable_valgrind
|
||||
options.coverage_basedir = "coverage_basedir"
|
||||
options.sim_name = None
|
||||
handler = BinaryHandler(mocked_instance, 'build', options, 'generator', False)
|
||||
handler.binary = 'bin'
|
||||
handler.call_make_run = call_make_run
|
||||
|
|
|
@ -14,7 +14,7 @@ import pytest
|
|||
ZEPHYR_BASE = os.getenv("ZEPHYR_BASE")
|
||||
sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister"))
|
||||
|
||||
from twisterlib.platform import Platform
|
||||
from twisterlib.platform import Platform, Simulator
|
||||
|
||||
|
||||
TESTDATA_1 = [
|
||||
|
@ -38,8 +38,7 @@ arch: arc
|
|||
'vendor': '',
|
||||
'tier': -1,
|
||||
'type': 'na',
|
||||
'simulation': 'na',
|
||||
'simulation_exec': None,
|
||||
'simulators': [],
|
||||
'supported_toolchains': [],
|
||||
'env': [],
|
||||
'env_satisfied': True
|
||||
|
@ -71,8 +70,9 @@ supported:
|
|||
vendor: vendor1
|
||||
tier: 1
|
||||
type: unit
|
||||
simulation: nsim
|
||||
simulation_exec: nsimdrv
|
||||
simulation:
|
||||
- name: nsim
|
||||
exec: nsimdrv
|
||||
toolchain:
|
||||
- zephyr
|
||||
- llvm
|
||||
|
@ -94,8 +94,7 @@ env:
|
|||
'vendor': 'vendor1',
|
||||
'tier': 1,
|
||||
'type': 'unit',
|
||||
'simulation': 'nsim',
|
||||
'simulation_exec': 'nsimdrv',
|
||||
'simulators': [Simulator({'name': 'nsim', 'exec': 'nsimdrv'})],
|
||||
'supported_toolchains': ['zephyr', 'llvm', 'cross-compile'],
|
||||
'env': ['dummynonexistentvar'],
|
||||
'env_satisfied': False
|
||||
|
|
|
@ -263,12 +263,12 @@ def test_quarantinedata_get_matched_quarantine(
|
|||
scenario=scenario,
|
||||
platform=platform,
|
||||
architecture=architecture,
|
||||
simulation=simulation
|
||||
simulator_name=simulation
|
||||
) is None
|
||||
else:
|
||||
assert quarantine_data.get_matched_quarantine(
|
||||
scenario=scenario,
|
||||
platform=platform,
|
||||
architecture=architecture,
|
||||
simulation=simulation
|
||||
simulator_name=simulation
|
||||
) == qlist[expected_idx]
|
||||
|
|
|
@ -16,6 +16,7 @@ import mock
|
|||
ZEPHYR_BASE = os.getenv("ZEPHYR_BASE")
|
||||
sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister"))
|
||||
|
||||
from pylib.twister.twisterlib.platform import Simulator
|
||||
from twisterlib.statuses import TwisterStatus
|
||||
from twisterlib.testinstance import TestInstance
|
||||
from twisterlib.error import BuildError
|
||||
|
@ -25,12 +26,12 @@ from expr_parser import reserved
|
|||
|
||||
|
||||
TESTDATA_PART_1 = [
|
||||
(False, False, "console", "na", "qemu", False, [], (False, True)),
|
||||
(False, False, "console", None, "qemu", False, [], (False, True)),
|
||||
(False, False, "console", "native", "qemu", False, [], (False, True)),
|
||||
(True, False, "console", "native", "nsim", False, [], (True, False)),
|
||||
(True, True, "console", "native", "renode", False, [], (True, False)),
|
||||
(False, False, "sensor", "native", "", False, [], (True, False)),
|
||||
(False, False, "sensor", "na", "", False, [], (True, False)),
|
||||
(False, False, "sensor", None, "", False, [], (True, False)),
|
||||
(False, True, "sensor", "native", "", True, [], (True, False)),
|
||||
]
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -62,7 +63,7 @@ def test_check_build_or_run(
|
|||
class_testplan.platforms = platforms_list
|
||||
platform = class_testplan.get_platform("demo_board_2")
|
||||
platform.type = platform_type
|
||||
platform.simulation = platform_sim
|
||||
platform.simulators = [Simulator({"name": platform_sim})] if platform_sim else []
|
||||
testsuite.harness = harness
|
||||
testsuite.build_only = build_only
|
||||
testsuite.slow = slow
|
||||
|
@ -73,7 +74,8 @@ def test_check_build_or_run(
|
|||
device_testing=False,
|
||||
enable_slow=slow,
|
||||
fixtures=fixture,
|
||||
filter=""
|
||||
filter="",
|
||||
sim_name=platform_sim
|
||||
)
|
||||
)
|
||||
run = testinstance.check_runnable(env.options)
|
||||
|
@ -455,9 +457,9 @@ TESTDATA_4 = [
|
|||
(True, mock.ANY, mock.ANY, mock.ANY, None, [], False),
|
||||
(False, True, mock.ANY, mock.ANY, 'device', [], True),
|
||||
(False, False, 'qemu', mock.ANY, 'qemu', ['QEMU_PIPE=1'], True),
|
||||
(False, False, 'dummy sim', mock.ANY, 'dummy sim', [], True),
|
||||
(False, False, 'na', 'unit', 'unit', ['COVERAGE=1'], True),
|
||||
(False, False, 'na', 'dummy type', '', [], False),
|
||||
(False, False, 'armfvp', mock.ANY, 'armfvp', [], True),
|
||||
(False, False, None, 'unit', 'unit', ['COVERAGE=1'], True),
|
||||
(False, False, None, 'dummy type', '', [], False),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -479,13 +481,13 @@ def test_testinstance_setup_handler(
|
|||
expected_handler_ready
|
||||
):
|
||||
testinstance.handler = mock.Mock() if preexisting_handler else None
|
||||
testinstance.platform.simulation = platform_sim
|
||||
testinstance.platform.simulation_exec = 'dummy exec'
|
||||
testinstance.platform.simulators = [Simulator({"name": platform_sim, "exec": 'dummy exec'})] if platform_sim else []
|
||||
testinstance.testsuite.type = testsuite_type
|
||||
env = mock.Mock(
|
||||
options=mock.Mock(
|
||||
device_testing=device_testing,
|
||||
enable_coverage=True
|
||||
enable_coverage=True,
|
||||
sim_name=platform_sim,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -546,8 +548,7 @@ def test_testinstance_check_runnable(
|
|||
hardware_map,
|
||||
expected
|
||||
):
|
||||
testinstance.platform.simulation = platform_sim
|
||||
testinstance.platform.simulation_exec = platform_sim_exec
|
||||
testinstance.platform.simulators = [Simulator({"name": platform_sim, "exec": platform_sim_exec})]
|
||||
testinstance.testsuite.build_only = testsuite_build_only
|
||||
testinstance.testsuite.slow = testsuite_slow
|
||||
testinstance.testsuite.harness = testsuite_harness
|
||||
|
@ -557,7 +558,8 @@ def test_testinstance_check_runnable(
|
|||
device_testing=False,
|
||||
enable_slow=enable_slow,
|
||||
fixtures=fixtures,
|
||||
filter=filter
|
||||
filter=filter,
|
||||
sim_name=platform_sim
|
||||
)
|
||||
)
|
||||
with mock.patch('os.name', os_name), \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue