2 # SPDX-License-Identifier: GPL-2.0
4 # A thin wrapper on top of the KUnit Kernel
6 # Copyright (C) 2019, Google LLC.
7 # Author: Felix Guo <felixguoxiuping@gmail.com>
8 # Author: Brendan Higgins <brendanhiggins@google.com>
16 from collections
import namedtuple
17 from enum
import Enum
, auto
23 KunitResult
= namedtuple('KunitResult', ['status','result'])
25 KunitRequest
= namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
27 class KunitStatus(Enum
):
29 CONFIG_FAILURE
= auto()
30 BUILD_FAILURE
= auto()
33 def create_default_kunitconfig():
34 if not os
.path
.exists(kunit_kernel
.kunitconfig_path
):
35 shutil
.copyfile('arch/um/configs/kunit_defconfig',
36 kunit_kernel
.kunitconfig_path
)
38 def run_tests(linux
: kunit_kernel
.LinuxSourceTree
,
39 request
: KunitRequest
) -> KunitResult
:
40 config_start
= time
.time()
41 success
= linux
.build_reconfig(request
.build_dir
)
42 config_end
= time
.time()
44 return KunitResult(KunitStatus
.CONFIG_FAILURE
, 'could not configure kernel')
46 kunit_parser
.print_with_timestamp('Building KUnit Kernel ...')
48 build_start
= time
.time()
49 success
= linux
.build_um_kernel(request
.jobs
, request
.build_dir
)
50 build_end
= time
.time()
52 return KunitResult(KunitStatus
.BUILD_FAILURE
, 'could not build kernel')
54 kunit_parser
.print_with_timestamp('Starting KUnit Kernel ...')
55 test_start
= time
.time()
57 test_result
= kunit_parser
.TestResult(kunit_parser
.TestStatus
.SUCCESS
,
60 if request
.raw_output
:
61 kunit_parser
.raw_output(
62 linux
.run_kernel(timeout
=request
.timeout
,
63 build_dir
=request
.build_dir
))
65 kunit_output
= linux
.run_kernel(timeout
=request
.timeout
,
66 build_dir
=request
.build_dir
)
67 test_result
= kunit_parser
.parse_run_tests(kunit_output
)
68 test_end
= time
.time()
70 kunit_parser
.print_with_timestamp((
71 'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' +
72 'building, %.3fs running\n') % (
73 test_end
- config_start
,
74 config_end
- config_start
,
75 build_end
- build_start
,
76 test_end
- test_start
))
78 if test_result
.status
!= kunit_parser
.TestStatus
.SUCCESS
:
79 return KunitResult(KunitStatus
.TEST_FAILURE
, test_result
)
81 return KunitResult(KunitStatus
.SUCCESS
, test_result
)
83 def main(argv
, linux
=None):
84 parser
= argparse
.ArgumentParser(
85 description
='Helps writing and running KUnit tests.')
86 subparser
= parser
.add_subparsers(dest
='subcommand')
88 run_parser
= subparser
.add_parser('run', help='Runs KUnit tests.')
89 run_parser
.add_argument('--raw_output', help='don\'t format output from kernel',
92 run_parser
.add_argument('--timeout',
93 help='maximum number of seconds to allow for all tests '
94 'to run. This does not include time taken to build the '
100 run_parser
.add_argument('--jobs',
101 help='As in the make command, "Specifies the number of '
102 'jobs (commands) to run simultaneously."',
103 type=int, default
=8, metavar
='jobs')
105 run_parser
.add_argument('--build_dir',
106 help='As in the make command, it specifies the build '
108 type=str, default
='', metavar
='build_dir')
110 run_parser
.add_argument('--defconfig',
111 help='Uses a default .kunitconfig.',
114 cli_args
= parser
.parse_args(argv
)
116 if cli_args
.subcommand
== 'run':
117 if cli_args
.build_dir
:
118 if not os
.path
.exists(cli_args
.build_dir
):
119 os
.mkdir(cli_args
.build_dir
)
120 kunit_kernel
.kunitconfig_path
= os
.path
.join(
122 kunit_kernel
.kunitconfig_path
)
124 if cli_args
.defconfig
:
125 create_default_kunitconfig()
128 linux
= kunit_kernel
.LinuxSourceTree()
130 request
= KunitRequest(cli_args
.raw_output
,
135 result
= run_tests(linux
, request
)
136 if result
.status
!= KunitStatus
.SUCCESS
:
141 if __name__
== '__main__':