|
|
|
#!/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()
|