1c25ce589SFinn Behrens#!/usr/bin/env python3 26ebf5866SFelix Guo# SPDX-License-Identifier: GPL-2.0 36ebf5866SFelix Guo# 46ebf5866SFelix Guo# A thin wrapper on top of the KUnit Kernel 56ebf5866SFelix Guo# 66ebf5866SFelix Guo# Copyright (C) 2019, Google LLC. 76ebf5866SFelix Guo# Author: Felix Guo <felixguoxiuping@gmail.com> 86ebf5866SFelix Guo# Author: Brendan Higgins <brendanhiggins@google.com> 96ebf5866SFelix Guo 106ebf5866SFelix Guoimport argparse 116ebf5866SFelix Guoimport sys 126ebf5866SFelix Guoimport os 136ebf5866SFelix Guoimport time 146ebf5866SFelix Guo 15*df4b0807SSeongJae Parkassert sys.version_info >= (3, 7), "Python version is too old" 16*df4b0807SSeongJae Park 176ebf5866SFelix Guofrom collections import namedtuple 186ebf5866SFelix Guofrom enum import Enum, auto 196ebf5866SFelix Guo 206ebf5866SFelix Guoimport kunit_config 2121a6d178SHeidi Fahimimport kunit_json 226ebf5866SFelix Guoimport kunit_kernel 236ebf5866SFelix Guoimport kunit_parser 246ebf5866SFelix Guo 2545ba7a89SDavid GowKunitResult = namedtuple('KunitResult', ['status','result','elapsed_time']) 266ebf5866SFelix Guo 2745ba7a89SDavid GowKunitConfigRequest = namedtuple('KunitConfigRequest', 2801397e82SVitor Massaru Iha ['build_dir', 'make_options']) 2945ba7a89SDavid GowKunitBuildRequest = namedtuple('KunitBuildRequest', 3045ba7a89SDavid Gow ['jobs', 'build_dir', 'alltests', 3145ba7a89SDavid Gow 'make_options']) 3245ba7a89SDavid GowKunitExecRequest = namedtuple('KunitExecRequest', 33d992880bSDaniel Latypov ['timeout', 'build_dir', 'alltests', 'filter_glob']) 3445ba7a89SDavid GowKunitParseRequest = namedtuple('KunitParseRequest', 3521a6d178SHeidi Fahim ['raw_output', 'input_data', 'build_dir', 'json']) 36021ed9f5SHeidi FahimKunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 37d992880bSDaniel Latypov 'build_dir', 'alltests', 'filter_glob', 38d992880bSDaniel Latypov 'json', 'make_options']) 396ebf5866SFelix Guo 40be886ba9SHeidi FahimKernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0] 41be886ba9SHeidi Fahim 426ebf5866SFelix Guoclass KunitStatus(Enum): 436ebf5866SFelix Guo SUCCESS = auto() 446ebf5866SFelix Guo CONFIG_FAILURE = auto() 456ebf5866SFelix Guo BUILD_FAILURE = auto() 466ebf5866SFelix Guo TEST_FAILURE = auto() 476ebf5866SFelix Guo 4809641f7cSDaniel Latypovdef get_kernel_root_path() -> str: 4909641f7cSDaniel Latypov path = sys.argv[0] if not __file__ else __file__ 5009641f7cSDaniel Latypov parts = os.path.realpath(path).split('tools/testing/kunit') 51be886ba9SHeidi Fahim if len(parts) != 2: 52be886ba9SHeidi Fahim sys.exit(1) 53be886ba9SHeidi Fahim return parts[0] 54be886ba9SHeidi Fahim 5545ba7a89SDavid Gowdef config_tests(linux: kunit_kernel.LinuxSourceTree, 5645ba7a89SDavid Gow request: KunitConfigRequest) -> KunitResult: 5745ba7a89SDavid Gow kunit_parser.print_with_timestamp('Configuring KUnit Kernel ...') 5845ba7a89SDavid Gow 596ebf5866SFelix Guo config_start = time.time() 600476e69fSGreg Thelen success = linux.build_reconfig(request.build_dir, request.make_options) 616ebf5866SFelix Guo config_end = time.time() 626ebf5866SFelix Guo if not success: 6345ba7a89SDavid Gow return KunitResult(KunitStatus.CONFIG_FAILURE, 6445ba7a89SDavid Gow 'could not configure kernel', 6545ba7a89SDavid Gow config_end - config_start) 6645ba7a89SDavid Gow return KunitResult(KunitStatus.SUCCESS, 6745ba7a89SDavid Gow 'configured kernel successfully', 6845ba7a89SDavid Gow config_end - config_start) 696ebf5866SFelix Guo 7045ba7a89SDavid Gowdef build_tests(linux: kunit_kernel.LinuxSourceTree, 7145ba7a89SDavid Gow request: KunitBuildRequest) -> KunitResult: 726ebf5866SFelix Guo kunit_parser.print_with_timestamp('Building KUnit Kernel ...') 736ebf5866SFelix Guo 746ebf5866SFelix Guo build_start = time.time() 7587c9c163SBrendan Higgins success = linux.build_kernel(request.alltests, 76021ed9f5SHeidi Fahim request.jobs, 770476e69fSGreg Thelen request.build_dir, 780476e69fSGreg Thelen request.make_options) 796ebf5866SFelix Guo build_end = time.time() 806ebf5866SFelix Guo if not success: 81ee61492aSDavid Gow return KunitResult(KunitStatus.BUILD_FAILURE, 82ee61492aSDavid Gow 'could not build kernel', 83ee61492aSDavid Gow build_end - build_start) 8445ba7a89SDavid Gow if not success: 8545ba7a89SDavid Gow return KunitResult(KunitStatus.BUILD_FAILURE, 8645ba7a89SDavid Gow 'could not build kernel', 8745ba7a89SDavid Gow build_end - build_start) 8845ba7a89SDavid Gow return KunitResult(KunitStatus.SUCCESS, 8945ba7a89SDavid Gow 'built kernel successfully', 9045ba7a89SDavid Gow build_end - build_start) 916ebf5866SFelix Guo 9245ba7a89SDavid Gowdef exec_tests(linux: kunit_kernel.LinuxSourceTree, 9345ba7a89SDavid Gow request: KunitExecRequest) -> KunitResult: 946ebf5866SFelix Guo kunit_parser.print_with_timestamp('Starting KUnit Kernel ...') 956ebf5866SFelix Guo test_start = time.time() 9645ba7a89SDavid Gow result = linux.run_kernel( 97021ed9f5SHeidi Fahim timeout=None if request.alltests else request.timeout, 98d992880bSDaniel Latypov filter_glob=request.filter_glob, 996ec1b81dSSeongJae Park build_dir=request.build_dir) 10045ba7a89SDavid Gow 1016ebf5866SFelix Guo test_end = time.time() 1026ebf5866SFelix Guo 10345ba7a89SDavid Gow return KunitResult(KunitStatus.SUCCESS, 10445ba7a89SDavid Gow result, 10545ba7a89SDavid Gow test_end - test_start) 10645ba7a89SDavid Gow 10745ba7a89SDavid Gowdef parse_tests(request: KunitParseRequest) -> KunitResult: 10845ba7a89SDavid Gow parse_start = time.time() 10945ba7a89SDavid Gow 11045ba7a89SDavid Gow test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS, 11145ba7a89SDavid Gow [], 11245ba7a89SDavid Gow 'Tests not Parsed.') 11321a6d178SHeidi Fahim 11445ba7a89SDavid Gow if request.raw_output: 11545ba7a89SDavid Gow kunit_parser.raw_output(request.input_data) 11645ba7a89SDavid Gow else: 11745ba7a89SDavid Gow test_result = kunit_parser.parse_run_tests(request.input_data) 11845ba7a89SDavid Gow parse_end = time.time() 11945ba7a89SDavid Gow 12021a6d178SHeidi Fahim if request.json: 12121a6d178SHeidi Fahim json_obj = kunit_json.get_json_result( 12221a6d178SHeidi Fahim test_result=test_result, 12321a6d178SHeidi Fahim def_config='kunit_defconfig', 12421a6d178SHeidi Fahim build_dir=request.build_dir, 12521a6d178SHeidi Fahim json_path=request.json) 12621a6d178SHeidi Fahim if request.json == 'stdout': 12721a6d178SHeidi Fahim print(json_obj) 12821a6d178SHeidi Fahim 12945ba7a89SDavid Gow if test_result.status != kunit_parser.TestStatus.SUCCESS: 13045ba7a89SDavid Gow return KunitResult(KunitStatus.TEST_FAILURE, test_result, 13145ba7a89SDavid Gow parse_end - parse_start) 13245ba7a89SDavid Gow 13345ba7a89SDavid Gow return KunitResult(KunitStatus.SUCCESS, test_result, 13445ba7a89SDavid Gow parse_end - parse_start) 13545ba7a89SDavid Gow 13645ba7a89SDavid Gow 13745ba7a89SDavid Gowdef run_tests(linux: kunit_kernel.LinuxSourceTree, 13845ba7a89SDavid Gow request: KunitRequest) -> KunitResult: 13945ba7a89SDavid Gow run_start = time.time() 14045ba7a89SDavid Gow 14145ba7a89SDavid Gow config_request = KunitConfigRequest(request.build_dir, 14245ba7a89SDavid Gow request.make_options) 14345ba7a89SDavid Gow config_result = config_tests(linux, config_request) 14445ba7a89SDavid Gow if config_result.status != KunitStatus.SUCCESS: 14545ba7a89SDavid Gow return config_result 14645ba7a89SDavid Gow 14745ba7a89SDavid Gow build_request = KunitBuildRequest(request.jobs, request.build_dir, 14845ba7a89SDavid Gow request.alltests, 14945ba7a89SDavid Gow request.make_options) 15045ba7a89SDavid Gow build_result = build_tests(linux, build_request) 15145ba7a89SDavid Gow if build_result.status != KunitStatus.SUCCESS: 15245ba7a89SDavid Gow return build_result 15345ba7a89SDavid Gow 15445ba7a89SDavid Gow exec_request = KunitExecRequest(request.timeout, request.build_dir, 155d992880bSDaniel Latypov request.alltests, request.filter_glob) 15645ba7a89SDavid Gow exec_result = exec_tests(linux, exec_request) 15745ba7a89SDavid Gow if exec_result.status != KunitStatus.SUCCESS: 15845ba7a89SDavid Gow return exec_result 15945ba7a89SDavid Gow 16045ba7a89SDavid Gow parse_request = KunitParseRequest(request.raw_output, 16121a6d178SHeidi Fahim exec_result.result, 16221a6d178SHeidi Fahim request.build_dir, 16321a6d178SHeidi Fahim request.json) 16445ba7a89SDavid Gow parse_result = parse_tests(parse_request) 16545ba7a89SDavid Gow 16645ba7a89SDavid Gow run_end = time.time() 16745ba7a89SDavid Gow 1686ebf5866SFelix Guo kunit_parser.print_with_timestamp(( 1696ebf5866SFelix Guo 'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' + 1706ebf5866SFelix Guo 'building, %.3fs running\n') % ( 17145ba7a89SDavid Gow run_end - run_start, 17245ba7a89SDavid Gow config_result.elapsed_time, 17345ba7a89SDavid Gow build_result.elapsed_time, 17445ba7a89SDavid Gow exec_result.elapsed_time)) 17545ba7a89SDavid Gow return parse_result 1766ebf5866SFelix Guo 17709641f7cSDaniel Latypovdef add_common_opts(parser) -> None: 17845ba7a89SDavid Gow parser.add_argument('--build_dir', 17945ba7a89SDavid Gow help='As in the make command, it specifies the build ' 18045ba7a89SDavid Gow 'directory.', 181ddbd60c7SVitor Massaru Iha type=str, default='.kunit', metavar='build_dir') 18245ba7a89SDavid Gow parser.add_argument('--make_options', 18345ba7a89SDavid Gow help='X=Y make option, can be repeated.', 18445ba7a89SDavid Gow action='append') 18545ba7a89SDavid Gow parser.add_argument('--alltests', 18645ba7a89SDavid Gow help='Run all KUnit tests through allyesconfig', 1876ebf5866SFelix Guo action='store_true') 188243180f5SDaniel Latypov parser.add_argument('--kunitconfig', 1899854781dSDaniel Latypov help='Path to Kconfig fragment that enables KUnit tests.' 1909854781dSDaniel Latypov ' If given a directory, (e.g. lib/kunit), "/.kunitconfig" ' 1919854781dSDaniel Latypov 'will get automatically appended.', 192243180f5SDaniel Latypov metavar='kunitconfig') 1936ebf5866SFelix Guo 19487c9c163SBrendan Higgins parser.add_argument('--arch', 19587c9c163SBrendan Higgins help=('Specifies the architecture to run tests under. ' 19687c9c163SBrendan Higgins 'The architecture specified here must match the ' 19787c9c163SBrendan Higgins 'string passed to the ARCH make param, ' 19887c9c163SBrendan Higgins 'e.g. i386, x86_64, arm, um, etc. Non-UML ' 19987c9c163SBrendan Higgins 'architectures run on QEMU.'), 20087c9c163SBrendan Higgins type=str, default='um', metavar='arch') 20187c9c163SBrendan Higgins 20287c9c163SBrendan Higgins parser.add_argument('--cross_compile', 20387c9c163SBrendan Higgins help=('Sets make\'s CROSS_COMPILE variable; it should ' 20487c9c163SBrendan Higgins 'be set to a toolchain path prefix (the prefix ' 20587c9c163SBrendan Higgins 'of gcc and other tools in your toolchain, for ' 20687c9c163SBrendan Higgins 'example `sparc64-linux-gnu-` if you have the ' 20787c9c163SBrendan Higgins 'sparc toolchain installed on your system, or ' 20887c9c163SBrendan Higgins '`$HOME/toolchains/microblaze/gcc-9.2.0-nolibc/microblaze-linux/bin/microblaze-linux-` ' 20987c9c163SBrendan Higgins 'if you have downloaded the microblaze toolchain ' 21087c9c163SBrendan Higgins 'from the 0-day website to a directory in your ' 21187c9c163SBrendan Higgins 'home directory called `toolchains`).'), 21287c9c163SBrendan Higgins metavar='cross_compile') 21387c9c163SBrendan Higgins 21487c9c163SBrendan Higgins parser.add_argument('--qemu_config', 21587c9c163SBrendan Higgins help=('Takes a path to a path to a file containing ' 21687c9c163SBrendan Higgins 'a QemuArchParams object.'), 21787c9c163SBrendan Higgins type=str, metavar='qemu_config') 21887c9c163SBrendan Higgins 21909641f7cSDaniel Latypovdef add_build_opts(parser) -> None: 22045ba7a89SDavid Gow parser.add_argument('--jobs', 22145ba7a89SDavid Gow help='As in the make command, "Specifies the number of ' 22245ba7a89SDavid Gow 'jobs (commands) to run simultaneously."', 22345ba7a89SDavid Gow type=int, default=8, metavar='jobs') 22445ba7a89SDavid Gow 22509641f7cSDaniel Latypovdef add_exec_opts(parser) -> None: 22645ba7a89SDavid Gow parser.add_argument('--timeout', 2276ebf5866SFelix Guo help='maximum number of seconds to allow for all tests ' 2286ebf5866SFelix Guo 'to run. This does not include time taken to build the ' 2296ebf5866SFelix Guo 'tests.', 2306ebf5866SFelix Guo type=int, 2316ebf5866SFelix Guo default=300, 2326ebf5866SFelix Guo metavar='timeout') 233d992880bSDaniel Latypov parser.add_argument('filter_glob', 234d992880bSDaniel Latypov help='maximum number of seconds to allow for all tests ' 235d992880bSDaniel Latypov 'to run. This does not include time taken to build the ' 236d992880bSDaniel Latypov 'tests.', 237d992880bSDaniel Latypov type=str, 238d992880bSDaniel Latypov nargs='?', 239d992880bSDaniel Latypov default='', 240d992880bSDaniel Latypov metavar='filter_glob') 2416ebf5866SFelix Guo 24209641f7cSDaniel Latypovdef add_parse_opts(parser) -> None: 24345ba7a89SDavid Gow parser.add_argument('--raw_output', help='don\'t format output from kernel', 244ff7b437fSBrendan Higgins action='store_true') 24521a6d178SHeidi Fahim parser.add_argument('--json', 24621a6d178SHeidi Fahim nargs='?', 24721a6d178SHeidi Fahim help='Stores test results in a JSON, and either ' 24821a6d178SHeidi Fahim 'prints to stdout or saves to file if a ' 24921a6d178SHeidi Fahim 'filename is specified', 25021a6d178SHeidi Fahim type=str, const='stdout', default=None) 251021ed9f5SHeidi Fahim 25245ba7a89SDavid Gowdef main(argv, linux=None): 25345ba7a89SDavid Gow parser = argparse.ArgumentParser( 25445ba7a89SDavid Gow description='Helps writing and running KUnit tests.') 25545ba7a89SDavid Gow subparser = parser.add_subparsers(dest='subcommand') 25645ba7a89SDavid Gow 25745ba7a89SDavid Gow # The 'run' command will config, build, exec, and parse in one go. 25845ba7a89SDavid Gow run_parser = subparser.add_parser('run', help='Runs KUnit tests.') 25945ba7a89SDavid Gow add_common_opts(run_parser) 26045ba7a89SDavid Gow add_build_opts(run_parser) 26145ba7a89SDavid Gow add_exec_opts(run_parser) 26245ba7a89SDavid Gow add_parse_opts(run_parser) 26345ba7a89SDavid Gow 26445ba7a89SDavid Gow config_parser = subparser.add_parser('config', 26545ba7a89SDavid Gow help='Ensures that .config contains all of ' 26645ba7a89SDavid Gow 'the options in .kunitconfig') 26745ba7a89SDavid Gow add_common_opts(config_parser) 26845ba7a89SDavid Gow 26945ba7a89SDavid Gow build_parser = subparser.add_parser('build', help='Builds a kernel with KUnit tests') 27045ba7a89SDavid Gow add_common_opts(build_parser) 27145ba7a89SDavid Gow add_build_opts(build_parser) 27245ba7a89SDavid Gow 27345ba7a89SDavid Gow exec_parser = subparser.add_parser('exec', help='Run a kernel with KUnit tests') 27445ba7a89SDavid Gow add_common_opts(exec_parser) 27545ba7a89SDavid Gow add_exec_opts(exec_parser) 27645ba7a89SDavid Gow add_parse_opts(exec_parser) 27745ba7a89SDavid Gow 27845ba7a89SDavid Gow # The 'parse' option is special, as it doesn't need the kernel source 27945ba7a89SDavid Gow # (therefore there is no need for a build_dir, hence no add_common_opts) 28045ba7a89SDavid Gow # and the '--file' argument is not relevant to 'run', so isn't in 28145ba7a89SDavid Gow # add_parse_opts() 28245ba7a89SDavid Gow parse_parser = subparser.add_parser('parse', 28345ba7a89SDavid Gow help='Parses KUnit results from a file, ' 28445ba7a89SDavid Gow 'and parses formatted results.') 28545ba7a89SDavid Gow add_parse_opts(parse_parser) 28645ba7a89SDavid Gow parse_parser.add_argument('file', 28745ba7a89SDavid Gow help='Specifies the file to read results from.', 28845ba7a89SDavid Gow type=str, nargs='?', metavar='input_file') 2890476e69fSGreg Thelen 2906ebf5866SFelix Guo cli_args = parser.parse_args(argv) 2916ebf5866SFelix Guo 2925578d008SBrendan Higgins if get_kernel_root_path(): 2935578d008SBrendan Higgins os.chdir(get_kernel_root_path()) 2945578d008SBrendan Higgins 2956ebf5866SFelix Guo if cli_args.subcommand == 'run': 296e3212513SSeongJae Park if not os.path.exists(cli_args.build_dir): 297e3212513SSeongJae Park os.mkdir(cli_args.build_dir) 29882206a0cSBrendan Higgins 299ff7b437fSBrendan Higgins if not linux: 30087c9c163SBrendan Higgins linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 30187c9c163SBrendan Higgins kunitconfig_path=cli_args.kunitconfig, 30287c9c163SBrendan Higgins arch=cli_args.arch, 30387c9c163SBrendan Higgins cross_compile=cli_args.cross_compile, 30487c9c163SBrendan Higgins qemu_config_path=cli_args.qemu_config) 305fcdb0bc0SAndy Shevchenko 3066ebf5866SFelix Guo request = KunitRequest(cli_args.raw_output, 3076ebf5866SFelix Guo cli_args.timeout, 3086ebf5866SFelix Guo cli_args.jobs, 309ff7b437fSBrendan Higgins cli_args.build_dir, 3100476e69fSGreg Thelen cli_args.alltests, 311d992880bSDaniel Latypov cli_args.filter_glob, 31221a6d178SHeidi Fahim cli_args.json, 3130476e69fSGreg Thelen cli_args.make_options) 3146ebf5866SFelix Guo result = run_tests(linux, request) 3156ebf5866SFelix Guo if result.status != KunitStatus.SUCCESS: 3166ebf5866SFelix Guo sys.exit(1) 31745ba7a89SDavid Gow elif cli_args.subcommand == 'config': 31882206a0cSBrendan Higgins if cli_args.build_dir and ( 31982206a0cSBrendan Higgins not os.path.exists(cli_args.build_dir)): 32045ba7a89SDavid Gow os.mkdir(cli_args.build_dir) 32182206a0cSBrendan Higgins 32245ba7a89SDavid Gow if not linux: 32387c9c163SBrendan Higgins linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 32487c9c163SBrendan Higgins kunitconfig_path=cli_args.kunitconfig, 32587c9c163SBrendan Higgins arch=cli_args.arch, 32687c9c163SBrendan Higgins cross_compile=cli_args.cross_compile, 32787c9c163SBrendan Higgins qemu_config_path=cli_args.qemu_config) 328fcdb0bc0SAndy Shevchenko 32945ba7a89SDavid Gow request = KunitConfigRequest(cli_args.build_dir, 33045ba7a89SDavid Gow cli_args.make_options) 33145ba7a89SDavid Gow result = config_tests(linux, request) 33245ba7a89SDavid Gow kunit_parser.print_with_timestamp(( 33345ba7a89SDavid Gow 'Elapsed time: %.3fs\n') % ( 33445ba7a89SDavid Gow result.elapsed_time)) 33545ba7a89SDavid Gow if result.status != KunitStatus.SUCCESS: 33645ba7a89SDavid Gow sys.exit(1) 33745ba7a89SDavid Gow elif cli_args.subcommand == 'build': 33845ba7a89SDavid Gow if not linux: 33987c9c163SBrendan Higgins linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 34087c9c163SBrendan Higgins kunitconfig_path=cli_args.kunitconfig, 34187c9c163SBrendan Higgins arch=cli_args.arch, 34287c9c163SBrendan Higgins cross_compile=cli_args.cross_compile, 34387c9c163SBrendan Higgins qemu_config_path=cli_args.qemu_config) 344fcdb0bc0SAndy Shevchenko 34545ba7a89SDavid Gow request = KunitBuildRequest(cli_args.jobs, 34645ba7a89SDavid Gow cli_args.build_dir, 34745ba7a89SDavid Gow cli_args.alltests, 34845ba7a89SDavid Gow cli_args.make_options) 34945ba7a89SDavid Gow result = build_tests(linux, request) 35045ba7a89SDavid Gow kunit_parser.print_with_timestamp(( 35145ba7a89SDavid Gow 'Elapsed time: %.3fs\n') % ( 35245ba7a89SDavid Gow result.elapsed_time)) 35345ba7a89SDavid Gow if result.status != KunitStatus.SUCCESS: 35445ba7a89SDavid Gow sys.exit(1) 35545ba7a89SDavid Gow elif cli_args.subcommand == 'exec': 35645ba7a89SDavid Gow if not linux: 35787c9c163SBrendan Higgins linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 35887c9c163SBrendan Higgins kunitconfig_path=cli_args.kunitconfig, 35987c9c163SBrendan Higgins arch=cli_args.arch, 36087c9c163SBrendan Higgins cross_compile=cli_args.cross_compile, 36187c9c163SBrendan Higgins qemu_config_path=cli_args.qemu_config) 362fcdb0bc0SAndy Shevchenko 36345ba7a89SDavid Gow exec_request = KunitExecRequest(cli_args.timeout, 36445ba7a89SDavid Gow cli_args.build_dir, 365d992880bSDaniel Latypov cli_args.alltests, 366d992880bSDaniel Latypov cli_args.filter_glob) 36745ba7a89SDavid Gow exec_result = exec_tests(linux, exec_request) 36845ba7a89SDavid Gow parse_request = KunitParseRequest(cli_args.raw_output, 36921a6d178SHeidi Fahim exec_result.result, 37021a6d178SHeidi Fahim cli_args.build_dir, 37121a6d178SHeidi Fahim cli_args.json) 37245ba7a89SDavid Gow result = parse_tests(parse_request) 37345ba7a89SDavid Gow kunit_parser.print_with_timestamp(( 37445ba7a89SDavid Gow 'Elapsed time: %.3fs\n') % ( 37545ba7a89SDavid Gow exec_result.elapsed_time)) 37645ba7a89SDavid Gow if result.status != KunitStatus.SUCCESS: 37745ba7a89SDavid Gow sys.exit(1) 37845ba7a89SDavid Gow elif cli_args.subcommand == 'parse': 37945ba7a89SDavid Gow if cli_args.file == None: 38045ba7a89SDavid Gow kunit_output = sys.stdin 38145ba7a89SDavid Gow else: 38245ba7a89SDavid Gow with open(cli_args.file, 'r') as f: 38345ba7a89SDavid Gow kunit_output = f.read().splitlines() 38445ba7a89SDavid Gow request = KunitParseRequest(cli_args.raw_output, 38521a6d178SHeidi Fahim kunit_output, 3863959d0a6SDavid Gow None, 38721a6d178SHeidi Fahim cli_args.json) 38845ba7a89SDavid Gow result = parse_tests(request) 38945ba7a89SDavid Gow if result.status != KunitStatus.SUCCESS: 39045ba7a89SDavid Gow sys.exit(1) 3916ebf5866SFelix Guo else: 3926ebf5866SFelix Guo parser.print_help() 3936ebf5866SFelix Guo 3946ebf5866SFelix Guoif __name__ == '__main__': 395ff7b437fSBrendan Higgins main(sys.argv[1:]) 396