#!/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 run_tests import handle_meson_skip_test from run_project_tests import TestDef, load_test_json, run_test, BuildStep from run_project_tests import setup_commands, detect_system_compiler, detect_tools from run_project_tests import 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()) setup_symlinks() setup_commands(args.backend) if not args.quick: detect_system_compiler(args) detect_tools(not args.quick) test = TestDef(args.case, args.case.stem, []) tests = load_test_json(test, False) 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()