Skip to content

Commit bac1a95

Browse files
gchwiernashif
authored andcommitted
twister: quarantine: Added simulations field and regex to filter fields
Regex are allowed on every field, not only scenarios. Signed-off-by: Grzegorz Chwierut <[email protected]>
1 parent d95eab1 commit bac1a95

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

scripts/pylib/twister/twisterlib/quarantine.py

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from __future__ import annotations
55

66
import logging
7+
import re
78

89
from pathlib import Path
910
from yaml import safe_load
@@ -25,9 +26,10 @@ def __init__(self, quarantine_list=[]) -> None:
2526
for quarantine_file in quarantine_list:
2627
self.quarantine.extend(QuarantineData.load_data_from_yaml(quarantine_file))
2728

28-
def get_matched_quarantine(self, testname, platform, architecture):
29-
qelem = self.quarantine.get_matched_quarantine(testname, platform, architecture)
29+
def get_matched_quarantine(self, testname, platform, architecture, simulation):
30+
qelem = self.quarantine.get_matched_quarantine(testname, platform, architecture, simulation)
3031
if qelem:
32+
logger.debug('%s quarantined with reason: %s' % (testname, qelem.comment))
3133
return qelem.comment
3234
return None
3335

@@ -37,18 +39,26 @@ class QuarantineElement:
3739
scenarios: list[str] = field(default_factory=list)
3840
platforms: list[str] = field(default_factory=list)
3941
architectures: list[str] = field(default_factory=list)
42+
simulations: list[str] = field(default_factory=list)
4043
comment: str = 'under quarantine'
4144

4245
def __post_init__(self):
46+
# If there is no entry in filters then take all possible values.
47+
# To keep backward compatibility, 'all' keyword might be still used.
4348
if 'all' in self.scenarios:
4449
self.scenarios = []
4550
if 'all' in self.platforms:
4651
self.platforms = []
4752
if 'all' in self.architectures:
4853
self.architectures = []
49-
if not any([self.scenarios, self.platforms, self.architectures]):
50-
raise QuarantineException("At least one of filters ('scenarios', 'platforms', "
51-
"'architectures') must be specified")
54+
if 'all' in self.simulations:
55+
self.simulations = []
56+
# However, at least one of the filters ('scenarios', platforms' ...)
57+
# must be given (there is no sense to put all possible configuration
58+
# into quarantine)
59+
if not any([self.scenarios, self.platforms, self.architectures, self.simulations]):
60+
raise QuarantineException("At least one of filters ('scenarios', 'platforms' ...) "
61+
"must be specified")
5262

5363

5464
@dataclass
@@ -58,48 +68,56 @@ class QuarantineData:
5868
def __post_init__(self):
5969
qelements = []
6070
for qelem in self.qlist:
61-
qelements.append(QuarantineElement(**qelem))
71+
if isinstance(qelem, QuarantineElement):
72+
qelements.append(qelem)
73+
else:
74+
qelements.append(QuarantineElement(**qelem))
6275
self.qlist = qelements
6376

6477
@classmethod
6578
def load_data_from_yaml(cls, filename: str | Path) -> QuarantineData:
6679
"""Load quarantine from yaml file."""
6780
with open(filename, 'r', encoding='UTF-8') as yaml_fd:
68-
qlist: list(dict) = safe_load(yaml_fd)
81+
qlist_raw_data: list[dict] = safe_load(yaml_fd)
6982
try:
70-
return cls(qlist)
83+
return cls(qlist_raw_data)
7184

7285
except Exception as e:
7386
logger.error(f'When loading {filename} received error: {e}')
7487
raise QuarantineException('Cannot load Quarantine data') from e
7588

76-
def extend(self, qdata: QuarantineData) -> list[QuarantineElement]:
89+
def extend(self, qdata: QuarantineData) -> None:
7790
self.qlist.extend(qdata.qlist)
7891

79-
def get_matched_quarantine(self, scenario: str, platform: str,
80-
architecture: str) -> QuarantineElement | None:
92+
def get_matched_quarantine(self,
93+
scenario: str,
94+
platform: str,
95+
architecture: str,
96+
simulation: str) -> QuarantineElement | None:
8197
"""Return quarantine element if test is matched to quarantine rules"""
8298
for qelem in self.qlist:
8399
matched: bool = False
84-
if qelem.scenarios:
85-
if scenario in qelem.scenarios:
86-
matched = True
87-
else:
88-
matched = False
89-
continue
90-
if qelem.platforms:
91-
if platform in qelem.platforms:
92-
matched = True
93-
else:
94-
matched = False
95-
continue
96-
if qelem.architectures:
97-
if architecture in qelem.architectures:
98-
matched = True
99-
else:
100-
matched = False
101-
continue
100+
if (qelem.scenarios
101+
and (matched := _is_element_matched(scenario, qelem.scenarios)) is False):
102+
continue
103+
if (qelem.platforms
104+
and (matched := _is_element_matched(platform, qelem.platforms)) is False):
105+
continue
106+
if (qelem.architectures
107+
and (matched := _is_element_matched(architecture, qelem.architectures)) is False):
108+
continue
109+
if (qelem.simulations
110+
and (matched := _is_element_matched(simulation, qelem.simulations)) is False):
111+
continue
112+
102113
if matched:
103114
return qelem
104-
105115
return None
116+
117+
118+
def _is_element_matched(element: str, list_of_elements: list) -> bool:
119+
"""Return True if given element is matching to any of elements from the list"""
120+
for pattern in list_of_elements:
121+
if re.fullmatch(pattern, element):
122+
return True
123+
return False

scripts/pylib/twister/twisterlib/testplan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ def apply_filters(self, **kwargs):
747747
# handle quarantined tests
748748
if self.quarantine:
749749
matched_quarantine = self.quarantine.get_matched_quarantine(
750-
instance.testsuite.id, plat.name, plat.arch
750+
instance.testsuite.id, plat.name, plat.arch, plat.simulation
751751
)
752752
if matched_quarantine and not self.options.quarantine_verify:
753753
instance.add_filter(matched_quarantine, Filters.QUARENTINE)

scripts/schemas/twister/quarantine-schema.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ sequence:
3131
type: seq
3232
sequence:
3333
- type: str
34-
- unique: true
34+
- unique: True
35+
"simulations":
36+
required: false
37+
type: seq
38+
sequence:
39+
- type: str
40+
- unique: True
3541
"comment":
3642
type: str
3743
required: false

0 commit comments

Comments
 (0)