Skip to content

Commit d91df93

Browse files
committed
Move platform test excludes from mx to runner
1 parent 9abc3b9 commit d91df93

File tree

3 files changed

+103
-87
lines changed

3 files changed

+103
-87
lines changed

graalpython/com.oracle.graal.python.test/src/runner.py

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
import unittest.loader
6060
from abc import abstractmethod
6161
from collections import defaultdict
62-
from dataclasses import dataclass
62+
from dataclasses import dataclass, field
6363
from functools import lru_cache
6464
from pathlib import Path
6565

@@ -679,21 +679,34 @@ class Config:
679679
new_worker_per_file: bool = False
680680
serial_tests: frozenset[str] = frozenset()
681681
partial_splits_individual_tests: frozenset[str] = frozenset()
682+
excludes: dict[str, frozenset[str]] = field(default_factory=dict)
682683

683-
def is_serial_test(self, test_file: Path):
684+
def test_file_name(self, test_file):
684685
resolved = test_file.resolve().relative_to(self.configdir)
685-
name = str(resolved).removesuffix('.py')
686-
return name in self.serial_tests
686+
return str(resolved).removesuffix('.py')
687+
688+
def is_serial_test(self, test_file: Path):
689+
return self.test_file_name(test_file) in self.serial_tests
687690

688691
def is_partial_splits_individual_tests(self, test_file: Path):
689-
resolved = test_file.resolve().relative_to(self.configdir)
690-
name = str(resolved).removesuffix('.py')
691-
return name in self.partial_splits_individual_tests
692+
return self.test_file_name(test_file) in self.partial_splits_individual_tests
692693

693694
def get_tag_file(self, test_file: Path):
694695
if self.tags_dir:
695696
return self.tags_dir / (test_file.name.removesuffix('.py') + '.txt')
696697

698+
def is_excluded(self, test_file: Path):
699+
exclude_keys = [sys.platform]
700+
if IS_GRAALPY:
701+
# noinspection PyUnresolvedReferences
702+
exclude_keys.append('native_image' if __graalpython__.is_native else 'jvm')
703+
test_file_name = self.test_file_name(test_file)
704+
for key in exclude_keys:
705+
if excludes := self.excludes.get(key):
706+
if test_file_name in excludes:
707+
return True
708+
return False
709+
697710

698711
@lru_cache
699712
def config_for_dir(path: Path) -> Config:
@@ -712,6 +725,10 @@ def config_for_file(test_file: Path) -> Config:
712725
return config_for_dir(path)
713726

714727

728+
def test_file_name_set(test_files: list[str]):
729+
return frozenset({test_file.removesuffix('.py') for test_file in test_files})
730+
731+
715732
@lru_cache
716733
def parse_config(config_path, path):
717734
with open(config_path, 'rb') as f:
@@ -725,10 +742,11 @@ def parse_config(config_path, path):
725742
tags_dir=tags_dir,
726743
run_top_level_functions=config_dict.get('run_top_level_functions', Config.run_top_level_functions),
727744
new_worker_per_file=config_dict.get('new_worker_per_file', Config.new_worker_per_file),
728-
serial_tests=frozenset(config_dict.get('serial_tests', Config.serial_tests)),
729-
partial_splits_individual_tests=frozenset(
745+
serial_tests=test_file_name_set(config_dict.get('serial_tests', Config.serial_tests)),
746+
partial_splits_individual_tests=test_file_name_set(
730747
config_dict.get('partial_splits_individual_tests', Config.partial_splits_individual_tests)
731748
),
749+
excludes={key: test_file_name_set(excludes) for key, excludes in config_dict.get('excludes', {}).items()},
732750
)
733751

734752

@@ -827,16 +845,21 @@ def path_for_comparison(p: Path):
827845

828846

829847
def collect(all_specifiers: list[TestSpecifier], *, use_tags=False, ignore=None, partial=None,
830-
continue_on_errors=False) -> list[TestSuite]:
848+
continue_on_errors=False, no_excludes=False) -> list[TestSuite]:
831849
to_run = []
832850
all_specifiers = expand_specifier_paths(all_specifiers)
851+
specifiers_by_file = group_specifiers_by_file(all_specifiers)
833852
if ignore:
834853
ignore = [path_for_comparison(i) for i in ignore]
835-
all_specifiers = [
836-
s for s in all_specifiers
837-
if not any(path_for_comparison(s.test_file).is_relative_to(i) for i in ignore)
838-
]
839-
specifiers_by_file = group_specifiers_by_file(all_specifiers)
854+
for test_file in set(specifiers_by_file):
855+
if any(path_for_comparison(test_file).is_relative_to(i) for i in ignore):
856+
del specifiers_by_file[test_file]
857+
if not no_excludes:
858+
for test_file in set(specifiers_by_file):
859+
config = config_for_file(test_file)
860+
if config.is_excluded(test_file):
861+
log(f"Test file {test_file} is excluded on this platform/configuration, use --no-excludes to overrride")
862+
del specifiers_by_file[test_file]
840863
if partial:
841864
selected, total = partial
842865
to_split = []
@@ -910,7 +933,7 @@ def result_factory(suite):
910933
def result_factory(suite):
911934
return SimpleResult(suite, data)
912935

913-
for test_suite in collect(tests):
936+
for test_suite in collect(tests, no_excludes=True):
914937
result = result_factory(test_suite)
915938
result.failfast = args.failfast
916939
test_suite.run(result)
@@ -939,6 +962,8 @@ def main():
939962
help="Create a new worker process for each test file (when -n is specified). Default for tagged unit tests")
940963
parser.add_argument('--ignore', type=Path, action='append', default=[],
941964
help="Ignore path during collection (multi-allowed)")
965+
parser.add_argument('--no-excludes', action='store_true',
966+
help="Don't apply configuration exclusions")
942967
parser.add_argument('-f', '--failfast', action='store_true',
943968
help="Exit immediately after the first failure")
944969
parser.add_argument('--all', action='store_true',
@@ -1017,6 +1042,7 @@ def main():
10171042
ignore=args.ignore,
10181043
partial=partial,
10191044
continue_on_errors=args.continue_on_collection_errors,
1045+
no_excludes=args.no_excludes,
10201046
)
10211047
if args.collect_only:
10221048
for test_suite in tests:

graalpython/com.oracle.graal.python.test/src/tests/conftest.toml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,54 @@ partial_splits_individual_tests = [
44
'standalone/test_standalone',
55
'standalone/test_jbang_integration',
66
]
7+
[tests.excludes]
8+
# Windows support is still experimental, so we exclude some unittests
9+
# on Windows for now. If you add unittests and cannot get them to work
10+
# on Windows, yet, add their files here.
11+
win32 = [
12+
"test_code.py", # forward slash in path problem
13+
"test_csv.py",
14+
"test_imports.py", # import posix
15+
"test_locale.py",
16+
"test_math.py",
17+
"test_memoryview.py",
18+
"test_mmap.py", # sys.getwindowsversion
19+
"test_multiprocessing.py", # import _winapi
20+
"test_multiprocessing_graalpy.py", # import _winapi
21+
"test_patched_pip.py",
22+
"test_pathlib.py",
23+
"test_pdb.py", # Tends to hit GR-41935
24+
"test_posix.py", # import posix
25+
"test_pyio.py",
26+
"test_signal.py",
27+
"test_struct.py",
28+
"test_structseq.py", # import posix
29+
"test_subprocess.py",
30+
"test_thread.py", # sys.getwindowsversion
31+
"test_traceback.py",
32+
"test_zipimport.py", # sys.getwindowsversion
33+
"test_ssl_java_integration.py",
34+
"cpyext/test_abstract.py",
35+
"cpyext/test_functions.py",
36+
"cpyext/test_long.py",
37+
"cpyext/test_member.py",
38+
"cpyext/test_memoryview.py",
39+
"cpyext/test_misc.py",
40+
"cpyext/test_mmap.py",
41+
"cpyext/test_slice.py",
42+
"cpyext/test_shutdown.py",
43+
"cpyext/test_thread.py",
44+
"cpyext/test_unicode.py",
45+
"cpyext/test_wiki.py",
46+
"cpyext/test_tp_slots.py", # Temporarily disabled due to GR-54345
47+
]
48+
native_image = [
49+
"test_interop.py",
50+
"test_register_interop_behavior.py",
51+
"test_jarray.py",
52+
"test_ssl_java_integration.py",
53+
]
54+
jvm = [
55+
# These test would work on JVM too, but they are prohibitively slow due to a large amount of subprocesses
56+
"test_patched_pip.py",
57+
]

mx.graalpython/mx_graalpython.py

Lines changed: 10 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -757,17 +757,6 @@ def update_unittest_tags(args):
757757
mx.warn("Potential regressions:\n" + '\n'.join(x[1] for x in diff))
758758

759759

760-
AOT_INCOMPATIBLE_TESTS = ["test_interop.py", "test_register_interop_behavior.py", "test_jarray.py", "test_ssl_java_integration.py"]
761-
# These test would work on JVM too, but they are prohibitively slow due to a large amount of subprocesses
762-
AOT_ONLY_TESTS = ["test_patched_pip.py", "test_multiprocessing_spawn.py"]
763-
764-
GINSTALL_GATE_PACKAGES = {
765-
"numpy": "numpy",
766-
"scipy": "scipy",
767-
"scikit_learn": "sklearn",
768-
}
769-
770-
771760
class GraalPythonTags(object):
772761
junit = 'python-junit'
773762
junit_maven = 'python-junit-maven'
@@ -1162,7 +1151,7 @@ def is_included(path):
11621151
return testfiles
11631152

11641153

1165-
def run_python_unittests(python_binary, args=None, paths=None, aot_compatible=False, exclude=None, env=None,
1154+
def run_python_unittests(python_binary, args=None, paths=None, exclude=None, env=None,
11661155
use_pytest=False, cwd=None, lock=None, out=None, err=None, nonZeroIsFatal=True, timeout=None,
11671156
report=False, parallel=1, runner_args=None):
11681157
if lock:
@@ -1175,7 +1164,6 @@ def run_python_unittests(python_binary, args=None, paths=None, aot_compatible=Fa
11751164
"--python.EnableDebuggingBuiltins",
11761165
*args,
11771166
]
1178-
exclude = exclude or []
11791167
if env is None:
11801168
env = os.environ.copy()
11811169
env['PYTHONHASHSEED'] = '0'
@@ -1184,12 +1172,6 @@ def run_python_unittests(python_binary, args=None, paths=None, aot_compatible=Fa
11841172
if mx.primary_suite() != SUITE:
11851173
env.setdefault("GRAALPYTEST_ALLOW_NO_JAVA_ASSERTIONS", "true")
11861174

1187-
# list of excluded tests
1188-
if aot_compatible:
1189-
exclude += AOT_INCOMPATIBLE_TESTS
1190-
else:
1191-
exclude += AOT_ONLY_TESTS
1192-
11931175
# just to be able to verify, print C ext mode (also works for CPython)
11941176
mx.run(
11951177
[
@@ -1209,8 +1191,9 @@ def run_python_unittests(python_binary, args=None, paths=None, aot_compatible=Fa
12091191
if runner_args:
12101192
args += runner_args
12111193

1212-
for file in exclude:
1213-
args += ['--ignore', file]
1194+
if exclude:
1195+
for file in exclude:
1196+
args += ['--ignore', file]
12141197

12151198
if is_collecting_coverage() and mx_gate.get_jacoco_agent_args():
12161199
# jacoco only dumps the data on exit, and when we run all our unittests
@@ -1386,49 +1369,6 @@ def get_wrapper_urls(wrapper_properties_file, keys):
13861369
def graalpython_gate_runner(args, tasks):
13871370
report = lambda: (not is_collecting_coverage()) and task
13881371
nonZeroIsFatal = not is_collecting_coverage()
1389-
if WIN32:
1390-
# Windows support is still experimental, so we exclude some unittests
1391-
# on Windows for now. If you add unittests and cannot get them to work
1392-
# on Windows, yet, add their files here.
1393-
excluded_tests = [
1394-
"test_code.py", # forward slash in path problem
1395-
"test_csv.py",
1396-
"test_imports.py", # import posix
1397-
"test_locale.py",
1398-
"test_math.py",
1399-
"test_memoryview.py",
1400-
"test_mmap.py", # sys.getwindowsversion
1401-
"test_multiprocessing.py", # import _winapi
1402-
"test_multiprocessing_graalpy.py", # import _winapi
1403-
"test_patched_pip.py",
1404-
"test_pathlib.py",
1405-
"test_pdb.py", # Tends to hit GR-41935
1406-
"test_posix.py", # import posix
1407-
"test_pyio.py",
1408-
"test_signal.py",
1409-
"test_struct.py",
1410-
"test_structseq.py", # import posix
1411-
"test_subprocess.py",
1412-
"test_thread.py", # sys.getwindowsversion
1413-
"test_traceback.py",
1414-
"test_zipimport.py", # sys.getwindowsversion
1415-
"test_ssl_java_integration.py",
1416-
"cpyext/test_abstract.py",
1417-
"cpyext/test_functions.py",
1418-
"cpyext/test_long.py",
1419-
"cpyext/test_member.py",
1420-
"cpyext/test_memoryview.py",
1421-
"cpyext/test_misc.py",
1422-
"cpyext/test_mmap.py",
1423-
"cpyext/test_slice.py",
1424-
"cpyext/test_shutdown.py",
1425-
"cpyext/test_thread.py",
1426-
"cpyext/test_unicode.py",
1427-
"cpyext/test_wiki.py",
1428-
"cpyext/test_tp_slots.py", # Temporarily disabled due to GR-54345
1429-
]
1430-
else:
1431-
excluded_tests = []
14321372

14331373
# JUnit tests
14341374
with Task('GraalPython JUnit', tasks, tags=[GraalPythonTags.junit, GraalPythonTags.windows]) as task:
@@ -1480,7 +1420,6 @@ def graalpython_gate_runner(args, tasks):
14801420
if task:
14811421
run_python_unittests(
14821422
graalpy_standalone_jvm(),
1483-
exclude=excluded_tests,
14841423
nonZeroIsFatal=nonZeroIsFatal,
14851424
report=report()
14861425
)
@@ -1493,11 +1432,11 @@ def graalpython_gate_runner(args, tasks):
14931432

14941433
with Task('GraalPython sandboxed tests', tasks, tags=[GraalPythonTags.unittest_sandboxed]) as task:
14951434
if task:
1496-
run_python_unittests(graalpy_standalone_jvm_enterprise(), args=SANDBOXED_OPTIONS, exclude=excluded_tests, report=report())
1435+
run_python_unittests(graalpy_standalone_jvm_enterprise(), args=SANDBOXED_OPTIONS, report=report())
14971436

14981437
with Task('GraalPython multi-context unittests', tasks, tags=[GraalPythonTags.unittest_multi]) as task:
14991438
if task:
1500-
run_python_unittests(graalpy_standalone_jvm(), args=["-multi-context"], exclude=excluded_tests, nonZeroIsFatal=nonZeroIsFatal, report=report())
1439+
run_python_unittests(graalpy_standalone_jvm(), args=["-multi-context"], nonZeroIsFatal=nonZeroIsFatal, report=report())
15011440

15021441
with Task('GraalPython Jython emulation tests', tasks, tags=[GraalPythonTags.unittest_jython]) as task:
15031442
if task:
@@ -1577,11 +1516,11 @@ def graalpython_gate_runner(args, tasks):
15771516
# Unittests on SVM
15781517
with Task('GraalPython tests on SVM', tasks, tags=[GraalPythonTags.svmunit, GraalPythonTags.windows]) as task:
15791518
if task:
1580-
run_python_unittests(graalpy_standalone_native(), exclude=excluded_tests, aot_compatible=True, report=report())
1519+
run_python_unittests(graalpy_standalone_native(), report=report())
15811520

15821521
with Task('GraalPython sandboxed tests on SVM', tasks, tags=[GraalPythonTags.svmunit_sandboxed]) as task:
15831522
if task:
1584-
run_python_unittests(graalpy_standalone_native_enterprise(), args=SANDBOXED_OPTIONS, aot_compatible=True, report=report())
1523+
run_python_unittests(graalpy_standalone_native_enterprise(), args=SANDBOXED_OPTIONS, report=report())
15851524

15861525
with Task('GraalPython license header update', tasks, tags=[GraalPythonTags.license]) as task:
15871526
if task:
@@ -2601,13 +2540,13 @@ def python_coverage(args):
26012540
]
26022541
env['GRAAL_PYTHON_ARGS'] = " ".join(extra_args)
26032542
# deselect some tagged unittests that hang with coverage enabled
2604-
exclude = [
2543+
tagged_exclude = [
26052544
"test_multiprocessing_spawn",
26062545
"test_multiprocessing_main_handling",
26072546
"test_multiprocessing_graalpy",
26082547
]
26092548
if kwds.pop("tagged", False):
2610-
run_tagged_unittests(executable, env=env, nonZeroIsFatal=False, parallel=1, exclude=exclude)
2549+
run_tagged_unittests(executable, env=env, nonZeroIsFatal=False, parallel=1, exclude=tagged_exclude)
26112550
elif kwds.pop("hpy", False):
26122551
run_hpy_unittests(executable, env=env, nonZeroIsFatal=False, timeout=5*60*60) # hpy unittests are really slow under coverage
26132552
else:

0 commit comments

Comments
 (0)