1*6ebf5866SFelix Guo#!/usr/bin/python3 2*6ebf5866SFelix Guo# SPDX-License-Identifier: GPL-2.0 3*6ebf5866SFelix Guo# 4*6ebf5866SFelix Guo# A thin wrapper on top of the KUnit Kernel 5*6ebf5866SFelix Guo# 6*6ebf5866SFelix Guo# Copyright (C) 2019, Google LLC. 7*6ebf5866SFelix Guo# Author: Felix Guo <felixguoxiuping@gmail.com> 8*6ebf5866SFelix Guo# Author: Brendan Higgins <brendanhiggins@google.com> 9*6ebf5866SFelix Guo 10*6ebf5866SFelix Guoimport argparse 11*6ebf5866SFelix Guoimport sys 12*6ebf5866SFelix Guoimport os 13*6ebf5866SFelix Guoimport time 14*6ebf5866SFelix Guo 15*6ebf5866SFelix Guofrom collections import namedtuple 16*6ebf5866SFelix Guofrom enum import Enum, auto 17*6ebf5866SFelix Guo 18*6ebf5866SFelix Guoimport kunit_config 19*6ebf5866SFelix Guoimport kunit_kernel 20*6ebf5866SFelix Guoimport kunit_parser 21*6ebf5866SFelix Guo 22*6ebf5866SFelix GuoKunitResult = namedtuple('KunitResult', ['status','result']) 23*6ebf5866SFelix Guo 24*6ebf5866SFelix GuoKunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir']) 25*6ebf5866SFelix Guo 26*6ebf5866SFelix Guoclass KunitStatus(Enum): 27*6ebf5866SFelix Guo SUCCESS = auto() 28*6ebf5866SFelix Guo CONFIG_FAILURE = auto() 29*6ebf5866SFelix Guo BUILD_FAILURE = auto() 30*6ebf5866SFelix Guo TEST_FAILURE = auto() 31*6ebf5866SFelix Guo 32*6ebf5866SFelix Guodef run_tests(linux: kunit_kernel.LinuxSourceTree, 33*6ebf5866SFelix Guo request: KunitRequest) -> KunitResult: 34*6ebf5866SFelix Guo config_start = time.time() 35*6ebf5866SFelix Guo success = linux.build_reconfig(request.build_dir) 36*6ebf5866SFelix Guo config_end = time.time() 37*6ebf5866SFelix Guo if not success: 38*6ebf5866SFelix Guo return KunitResult(KunitStatus.CONFIG_FAILURE, 'could not configure kernel') 39*6ebf5866SFelix Guo 40*6ebf5866SFelix Guo kunit_parser.print_with_timestamp('Building KUnit Kernel ...') 41*6ebf5866SFelix Guo 42*6ebf5866SFelix Guo build_start = time.time() 43*6ebf5866SFelix Guo success = linux.build_um_kernel(request.jobs, request.build_dir) 44*6ebf5866SFelix Guo build_end = time.time() 45*6ebf5866SFelix Guo if not success: 46*6ebf5866SFelix Guo return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel') 47*6ebf5866SFelix Guo 48*6ebf5866SFelix Guo kunit_parser.print_with_timestamp('Starting KUnit Kernel ...') 49*6ebf5866SFelix Guo test_start = time.time() 50*6ebf5866SFelix Guo 51*6ebf5866SFelix Guo test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS, 52*6ebf5866SFelix Guo [], 53*6ebf5866SFelix Guo 'Tests not Parsed.') 54*6ebf5866SFelix Guo if request.raw_output: 55*6ebf5866SFelix Guo kunit_parser.raw_output( 56*6ebf5866SFelix Guo linux.run_kernel(timeout=request.timeout)) 57*6ebf5866SFelix Guo else: 58*6ebf5866SFelix Guo kunit_output = linux.run_kernel(timeout=request.timeout) 59*6ebf5866SFelix Guo test_result = kunit_parser.parse_run_tests(kunit_output) 60*6ebf5866SFelix Guo test_end = time.time() 61*6ebf5866SFelix Guo 62*6ebf5866SFelix Guo kunit_parser.print_with_timestamp(( 63*6ebf5866SFelix Guo 'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' + 64*6ebf5866SFelix Guo 'building, %.3fs running\n') % ( 65*6ebf5866SFelix Guo test_end - config_start, 66*6ebf5866SFelix Guo config_end - config_start, 67*6ebf5866SFelix Guo build_end - build_start, 68*6ebf5866SFelix Guo test_end - test_start)) 69*6ebf5866SFelix Guo 70*6ebf5866SFelix Guo if test_result.status != kunit_parser.TestStatus.SUCCESS: 71*6ebf5866SFelix Guo return KunitResult(KunitStatus.TEST_FAILURE, test_result) 72*6ebf5866SFelix Guo else: 73*6ebf5866SFelix Guo return KunitResult(KunitStatus.SUCCESS, test_result) 74*6ebf5866SFelix Guo 75*6ebf5866SFelix Guodef main(argv, linux): 76*6ebf5866SFelix Guo parser = argparse.ArgumentParser( 77*6ebf5866SFelix Guo description='Helps writing and running KUnit tests.') 78*6ebf5866SFelix Guo subparser = parser.add_subparsers(dest='subcommand') 79*6ebf5866SFelix Guo 80*6ebf5866SFelix Guo run_parser = subparser.add_parser('run', help='Runs KUnit tests.') 81*6ebf5866SFelix Guo run_parser.add_argument('--raw_output', help='don\'t format output from kernel', 82*6ebf5866SFelix Guo action='store_true') 83*6ebf5866SFelix Guo 84*6ebf5866SFelix Guo run_parser.add_argument('--timeout', 85*6ebf5866SFelix Guo help='maximum number of seconds to allow for all tests ' 86*6ebf5866SFelix Guo 'to run. This does not include time taken to build the ' 87*6ebf5866SFelix Guo 'tests.', 88*6ebf5866SFelix Guo type=int, 89*6ebf5866SFelix Guo default=300, 90*6ebf5866SFelix Guo metavar='timeout') 91*6ebf5866SFelix Guo 92*6ebf5866SFelix Guo run_parser.add_argument('--jobs', 93*6ebf5866SFelix Guo help='As in the make command, "Specifies the number of ' 94*6ebf5866SFelix Guo 'jobs (commands) to run simultaneously."', 95*6ebf5866SFelix Guo type=int, default=8, metavar='jobs') 96*6ebf5866SFelix Guo 97*6ebf5866SFelix Guo run_parser.add_argument('--build_dir', 98*6ebf5866SFelix Guo help='As in the make command, it specifies the build ' 99*6ebf5866SFelix Guo 'directory.', 100*6ebf5866SFelix Guo type=str, default=None, metavar='build_dir') 101*6ebf5866SFelix Guo 102*6ebf5866SFelix Guo cli_args = parser.parse_args(argv) 103*6ebf5866SFelix Guo 104*6ebf5866SFelix Guo if cli_args.subcommand == 'run': 105*6ebf5866SFelix Guo request = KunitRequest(cli_args.raw_output, 106*6ebf5866SFelix Guo cli_args.timeout, 107*6ebf5866SFelix Guo cli_args.jobs, 108*6ebf5866SFelix Guo cli_args.build_dir) 109*6ebf5866SFelix Guo result = run_tests(linux, request) 110*6ebf5866SFelix Guo if result.status != KunitStatus.SUCCESS: 111*6ebf5866SFelix Guo sys.exit(1) 112*6ebf5866SFelix Guo else: 113*6ebf5866SFelix Guo parser.print_help() 114*6ebf5866SFelix Guo 115*6ebf5866SFelix Guoif __name__ == '__main__': 116*6ebf5866SFelix Guo main(sys.argv[1:], kunit_kernel.LinuxSourceTree()) 117