Skip to content

Commit 64b8f37

Browse files
authored
Merge pull request #664 from ChristopherBignamini/regular_expressions
[feat] Add support for selecting tests using regular expressions
2 parents 70d3dff + c18b176 commit 64b8f37

File tree

5 files changed

+77
-61
lines changed

5 files changed

+77
-61
lines changed

reframe/core/pipeline.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
'RunOnlyRegressionTest', 'CompileOnlyRegressionTest']
77

88

9-
import fnmatch
109
import inspect
1110
import itertools
1211
import os
@@ -67,12 +66,18 @@ class RegressionTest:
6766

6867
#: List of programming environments supported by this test.
6968
#:
69+
#: If ``*`` is in the list then all programming environments are supported
70+
#: by this test.
71+
#:
7072
#: :type: :class:`List[str]`
7173
#: :default: ``[]``
7274
#:
7375
#: .. note::
7476
#: .. versionchanged:: 2.12
7577
#: Programming environments can now be specified using wildcards.
78+
#:
79+
#: .. versionchanged:: 2.17
80+
#: Support for wildcards is dropped.
7681
valid_prog_environs = fields.TypedField('valid_prog_environs',
7782
typ.List[str])
7883

@@ -787,11 +792,10 @@ def supports_system(self, partition_name):
787792
return partition_name in self.valid_systems
788793

789794
def supports_environ(self, env_name):
790-
for env in self.valid_prog_environs:
791-
if fnmatch.fnmatch(env_name, env):
792-
return True
795+
if '*' in self.valid_prog_environs:
796+
return True
793797

794-
return False
798+
return env_name in self.valid_prog_environs
795799

796800
def is_local(self):
797801
"""Check if the test will execute locally.

reframe/frontend/check_filters.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,42 @@
1+
import re
2+
13
import reframe.core.runtime as rt
24
import reframe.utility.sanity as util
35

46

5-
def have_name(names):
7+
def have_name(patt):
8+
regex = re.compile(patt)
9+
610
def _fn(c):
7-
return c.name in names
11+
return regex.match(c.name)
812

913
return _fn
1014

1115

12-
def have_not_name(names):
16+
def have_not_name(patt):
1317
def _fn(c):
14-
return not have_name(names)(c)
18+
return not have_name(patt)(c)
1519

1620
return _fn
1721

1822

19-
def have_tag(tags):
23+
def have_tag(patt):
24+
regex = re.compile(patt)
25+
2026
def _fn(c):
21-
return (set(tags)).issubset(c.tags)
27+
return any(regex.match(p) for p in c.tags)
2228

2329
return _fn
2430

2531

26-
def have_prgenv(prgenv):
32+
def have_prgenv(patt):
33+
regex = re.compile(patt)
34+
2735
def _fn(c):
28-
if prgenv:
29-
return util.allx(c.supports_environ(e) for e in prgenv)
36+
if '*' in c.valid_prog_environs:
37+
return True
3038
else:
31-
return bool(c.valid_prog_environs)
39+
return any(regex.match(p) for p in c.valid_prog_environs)
3240

3341
return _fn
3442

reframe/frontend/cli.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import os
21
import inspect
32
import json
3+
import os
44
import socket
55
import sys
66
import traceback
@@ -111,7 +111,7 @@ def main():
111111
'-x', '--exclude', action='append', dest='exclude_names',
112112
metavar='NAME', default=[], help='Exclude checks with NAME')
113113
select_options.add_argument(
114-
'-p', '--prgenv', action='append', default=[],
114+
'-p', '--prgenv', action='append', default=[r'.*'],
115115
help='Select tests for PRGENV programming environment only')
116116
select_options.add_argument(
117117
'--gpu-only', action='store_true',
@@ -414,20 +414,25 @@ def main():
414414
raise ReframeError from e
415415

416416
# Filter checks by name
417-
checks_matched = filter(filters.have_not_name(options.exclude_names),
418-
checks_found)
417+
checks_matched = checks_found
418+
if options.exclude_names:
419+
for name in options.exclude_names:
420+
checks_matched = filter(filters.have_not_name(name),
421+
checks_matched)
419422

420423
if options.names:
421-
checks_matched = filter(filters.have_name(options.names),
424+
checks_matched = filter(filters.have_name('|'.join(options.names)),
422425
checks_matched)
423426

424427
# Filter checks by tags
425-
checks_matched = filter(filters.have_tag(options.tags), checks_matched)
428+
for tag in options.tags:
429+
checks_matched = filter(filters.have_tag(tag), checks_matched)
426430

427431
# Filter checks by prgenv
428432
if not options.skip_prgenv_check:
429-
checks_matched = filter(filters.have_prgenv(options.prgenv),
430-
checks_matched)
433+
for prgenv in options.prgenv:
434+
checks_matched = filter(filters.have_prgenv(prgenv),
435+
checks_matched)
431436

432437
# Filter checks by system
433438
if not options.skip_system_check:

unittests/test_check_filters.py

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,51 +37,56 @@ def setUp(self):
3737
'num_gpus_per_node': 1})
3838
]
3939

40+
def count_checks(self, filter_fn):
41+
return sn.count(filter(filter_fn, self.checks))
42+
4043
def test_have_name(self):
41-
self.assertEqual(1, sn.count(filter(filters.have_name('check1'),
42-
self.checks)))
43-
self.assertEqual(1, sn.count(filter(filters.have_name('check2'),
44-
self.checks)))
45-
self.assertEqual(1, sn.count(filter(filters.have_name('check3'),
46-
self.checks)))
47-
self.assertEqual(0, sn.count(filter(filters.have_name('check4'),
48-
self.checks)))
44+
self.assertEqual(1, self.count_checks(filters.have_name('check1')))
45+
self.assertEqual(3, self.count_checks(filters.have_name('check')))
46+
self.assertEqual(2, self.count_checks(filters.have_name(r'\S*1|\S*3')))
47+
self.assertEqual(0, self.count_checks(filters.have_name('Check')))
48+
self.assertEqual(3, self.count_checks(filters.have_name('(?i)Check')))
49+
self.assertEqual(
50+
2, self.count_checks(filters.have_name('check1|(?i)CHECK2'))
51+
)
4952

5053
def test_have_not_name(self):
51-
self.assertEqual(2, sn.count(filter(filters.have_not_name('check1'),
52-
self.checks)))
54+
self.assertEqual(2, self.count_checks(filters.have_not_name('check1')))
55+
self.assertEqual(
56+
1, self.count_checks(filters.have_not_name('check1|check3'))
57+
)
58+
self.assertEqual(
59+
0, self.count_checks(filters.have_not_name('check1|check2|check3'))
60+
)
61+
self.assertEqual(3, self.count_checks(filters.have_not_name('Check1')))
62+
self.assertEqual(
63+
2, self.count_checks(filters.have_not_name('(?i)Check1'))
64+
)
5365

5466
def test_have_tags(self):
55-
self.assertEqual(1, sn.count(filter(filters.have_tag(['a', 'c']),
56-
self.checks)))
57-
self.assertEqual(0, sn.count(filter(filters.have_tag(['p', 'q']),
58-
self.checks)))
59-
self.assertEqual(2, sn.count(filter(filters.have_tag(['z']),
60-
self.checks)))
67+
self.assertEqual(2, self.count_checks(filters.have_tag('a|c')))
68+
self.assertEqual(0, self.count_checks(filters.have_tag('p|q')))
69+
self.assertEqual(2, self.count_checks(filters.have_tag('z')))
6170

6271
def test_have_prgenv(self):
63-
self.assertEqual(1, sn.count(filter(
64-
filters.have_prgenv(['env1', 'env2']), self.checks)))
65-
self.assertEqual(2, sn.count(filter(filters.have_prgenv(['env3']),
66-
self.checks)))
67-
self.assertEqual(1, sn.count(filter(filters.have_prgenv(['env4']),
68-
self.checks)))
69-
self.assertEqual(0, sn.count(filter(
70-
filters.have_prgenv(['env1', 'env3']), self.checks)))
72+
self.assertEqual(
73+
1, self.count_checks(filters.have_prgenv('env1|env2'))
74+
)
75+
self.assertEqual(2, self.count_checks(filters.have_prgenv('env3')))
76+
self.assertEqual(1, self.count_checks(filters.have_prgenv('env4')))
77+
self.assertEqual(
78+
3, self.count_checks(filters.have_prgenv('env1|env3'))
79+
)
7180

7281
@rt.switch_runtime(fixtures.TEST_SITE_CONFIG, 'testsys')
7382
def test_partition(self):
7483
p = rt.runtime().system.partition('gpu')
75-
self.assertEqual(2, sn.count(filter(filters.have_partition([p]),
76-
self.checks)))
84+
self.assertEqual(2, self.count_checks(filters.have_partition([p])))
7785
p = rt.runtime().system.partition('login')
78-
self.assertEqual(0, sn.count(filter(filters.have_partition([p]),
79-
self.checks)))
86+
self.assertEqual(0, self.count_checks(filters.have_partition([p])))
8087

8188
def test_have_gpu_only(self):
82-
self.assertEqual(2, sn.count(filter(filters.have_gpu_only(),
83-
self.checks)))
89+
self.assertEqual(2, self.count_checks(filters.have_gpu_only()))
8490

8591
def test_have_cpu_only(self):
86-
self.assertEqual(1, sn.count(filter(filters.have_cpu_only(),
87-
self.checks)))
92+
self.assertEqual(1, self.count_checks(filters.have_cpu_only()))

unittests/test_pipeline.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,6 @@ def test_supports_environ(self):
253253
self.assertTrue(test.supports_environ('foo-env'))
254254
self.assertTrue(test.supports_environ('*'))
255255

256-
test.valid_prog_environs = ['PrgEnv-foo-*']
257-
self.assertTrue(test.supports_environ('PrgEnv-foo-version1'))
258-
self.assertTrue(test.supports_environ('PrgEnv-foo-version2'))
259-
self.assertFalse(test.supports_environ('PrgEnv-boo-version1'))
260-
self.assertFalse(test.supports_environ('Prgenv-foo-version1'))
261-
262256
def test_sourcesdir_none(self):
263257
test = RegressionTest('hellocheck', 'unittests/resources/checks')
264258
test.sourcesdir = None

0 commit comments

Comments
 (0)