2019-09-23 02:02:43 -07:00
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0
#
# A thin wrapper on top of the KUnit Kernel
#
# Copyright (C) 2019, Google LLC.
# Author: Felix Guo <felixguoxiuping@gmail.com>
# Author: Brendan Higgins <brendanhiggins@google.com>
import argparse
import sys
import os
import time
2019-09-23 02:02:44 -07:00
import shutil
2019-09-23 02:02:43 -07:00
from collections import namedtuple
from enum import Enum , auto
import kunit_config
import kunit_kernel
import kunit_parser
KunitResult = namedtuple ( ' KunitResult ' , [ ' status ' , ' result ' ] )
2020-03-16 13:21:25 -07:00
KunitRequest = namedtuple ( ' KunitRequest ' , [ ' raw_output ' , ' timeout ' , ' jobs ' ,
' build_dir ' , ' defconfig ' ,
2020-03-23 12:04:59 -07:00
' alltests ' , ' make_options ' ] )
2019-09-23 02:02:43 -07:00
2020-02-18 14:19:16 -08:00
KernelDirectoryPath = sys . argv [ 0 ] . split ( ' tools/testing/kunit/ ' ) [ 0 ]
2019-09-23 02:02:43 -07:00
class KunitStatus ( Enum ) :
SUCCESS = auto ( )
CONFIG_FAILURE = auto ( )
BUILD_FAILURE = auto ( )
TEST_FAILURE = auto ( )
2019-09-23 02:02:44 -07:00
def create_default_kunitconfig ( ) :
2019-12-20 05:14:05 +00:00
if not os . path . exists ( kunit_kernel . kunitconfig_path ) :
2019-09-23 02:02:44 -07:00
shutil . copyfile ( ' arch/um/configs/kunit_defconfig ' ,
2019-12-20 05:14:05 +00:00
kunit_kernel . kunitconfig_path )
2019-09-23 02:02:44 -07:00
2020-02-18 14:19:16 -08:00
def get_kernel_root_path ( ) :
parts = sys . argv [ 0 ] if not __file__ else __file__
parts = os . path . realpath ( parts ) . split ( ' tools/testing/kunit ' )
if len ( parts ) != 2 :
sys . exit ( 1 )
return parts [ 0 ]
2019-09-23 02:02:43 -07:00
def run_tests ( linux : kunit_kernel . LinuxSourceTree ,
request : KunitRequest ) - > KunitResult :
config_start = time . time ( )
2020-03-23 12:04:59 -07:00
success = linux . build_reconfig ( request . build_dir , request . make_options )
2019-09-23 02:02:43 -07:00
config_end = time . time ( )
if not success :
return KunitResult ( KunitStatus . CONFIG_FAILURE , ' could not configure kernel ' )
kunit_parser . print_with_timestamp ( ' Building KUnit Kernel ... ' )
build_start = time . time ( )
2020-03-16 13:21:25 -07:00
success = linux . build_um_kernel ( request . alltests ,
request . jobs ,
2020-03-23 12:04:59 -07:00
request . build_dir ,
request . make_options )
2019-09-23 02:02:43 -07:00
build_end = time . time ( )
if not success :
return KunitResult ( KunitStatus . BUILD_FAILURE , ' could not build kernel ' )
kunit_parser . print_with_timestamp ( ' Starting KUnit Kernel ... ' )
test_start = time . time ( )
2020-03-16 13:21:25 -07:00
kunit_output = linux . run_kernel (
timeout = None if request . alltests else request . timeout ,
build_dir = request . build_dir )
2019-09-23 02:02:43 -07:00
if request . raw_output :
2020-03-16 13:21:25 -07:00
raw_output = kunit_parser . raw_output ( kunit_output )
isolated = list ( kunit_parser . isolate_kunit_output ( raw_output ) )
test_result = kunit_parser . parse_test_result ( isolated )
2019-09-23 02:02:43 -07:00
else :
test_result = kunit_parser . parse_run_tests ( kunit_output )
test_end = time . time ( )
kunit_parser . print_with_timestamp ( (
' Elapsed time: %.3f s total, %.3f s configuring, %.3f s ' +
' building, %.3f s running \n ' ) % (
test_end - config_start ,
config_end - config_start ,
build_end - build_start ,
test_end - test_start ) )
if test_result . status != kunit_parser . TestStatus . SUCCESS :
return KunitResult ( KunitStatus . TEST_FAILURE , test_result )
else :
return KunitResult ( KunitStatus . SUCCESS , test_result )
2019-09-23 02:02:44 -07:00
def main ( argv , linux = None ) :
2019-09-23 02:02:43 -07:00
parser = argparse . ArgumentParser (
description = ' Helps writing and running KUnit tests. ' )
subparser = parser . add_subparsers ( dest = ' subcommand ' )
run_parser = subparser . add_parser ( ' run ' , help = ' Runs KUnit tests. ' )
run_parser . add_argument ( ' --raw_output ' , help = ' don \' t format output from kernel ' ,
action = ' store_true ' )
run_parser . add_argument ( ' --timeout ' ,
help = ' maximum number of seconds to allow for all tests '
' to run. This does not include time taken to build the '
' tests. ' ,
type = int ,
default = 300 ,
metavar = ' timeout ' )
run_parser . add_argument ( ' --jobs ' ,
help = ' As in the make command, " Specifies the number of '
' jobs (commands) to run simultaneously. " ' ,
type = int , default = 8 , metavar = ' jobs ' )
run_parser . add_argument ( ' --build_dir ' ,
help = ' As in the make command, it specifies the build '
' directory. ' ,
2019-12-20 05:14:06 +00:00
type = str , default = ' ' , metavar = ' build_dir ' )
2019-09-23 02:02:43 -07:00
2019-09-23 02:02:44 -07:00
run_parser . add_argument ( ' --defconfig ' ,
2019-12-20 05:14:07 +00:00
help = ' Uses a default .kunitconfig. ' ,
2019-09-23 02:02:44 -07:00
action = ' store_true ' )
2020-03-16 13:21:25 -07:00
run_parser . add_argument ( ' --alltests ' ,
help = ' Run all KUnit tests through allyesconfig ' ,
action = ' store_true ' )
2020-03-23 12:04:59 -07:00
run_parser . add_argument ( ' --make_options ' ,
help = ' X=Y make option, can be repeated. ' ,
action = ' append ' )
2019-09-23 02:02:43 -07:00
cli_args = parser . parse_args ( argv )
if cli_args . subcommand == ' run ' :
2020-02-18 14:19:16 -08:00
if get_kernel_root_path ( ) :
os . chdir ( get_kernel_root_path ( ) )
2019-12-20 05:14:05 +00:00
if cli_args . build_dir :
if not os . path . exists ( cli_args . build_dir ) :
os . mkdir ( cli_args . build_dir )
kunit_kernel . kunitconfig_path = os . path . join (
cli_args . build_dir ,
kunit_kernel . kunitconfig_path )
2019-09-23 02:02:44 -07:00
if cli_args . defconfig :
create_default_kunitconfig ( )
if not linux :
linux = kunit_kernel . LinuxSourceTree ( )
2019-09-23 02:02:43 -07:00
request = KunitRequest ( cli_args . raw_output ,
cli_args . timeout ,
cli_args . jobs ,
2019-09-23 02:02:44 -07:00
cli_args . build_dir ,
2020-03-16 13:21:25 -07:00
cli_args . defconfig ,
2020-03-23 12:04:59 -07:00
cli_args . alltests ,
cli_args . make_options )
2019-09-23 02:02:43 -07:00
result = run_tests ( linux , request )
if result . status != KunitStatus . SUCCESS :
sys . exit ( 1 )
else :
parser . print_help ( )
if __name__ == ' __main__ ' :
2019-09-23 02:02:44 -07:00
main ( sys . argv [ 1 : ] )