summaryrefslogtreecommitdiffstats
path: root/Lib/test/libregrtest
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-10-21 17:30:19 (GMT)
committerGitHub <noreply@github.com>2023-10-21 17:30:19 (GMT)
commit4222dd93af710ba9f427d4f5d95a9241298ff0db (patch)
treea79f8c2b9d912d8fe297ecdc91ba54c95c43cdd5 /Lib/test/libregrtest
parent17b8e35b65315efbb859100c9d0393eed338a815 (diff)
downloadcpython-4222dd93af710ba9f427d4f5d95a9241298ff0db.zip
cpython-4222dd93af710ba9f427d4f5d95a9241298ff0db.tar.gz
cpython-4222dd93af710ba9f427d4f5d95a9241298ff0db.tar.bz2
[3.11] gh-110918: regrtest: allow to intermix --match and --ignore options (GH-110919) (GH-111168)
Test case matching patterns specified by options --match, --ignore, --matchfile and --ignorefile are now tested in the order of specification, and the last match determines whether the test case be run or ignored. (cherry picked from commit 9a1fe09622cd0f1e24c2ba5335c94c5d70306fd0)
Diffstat (limited to 'Lib/test/libregrtest')
-rw-r--r--Lib/test/libregrtest/cmdline.py40
-rw-r--r--Lib/test/libregrtest/findtests.py7
-rw-r--r--Lib/test/libregrtest/main.py15
-rw-r--r--Lib/test/libregrtest/run_workers.py2
-rw-r--r--Lib/test/libregrtest/runtests.py5
-rw-r--r--Lib/test/libregrtest/setup.py2
-rw-r--r--Lib/test/libregrtest/utils.py1
-rw-r--r--Lib/test/libregrtest/worker.py6
8 files changed, 36 insertions, 42 deletions
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index b1b0089..905b3f8 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -161,8 +161,7 @@ class Namespace(argparse.Namespace):
self.forever = False
self.header = False
self.failfast = False
- self.match_tests = None
- self.ignore_tests = None
+ self.match_tests = []
self.pgo = False
self.pgo_extended = False
self.worker_json = None
@@ -183,6 +182,20 @@ class _ArgParser(argparse.ArgumentParser):
super().error(message + "\nPass -h or --help for complete help.")
+class FilterAction(argparse.Action):
+ def __call__(self, parser, namespace, value, option_string=None):
+ items = getattr(namespace, self.dest)
+ items.append((value, self.const))
+
+
+class FromFileFilterAction(argparse.Action):
+ def __call__(self, parser, namespace, value, option_string=None):
+ items = getattr(namespace, self.dest)
+ with open(value, encoding='utf-8') as fp:
+ for line in fp:
+ items.append((line.strip(), self.const))
+
+
def _create_parser():
# Set prog to prevent the uninformative "__main__.py" from displaying in
# error messages when using "python -m test ...".
@@ -192,6 +205,7 @@ def _create_parser():
epilog=EPILOG,
add_help=False,
formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.set_defaults(match_tests=[])
# Arguments with this clause added to its help are described further in
# the epilog's "Additional option details" section.
@@ -251,17 +265,19 @@ def _create_parser():
help='single step through a set of tests.' +
more_details)
group.add_argument('-m', '--match', metavar='PAT',
- dest='match_tests', action='append',
+ dest='match_tests', action=FilterAction, const=True,
help='match test cases and methods with glob pattern PAT')
group.add_argument('-i', '--ignore', metavar='PAT',
- dest='ignore_tests', action='append',
+ dest='match_tests', action=FilterAction, const=False,
help='ignore test cases and methods with glob pattern PAT')
group.add_argument('--matchfile', metavar='FILENAME',
- dest='match_filename',
+ dest='match_tests',
+ action=FromFileFilterAction, const=True,
help='similar to --match but get patterns from a '
'text file, one pattern per line')
group.add_argument('--ignorefile', metavar='FILENAME',
- dest='ignore_filename',
+ dest='match_tests',
+ action=FromFileFilterAction, const=False,
help='similar to --matchfile but it receives patterns '
'from text file to ignore')
group.add_argument('-G', '--failfast', action='store_true',
@@ -483,18 +499,6 @@ def _parse_args(args, **kwargs):
print("WARNING: Disable --verbose3 because it's incompatible with "
"--huntrleaks: see http://bugs.python.org/issue27103",
file=sys.stderr)
- if ns.match_filename:
- if ns.match_tests is None:
- ns.match_tests = []
- with open(ns.match_filename) as fp:
- for line in fp:
- ns.match_tests.append(line.strip())
- if ns.ignore_filename:
- if ns.ignore_tests is None:
- ns.ignore_tests = []
- with open(ns.ignore_filename) as fp:
- for line in fp:
- ns.ignore_tests.append(line.strip())
if ns.forever:
# --forever implies --failfast
ns.failfast = True
diff --git a/Lib/test/libregrtest/findtests.py b/Lib/test/libregrtest/findtests.py
index 96cc3e0..dd39fe1 100644
--- a/Lib/test/libregrtest/findtests.py
+++ b/Lib/test/libregrtest/findtests.py
@@ -5,7 +5,7 @@ import unittest
from test import support
from .utils import (
- StrPath, TestName, TestTuple, TestList, FilterTuple,
+ StrPath, TestName, TestTuple, TestList, TestFilter,
abs_module_name, count, printlist)
@@ -82,11 +82,10 @@ def _list_cases(suite):
print(test.id())
def list_cases(tests: TestTuple, *,
- match_tests: FilterTuple | None = None,
- ignore_tests: FilterTuple | None = None,
+ match_tests: TestFilter | None = None,
test_dir: StrPath | None = None):
support.verbose = False
- support.set_match_tests(match_tests, ignore_tests)
+ support.set_match_tests(match_tests)
skipped = []
for test_name in tests:
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index e765ed5..8544bb4 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -19,7 +19,7 @@ from .runtests import RunTests, HuntRefleak
from .setup import setup_process, setup_test_dir
from .single import run_single_test, PROGRESS_MIN_TIME
from .utils import (
- StrPath, StrJSON, TestName, TestList, TestTuple, FilterTuple,
+ StrPath, StrJSON, TestName, TestList, TestTuple, TestFilter,
strip_py_suffix, count, format_duration,
printlist, get_temp_dir, get_work_dir, exit_timeout,
display_header, cleanup_temp_dir, print_warning,
@@ -78,14 +78,7 @@ class Regrtest:
and ns._add_python_opts)
# Select tests
- if ns.match_tests:
- self.match_tests: FilterTuple | None = tuple(ns.match_tests)
- else:
- self.match_tests = None
- if ns.ignore_tests:
- self.ignore_tests: FilterTuple | None = tuple(ns.ignore_tests)
- else:
- self.ignore_tests = None
+ self.match_tests: TestFilter = ns.match_tests
self.exclude: bool = ns.exclude
self.fromfile: StrPath | None = ns.fromfile
self.starting_test: TestName | None = ns.start
@@ -389,7 +382,7 @@ class Regrtest:
def display_summary(self):
duration = time.perf_counter() - self.logger.start_time
- filtered = bool(self.match_tests) or bool(self.ignore_tests)
+ filtered = bool(self.match_tests)
# Total duration
print()
@@ -407,7 +400,6 @@ class Regrtest:
fail_fast=self.fail_fast,
fail_env_changed=self.fail_env_changed,
match_tests=self.match_tests,
- ignore_tests=self.ignore_tests,
match_tests_dict=None,
rerun=False,
forever=self.forever,
@@ -660,7 +652,6 @@ class Regrtest:
elif self.want_list_cases:
list_cases(selected,
match_tests=self.match_tests,
- ignore_tests=self.ignore_tests,
test_dir=self.test_dir)
else:
exitcode = self.run_tests(selected, tests)
diff --git a/Lib/test/libregrtest/run_workers.py b/Lib/test/libregrtest/run_workers.py
index 16f8331..ab03cb5 100644
--- a/Lib/test/libregrtest/run_workers.py
+++ b/Lib/test/libregrtest/run_workers.py
@@ -261,7 +261,7 @@ class WorkerThread(threading.Thread):
kwargs = {}
if match_tests:
- kwargs['match_tests'] = match_tests
+ kwargs['match_tests'] = [(test, True) for test in match_tests]
if self.runtests.output_on_failure:
kwargs['verbose'] = True
kwargs['output_on_failure'] = False
diff --git a/Lib/test/libregrtest/runtests.py b/Lib/test/libregrtest/runtests.py
index 893b311..bfed1b4 100644
--- a/Lib/test/libregrtest/runtests.py
+++ b/Lib/test/libregrtest/runtests.py
@@ -8,7 +8,7 @@ from typing import Any
from test import support
from .utils import (
- StrPath, StrJSON, TestTuple, FilterTuple, FilterDict)
+ StrPath, StrJSON, TestTuple, TestFilter, FilterTuple, FilterDict)
class JsonFileType:
@@ -72,8 +72,7 @@ class RunTests:
tests: TestTuple
fail_fast: bool
fail_env_changed: bool
- match_tests: FilterTuple | None
- ignore_tests: FilterTuple | None
+ match_tests: TestFilter
match_tests_dict: FilterDict | None
rerun: bool
forever: bool
diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py
index 793347f..6a96b05 100644
--- a/Lib/test/libregrtest/setup.py
+++ b/Lib/test/libregrtest/setup.py
@@ -92,7 +92,7 @@ def setup_tests(runtests: RunTests):
support.PGO = runtests.pgo
support.PGO_EXTENDED = runtests.pgo_extended
- support.set_match_tests(runtests.match_tests, runtests.ignore_tests)
+ support.set_match_tests(runtests.match_tests)
if runtests.use_junit:
support.junit_xml_list = []
diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py
index f62184a..f6de62a 100644
--- a/Lib/test/libregrtest/utils.py
+++ b/Lib/test/libregrtest/utils.py
@@ -52,6 +52,7 @@ TestTuple = tuple[TestName, ...]
TestList = list[TestName]
# --match and --ignore options: list of patterns
# ('*' joker character can be used)
+TestFilter = list[tuple[TestName, bool]]
FilterTuple = tuple[TestName, ...]
FilterDict = dict[TestName, FilterTuple]
diff --git a/Lib/test/libregrtest/worker.py b/Lib/test/libregrtest/worker.py
index a9c8be0..2eccfab 100644
--- a/Lib/test/libregrtest/worker.py
+++ b/Lib/test/libregrtest/worker.py
@@ -10,7 +10,7 @@ from .setup import setup_process, setup_test_dir
from .runtests import RunTests, JsonFile, JsonFileType
from .single import run_single_test
from .utils import (
- StrPath, StrJSON, FilterTuple,
+ StrPath, StrJSON, TestFilter,
get_temp_dir, get_work_dir, exit_timeout)
@@ -73,7 +73,7 @@ def create_worker_process(runtests: RunTests, output_fd: int,
def worker_process(worker_json: StrJSON) -> NoReturn:
runtests = RunTests.from_json(worker_json)
test_name = runtests.tests[0]
- match_tests: FilterTuple | None = runtests.match_tests
+ match_tests: TestFilter = runtests.match_tests
json_file: JsonFile = runtests.json_file
setup_test_dir(runtests.test_dir)
@@ -81,7 +81,7 @@ def worker_process(worker_json: StrJSON) -> NoReturn:
if runtests.rerun:
if match_tests:
- matching = "matching: " + ", ".join(match_tests)
+ matching = "matching: " + ", ".join(pattern for pattern, result in match_tests if result)
print(f"Re-running {test_name} in verbose mode ({matching})", flush=True)
else:
print(f"Re-running {test_name} in verbose mode", flush=True)