Skip to content

Commit 2abe841

Browse files
committed
Add --continue-on-collection-errors and --retag-append
1 parent 594a0db commit 2abe841

File tree

2 files changed

+50
-20
lines changed

2 files changed

+50
-20
lines changed

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

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ def log(self, msg='', incomplete=False):
9393
if self.report_incomplete and self.incomplete_line:
9494
first_line, newline, rest = msg.partition('\n')
9595
pad = len(self.incomplete_line)
96-
print(f"\r{first_line:{pad}}{newline}{rest}", end=end, flush=True)
96+
print(f"\r{first_line:{pad}}{newline}{rest}", file=sys.stderr, end=end, flush=True)
9797
else:
98-
print(msg, end=end, flush=True)
98+
print(msg, file=sys.stderr, end=end, flush=True)
9999
self.incomplete_line = msg if incomplete else None
100100

101101

@@ -178,8 +178,8 @@ class TestResult:
178178
duration: float = 0.0
179179

180180

181-
def format_exception(err):
182-
_, exc, tb = err
181+
def format_exception(exc):
182+
tb = exc.__traceback__
183183
while tb and '__unittest' in tb.tb_frame.f_globals:
184184
tb = tb.tb_next
185185
exc.__traceback__ = tb
@@ -229,19 +229,19 @@ def addSuccess(self, test):
229229

230230
def addFailure(self, test, err):
231231
super().addFailure(test, err)
232-
self.report_result(self.make_result(test, status=TestStatus.FAILURE, param=format_exception(err)))
232+
self.report_result(self.make_result(test, status=TestStatus.FAILURE, param=format_exception(err[1])))
233233

234234
def addError(self, test, err):
235235
super().addError(test, err)
236-
self.report_result(self.make_result(test, status=TestStatus.ERROR, param=format_exception(err)))
236+
self.report_result(self.make_result(test, status=TestStatus.ERROR, param=format_exception(err[1])))
237237

238238
def addSkip(self, test, reason):
239239
super().addSkip(test, reason)
240240
self.report_result(self.make_result(test, status=TestStatus.SKIPPED, param=reason))
241241

242242
def addExpectedFailure(self, test, err):
243243
super().addExpectedFailure(test, err)
244-
self.report_result(self.make_result(test, status=TestStatus.EXPECTED_FAILURE, param=format_exception(err)))
244+
self.report_result(self.make_result(test, status=TestStatus.EXPECTED_FAILURE, param=format_exception(err[1])))
245245

246246
def addUnexpectedSuccess(self, test):
247247
super().addUnexpectedSuccess(test)
@@ -267,7 +267,14 @@ def emit(self, **data):
267267
pass
268268

269269
def report_result(self, result: TestResult):
270-
self.emit(event='testResult', status=result.status, test=result.test_id, param=result.param, out_pos=out_tell())
270+
self.emit(
271+
event='testResult',
272+
status=result.status,
273+
test=result.test_id,
274+
param=result.param,
275+
out_pos=out_tell(),
276+
duration=result.duration,
277+
)
271278

272279
def startTest(self, test):
273280
super().startTest(test)
@@ -403,20 +410,22 @@ def generate_mx_report(self, path: str):
403410
# noinspection PyTypeChecker
404411
json.dump(report_data, f)
405412

406-
def generate_tags(self):
413+
def generate_tags(self, append=False):
407414
by_file = defaultdict(list)
408415
for result in self.results:
409416
by_file[result.test_id.test_file].append(result)
410417
for test_file, results in by_file.items():
411418
config = config_for_file(test_file)
412419
tag_file = config.get_tag_file(test_file)
413420
if not tag_file:
414-
log(f"WARNNING: no tag directory for test file {result.test_id.test_file}")
421+
log(f"WARNNING: no tag directory for test file {test_file}")
415422
continue
423+
tags = {result.test_id.test_name for result in results if result.status == TestStatus.SUCCESS}
424+
if append:
425+
tags |= {test.test_name for test in read_tags(test_file, config)}
416426
with open(tag_file, 'w') as f:
417-
for result in results:
418-
if result.status == TestStatus.SUCCESS:
419-
f.write(f'*graalpython.lib-python.3.{result.test_id.test_name}\n')
427+
for test_name in sorted(tags):
428+
f.write(f'{test_name}\n')
420429

421430

422431
def interrupt_process(process: subprocess.Popen):
@@ -534,6 +543,7 @@ def process_event(event):
534543
status=event['status'],
535544
param=event.get('param'),
536545
output=test_output,
546+
duration=event.get('duration'),
537547
)
538548
self.report_result(result)
539549
last_started_test = None
@@ -754,6 +764,8 @@ def expand_specifier_paths(specifiers: list[TestSpecifier]) -> list[TestSpecifie
754764
else:
755765
expanded_paths += path.rglob("test*.py")
756766
else:
767+
if config.tags_dir and path.name == '__init__.py':
768+
path = path.parent
757769
expanded_paths.append(path)
758770
expanded_paths.sort()
759771
for path in expanded_paths:
@@ -793,7 +805,8 @@ def path_for_comparison(p: Path):
793805
return p.parent / p.name.removesuffix('.py')
794806

795807

796-
def collect(all_specifiers: list[TestSpecifier], *, use_tags=False, ignore=None, partial=None) -> list[TestSuite]:
808+
def collect(all_specifiers: list[TestSpecifier], *, use_tags=False, ignore=None, partial=None,
809+
continue_on_errors=False) -> list[TestSuite]:
797810
to_run = []
798811
all_specifiers = expand_specifier_paths(all_specifiers)
799812
if ignore:
@@ -819,7 +832,13 @@ def collect(all_specifiers: list[TestSpecifier], *, use_tags=False, ignore=None,
819832
for test_file, specifiers in specifiers_by_file.items():
820833
if not test_file.exists():
821834
sys.exit(f"File does not exist: {test_file}")
822-
collected = collect_module(test_file, specifiers, use_tags=use_tags, partial=partial)
835+
try:
836+
collected = collect_module(test_file, specifiers, use_tags=use_tags, partial=partial)
837+
except Exception as e:
838+
if continue_on_errors:
839+
log(f"WARNING: Failed to collect {test_file}:\n{format_exception(e)}")
840+
continue
841+
raise e
823842
if collected:
824843
to_run.append(collected)
825844
return to_run
@@ -887,10 +906,14 @@ def main():
887906
help="Exit immediately after the first failure")
888907
parser.add_argument('--all', action='store_true',
889908
help="Run tests that are normally not enabled due to tags")
890-
parser.add_argument('--retag', action='store_true',
909+
parser.add_argument('--retag', dest='retag_mode', action='store_const', const='replace',
891910
help="Run tests and regenerate tags based on the results. Implies --all, --tagged and -n")
911+
parser.add_argument('--retag-append', dest='retag_mode', action='store_const', const='append',
912+
help="Like --retag, but doesn't remove existing tags. Useful for regtagging subsets of tests")
892913
parser.add_argument('--collect-only', action='store_true',
893914
help="Print found tests IDs without running tests")
915+
parser.add_argument('--continue-on-collection-errors', action='store_true',
916+
help="Collection errors are not fatal")
894917
parser.add_argument('--durations', type=int, default=0,
895918
help="Show durations of N slowest tests (-1 to show all)")
896919
parser.add_argument('--mx-report',
@@ -919,7 +942,7 @@ def main():
919942

920943
args = parser.parse_args()
921944

922-
if args.retag:
945+
if args.retag_mode:
923946
args.all = True
924947
args.tagged = True
925948
args.num_processes = args.num_processes or 1
@@ -951,7 +974,13 @@ def main():
951974
selected_str, total_str = partial_env.split('/', 1)
952975
partial = int(selected_str) - 1, int(total_str)
953976

954-
tests = collect(args.tests, use_tags=(not args.all), ignore=args.ignore, partial=partial)
977+
tests = collect(
978+
args.tests,
979+
use_tags=(not args.all),
980+
ignore=args.ignore,
981+
partial=partial,
982+
continue_on_errors=args.continue_on_collection_errors,
983+
)
955984
if args.collect_only:
956985
for test_suite in tests:
957986
for test in test_suite.collected_tests:
@@ -978,8 +1007,8 @@ def main():
9781007
runner.run_tests(tests)
9791008
if args.mx_report:
9801009
runner.generate_mx_report(args.mx_report)
981-
if args.retag:
982-
runner.generate_tags()
1010+
if args.retag_mode:
1011+
runner.generate_tags(append=(args.retag_mode == 'append'))
9831012
return
9841013
if runner.tests_failed():
9851014
sys.exit(1)

graalpython/lib-python/3/test/conftest.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ serial_tests = [
3030
]
3131
partial_splits_individual_tests = [
3232
'test_multiprocessing_spawn',
33+
'test_multiprocessing_main_handling',
3334
]

0 commit comments

Comments
 (0)