Skip to content

Commit e25916b

Browse files
committed
twister: use filter cache
Signed-off-by: Anas Nashif <[email protected]>
1 parent 0d378a9 commit e25916b

File tree

5 files changed

+94
-9
lines changed

5 files changed

+94
-9
lines changed

samples/basic/blinky/sample.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ tests:
66
- LED
77
- gpio
88
filter: dt_enabled_alias_with_parent_compat("led0", "gpio-leds")
9-
depends_on: gpio
9+
#depends_on: gpio
1010
harness: led
1111
integration_platforms:
1212
- frdm_k64f

scripts/pylib/twister/twisterlib/environment.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@ def add_parse_arguments(parser = None):
291291
files in the directory will be processed. The directory should have the same
292292
structure in the main Zephyr tree: boards/<vendor>/<board_name>/""")
293293

294+
parser.add_argument(
295+
"--filter-cache",
296+
help="Use existing filter cache to speed up test selection."
297+
)
298+
294299
parser.add_argument(
295300
"--allow-installed-plugin", action="store_true", default=None,
296301
help="Allow to use pytest plugin installed by pip for pytest tests."

scripts/pylib/twister/twisterlib/runner.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,6 @@ def run_cmake(self, args="", filter_stages=[]):
675675
with open(os.path.join(self.build_dir, self.log), "a", encoding=self.default_encoding) as log:
676676
log_msg = out.decode(self.default_encoding)
677677
log.write(log_msg)
678-
679678
return ret
680679

681680

@@ -1721,10 +1720,11 @@ def add_tasks_to_queue(self, pipeline, build_only=False, test_only=False, retry_
17211720
if self.results.iteration > 1:
17221721
ProjectBuilder._add_instance_testcases_to_status_counts(instance, self.results, decrement=True)
17231722

1724-
# Check if cmake package_helper script can be run in advance.
17251723
instance.filter_stages = []
1726-
if instance.testsuite.filter:
1727-
instance.filter_stages = self.get_cmake_filter_stages(instance.testsuite.filter, expr_parser.reserved.keys())
1724+
if not self.env.options.filter_cache:
1725+
# Check if cmake package_helper script can be run in advance.
1726+
if instance.testsuite.filter:
1727+
instance.filter_stages = self.get_cmake_filter_stages(instance.testsuite.filter, expr_parser.reserved.keys())
17281728

17291729
if test_only and instance.run:
17301730
pipeline.put({"op": "run", "test": instance})

scripts/pylib/twister/twisterlib/testplan.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import re
99
import subprocess
10+
import pickle
1011
import glob
1112
import json
1213
import collections
@@ -35,6 +36,7 @@
3536
from twisterlib.statuses import TwisterStatus
3637
from twisterlib.testinstance import TestInstance
3738
from twisterlib.quarantine import Quarantine
39+
from twisterlib.cmakecache import CMakeCache
3840

3941
import list_boards
4042
from zephyr_module import parse_modules
@@ -51,6 +53,8 @@
5153
sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/"))
5254

5355
import scl
56+
import expr_parser
57+
5458
class Filters:
5559
# platform keys
5660
PLATFORM_KEY = 'platform key filter'
@@ -99,6 +103,7 @@ def __init__(self, env=None):
99103

100104
self.options = env.options
101105
self.env = env
106+
self.filter_cache = {}
102107

103108
# Keep track of which test cases we've filtered out and why
104109
self.testsuites = {}
@@ -722,6 +727,80 @@ def check_platform(self, platform, platform_list):
722727
return True
723728
return False
724729

730+
def parse_generated(self, instance):
731+
config_re = re.compile('(CONFIG_[A-Za-z0-9_]+)[=]\"?([^\"]*)\"?$')
732+
dt_re = re.compile('([A-Za-z0-9_]+)[=]\"?([^\"]*)\"?$')
733+
734+
if instance.platform.name == "unit_testing":
735+
return {}
736+
737+
if not self.filter_cache.get(instance.platform.name):
738+
cache_dir = os.path.join(self.options.filter_cache, instance.platform.normalized_name)
739+
cmake_cache_path = os.path.join(cache_dir, "CMakeCache.txt")
740+
defconfig_path = os.path.join(cache_dir, ".config")
741+
edt_pickle = os.path.join(cache_dir, "edt.pickle")
742+
defconfig = {}
743+
744+
if not os.path.exists(defconfig_path) and not os.path.exists(edt_pickle):
745+
return None
746+
747+
if os.path.exists(defconfig_path):
748+
with open(defconfig_path, "r") as fp:
749+
for line in fp.readlines():
750+
m = config_re.match(line)
751+
if not m:
752+
if line.strip() and not line.startswith("#"):
753+
sys.stderr.write("Unrecognized line %s\n" % line)
754+
continue
755+
defconfig[m.group(1)] = m.group(2).strip()
756+
757+
cmake_conf = {}
758+
if os.path.exists(cmake_cache_path):
759+
760+
try:
761+
cache = CMakeCache.from_file(cmake_cache_path)
762+
except FileNotFoundError:
763+
cache = {}
764+
765+
for k in iter(cache):
766+
cmake_conf[k.name] = k.value
767+
768+
filter_data = {
769+
"ARCH": instance.platform.arch,
770+
"PLATFORM": instance.platform.name
771+
}
772+
filter_data.update(os.environ)
773+
filter_data.update(defconfig)
774+
filter_data.update(cmake_conf)
775+
776+
if os.path.exists(edt_pickle):
777+
with open(edt_pickle, 'rb') as f:
778+
edt = pickle.load(f)
779+
else:
780+
edt = None
781+
782+
self.filter_cache[instance.platform.name] = {'filter': filter_data, 'edt': edt}
783+
784+
if instance.testsuite and instance.testsuite.filter:
785+
try:
786+
edt = self.filter_cache[instance.platform.name]['edt']
787+
filter_data = self.filter_cache[instance.platform.name]['filter']
788+
789+
ret = expr_parser.parse(instance.testsuite.filter, filter_data, edt)
790+
791+
except (ValueError, SyntaxError) as se:
792+
sys.stderr.write(
793+
"Failed processing %s\n" % instance.testsuite.yamlfile)
794+
raise se
795+
796+
if not ret:
797+
return {os.path.join(instance.platform.name, instance.testsuite.name): True}
798+
else:
799+
return {os.path.join(instance.platform.name, instance.testsuite.name): False}
800+
else:
801+
instance.platform.filter_data = filter_data
802+
return None
803+
725804
def apply_filters(self, **kwargs):
726805

727806
toolchain = self.env.toolchain
@@ -869,6 +948,11 @@ def apply_filters(self, **kwargs):
869948
if self.options.integration and ts.integration_platforms and plat.name not in ts.integration_platforms:
870949
instance.add_filter("Not part of integration platforms", Filters.TESTSUITE)
871950

951+
if ts.filter and self.options.filter_cache and not instance.sysbuild:
952+
filter_data = self.parse_generated(instance)
953+
if filter_data and filter_data.get(instance.name, False):
954+
instance.add_filter("Generated filter", Filters.TESTSUITE)
955+
872956
if ts.skip:
873957
instance.add_filter("Skip filter", Filters.SKIP)
874958

tests/kernel/mem_protect/sys_sem/testcase.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,3 @@ tests:
66
tags:
77
- kernel
88
- userspace
9-
kernel.memory_protection.sys_sem.nouser:
10-
extra_configs:
11-
- CONFIG_TEST_USERSPACE=n
12-
tags: kernel

0 commit comments

Comments
 (0)