16ebf5866SFelix Guo#!/usr/bin/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 14*ff7b437fSBrendan Higginsimport shutil 156ebf5866SFelix Guo 166ebf5866SFelix Guofrom collections import namedtuple 176ebf5866SFelix Guofrom enum import Enum, auto 186ebf5866SFelix Guo 196ebf5866SFelix Guoimport kunit_config 206ebf5866SFelix Guoimport kunit_kernel 216ebf5866SFelix Guoimport kunit_parser 226ebf5866SFelix Guo 236ebf5866SFelix GuoKunitResult = namedtuple('KunitResult', ['status','result']) 246ebf5866SFelix Guo 25*ff7b437fSBrendan HigginsKunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig']) 266ebf5866SFelix Guo 276ebf5866SFelix Guoclass KunitStatus(Enum): 286ebf5866SFelix Guo SUCCESS = auto() 296ebf5866SFelix Guo CONFIG_FAILURE = auto() 306ebf5866SFelix Guo BUILD_FAILURE = auto() 316ebf5866SFelix Guo TEST_FAILURE = auto() 326ebf5866SFelix Guo 33*ff7b437fSBrendan Higginsdef create_default_kunitconfig(): 34*ff7b437fSBrendan Higgins if not os.path.exists(kunit_kernel.KUNITCONFIG_PATH): 35*ff7b437fSBrendan Higgins shutil.copyfile('arch/um/configs/kunit_defconfig', 36*ff7b437fSBrendan Higgins kunit_kernel.KUNITCONFIG_PATH) 37*ff7b437fSBrendan Higgins 386ebf5866SFelix Guodef run_tests(linux: kunit_kernel.LinuxSourceTree, 396ebf5866SFelix Guo request: KunitRequest) -> KunitResult: 40*ff7b437fSBrendan Higgins if request.defconfig: 41*ff7b437fSBrendan Higgins create_default_kunitconfig() 42*ff7b437fSBrendan Higgins 436ebf5866SFelix Guo config_start = time.time() 446ebf5866SFelix Guo success = linux.build_reconfig(request.build_dir) 456ebf5866SFelix Guo config_end = time.time() 466ebf5866SFelix Guo if not success: 476ebf5866SFelix Guo return KunitResult(KunitStatus.CONFIG_FAILURE, 'could not configure kernel') 486ebf5866SFelix Guo 496ebf5866SFelix Guo kunit_parser.print_with_timestamp('Building KUnit Kernel ...') 506ebf5866SFelix Guo 516ebf5866SFelix Guo build_start = time.time() 526ebf5866SFelix Guo success = linux.build_um_kernel(request.jobs, request.build_dir) 536ebf5866SFelix Guo build_end = time.time() 546ebf5866SFelix Guo if not success: 556ebf5866SFelix Guo return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel') 566ebf5866SFelix Guo 576ebf5866SFelix Guo kunit_parser.print_with_timestamp('Starting KUnit Kernel ...') 586ebf5866SFelix Guo test_start = time.time() 596ebf5866SFelix Guo 606ebf5866SFelix Guo test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS, 616ebf5866SFelix Guo [], 626ebf5866SFelix Guo 'Tests not Parsed.') 636ebf5866SFelix Guo if request.raw_output: 646ebf5866SFelix Guo kunit_parser.raw_output( 656ebf5866SFelix Guo linux.run_kernel(timeout=request.timeout)) 666ebf5866SFelix Guo else: 676ebf5866SFelix Guo kunit_output = linux.run_kernel(timeout=request.timeout) 686ebf5866SFelix Guo test_result = kunit_parser.parse_run_tests(kunit_output) 696ebf5866SFelix Guo test_end = time.time() 706ebf5866SFelix Guo 716ebf5866SFelix Guo kunit_parser.print_with_timestamp(( 726ebf5866SFelix Guo 'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' + 736ebf5866SFelix Guo 'building, %.3fs running\n') % ( 746ebf5866SFelix Guo test_end - config_start, 756ebf5866SFelix Guo config_end - config_start, 766ebf5866SFelix Guo build_end - build_start, 776ebf5866SFelix Guo test_end - test_start)) 786ebf5866SFelix Guo 796ebf5866SFelix Guo if test_result.status != kunit_parser.TestStatus.SUCCESS: 806ebf5866SFelix Guo return KunitResult(KunitStatus.TEST_FAILURE, test_result) 816ebf5866SFelix Guo else: 826ebf5866SFelix Guo return KunitResult(KunitStatus.SUCCESS, test_result) 836ebf5866SFelix Guo 84*ff7b437fSBrendan Higginsdef main(argv, linux=None): 856ebf5866SFelix Guo parser = argparse.ArgumentParser( 866ebf5866SFelix Guo description='Helps writing and running KUnit tests.') 876ebf5866SFelix Guo subparser = parser.add_subparsers(dest='subcommand') 886ebf5866SFelix Guo 896ebf5866SFelix Guo run_parser = subparser.add_parser('run', help='Runs KUnit tests.') 906ebf5866SFelix Guo run_parser.add_argument('--raw_output', help='don\'t format output from kernel', 916ebf5866SFelix Guo action='store_true') 926ebf5866SFelix Guo 936ebf5866SFelix Guo run_parser.add_argument('--timeout', 946ebf5866SFelix Guo help='maximum number of seconds to allow for all tests ' 956ebf5866SFelix Guo 'to run. This does not include time taken to build the ' 966ebf5866SFelix Guo 'tests.', 976ebf5866SFelix Guo type=int, 986ebf5866SFelix Guo default=300, 996ebf5866SFelix Guo metavar='timeout') 1006ebf5866SFelix Guo 1016ebf5866SFelix Guo run_parser.add_argument('--jobs', 1026ebf5866SFelix Guo help='As in the make command, "Specifies the number of ' 1036ebf5866SFelix Guo 'jobs (commands) to run simultaneously."', 1046ebf5866SFelix Guo type=int, default=8, metavar='jobs') 1056ebf5866SFelix Guo 1066ebf5866SFelix Guo run_parser.add_argument('--build_dir', 1076ebf5866SFelix Guo help='As in the make command, it specifies the build ' 1086ebf5866SFelix Guo 'directory.', 1096ebf5866SFelix Guo type=str, default=None, metavar='build_dir') 1106ebf5866SFelix Guo 111*ff7b437fSBrendan Higgins run_parser.add_argument('--defconfig', 112*ff7b437fSBrendan Higgins help='Uses a default kunitconfig.', 113*ff7b437fSBrendan Higgins action='store_true') 114*ff7b437fSBrendan Higgins 1156ebf5866SFelix Guo cli_args = parser.parse_args(argv) 1166ebf5866SFelix Guo 1176ebf5866SFelix Guo if cli_args.subcommand == 'run': 118*ff7b437fSBrendan Higgins if cli_args.defconfig: 119*ff7b437fSBrendan Higgins create_default_kunitconfig() 120*ff7b437fSBrendan Higgins 121*ff7b437fSBrendan Higgins if not linux: 122*ff7b437fSBrendan Higgins linux = kunit_kernel.LinuxSourceTree() 123*ff7b437fSBrendan Higgins 1246ebf5866SFelix Guo request = KunitRequest(cli_args.raw_output, 1256ebf5866SFelix Guo cli_args.timeout, 1266ebf5866SFelix Guo cli_args.jobs, 127*ff7b437fSBrendan Higgins cli_args.build_dir, 128*ff7b437fSBrendan Higgins cli_args.defconfig) 1296ebf5866SFelix Guo result = run_tests(linux, request) 1306ebf5866SFelix Guo if result.status != KunitStatus.SUCCESS: 1316ebf5866SFelix Guo sys.exit(1) 1326ebf5866SFelix Guo else: 1336ebf5866SFelix Guo parser.print_help() 1346ebf5866SFelix Guo 1356ebf5866SFelix Guoif __name__ == '__main__': 136*ff7b437fSBrendan Higgins main(sys.argv[1:]) 137