Files
meson/run_single_test.py
Jon Turney 1021acec1d run_project_tests: Plumb test category name down into TestDef
Unfortunately, the idiot who wrote bee4dc9f (me!) assumed that the 'test
category' (the 'testsuite' name) is the same as the directory. (That is,
that TestCategory.category == TestCategory.subdir).

These are not the same (e.g. 'failing-test' vs 'failing test' etc.)
which is why they are separate things.

Rather than adding yet another function argument to pass yet another
attribute of the TestCategory object around, just pass the object itself.
2026-03-16 18:38:22 +01:00

109 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright © 2021-2024 Intel Corporation
"""Script for running a single project test.
This script is meant for Meson developers who want to run a single project
test, with all of the rules from the test.json file loaded.
"""
import argparse
import pathlib
import typing as T
from mesonbuild import mlog
from mesonbuild.mesonlib import is_windows
from run_tests import handle_meson_skip_test
from run_project_tests import TestDef, TestCategory, load_test_json, run_test, BuildStep
from run_project_tests import setup_commands, detect_system_compiler, detect_tools
from run_project_tests import scan_test_data_symlinks, setup_symlinks, clear_transitive_files
if T.TYPE_CHECKING:
from run_project_tests import CompilerArgumentType
class ArgumentType(CompilerArgumentType):
"""Typing information for command line arguments."""
case: pathlib.Path
subtests: T.List[int]
backend: str
extra_args: T.List[str]
quick: bool
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('case', type=pathlib.Path, help='The test case to run')
parser.add_argument('extra_args', nargs='*',
help='arguments that are passed directly to Meson (remember to have -- before these).')
parser.add_argument('--subtest', type=int, action='append', dest='subtests', help='which subtests to run')
parser.add_argument('--backend', action='store', help="Which backend to use")
parser.add_argument('--cross-file', action='store', help='File describing cross compilation environment.')
parser.add_argument('--native-file', action='store', help='File describing native compilation environment.')
parser.add_argument('--use-tmpdir', action='store_true', help='Use tmp directory for temporary files.')
parser.add_argument('--quick', action='store_true', help='Skip some compiler and tool checking')
args = T.cast('ArgumentType', parser.parse_args())
if not is_windows():
scan_test_data_symlinks()
setup_symlinks()
setup_commands(args.backend)
if not args.quick:
detect_system_compiler(args)
detect_tools(not args.quick)
cat = TestCategory(args.case.stem, args.case.stem, False, False)
test = TestDef(args.case, None, [], False, cat)
tests = load_test_json(test, cat)
if args.subtests:
tests = [t for i, t in enumerate(tests) if i in args.subtests]
def should_fail(path: pathlib.Path) -> str:
dir_ = path.parent.stem
# FIXME: warning tets might not be handled correctly still…
if dir_.startswith(('failing', 'warning')):
if ' ' in dir_:
return dir_.split(' ')[1]
return 'meson'
return ''
results = [run_test(t, t.args + args.extra_args, should_fail(t.path), args.use_tmpdir) for t in tests]
failed = False
for test, result in zip(tests, results):
if result is None:
is_skipped = True
skip_reason = 'not run because preconditions were not met'
else:
is_skipped, skip_reason = handle_meson_skip_test(result.stdo)
if is_skipped:
msg = mlog.yellow('SKIP:')
elif result.msg:
msg = mlog.red('FAIL:')
failed = True
else:
msg = mlog.green('PASS:')
mlog.log(msg, *test.display_name())
if skip_reason:
mlog.log(mlog.bold('Reason:'), skip_reason)
if result is not None and result.msg and 'MESON_SKIP_TEST' not in result.stdo:
mlog.log('reason:', result.msg)
if result.step is BuildStep.configure:
# For configure failures, instead of printing stdout,
# print the meson log if available since it's a superset
# of stdout and often has very useful information.
mlog.log(result.mlog)
else:
mlog.log(result.stdo)
for cmd_res in result.cicmds:
mlog.log(cmd_res)
mlog.log(result.stde)
clear_transitive_files()
exit(1 if failed else 0)
if __name__ == "__main__":
main()