~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/kunit/kunit.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/testing/kunit/kunit.py (Version linux-6.12-rc7) and /tools/testing/kunit/kunit.py (Version linux-6.0.19)


  1 #!/usr/bin/env python3                              1 #!/usr/bin/env python3
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3 #                                                   3 #
  4 # A thin wrapper on top of the KUnit Kernel         4 # A thin wrapper on top of the KUnit Kernel
  5 #                                                   5 #
  6 # Copyright (C) 2019, Google LLC.                   6 # Copyright (C) 2019, Google LLC.
  7 # Author: Felix Guo <felixguoxiuping@gmail.com>      7 # Author: Felix Guo <felixguoxiuping@gmail.com>
  8 # Author: Brendan Higgins <brendanhiggins@googl      8 # Author: Brendan Higgins <brendanhiggins@google.com>
  9                                                     9 
 10 import argparse                                    10 import argparse
 11 import os                                          11 import os
 12 import re                                          12 import re
 13 import shlex                                       13 import shlex
 14 import sys                                         14 import sys
 15 import time                                        15 import time
 16                                                    16 
 17 assert sys.version_info >= (3, 7), "Python ver     17 assert sys.version_info >= (3, 7), "Python version is too old"
 18                                                    18 
 19 from dataclasses import dataclass                  19 from dataclasses import dataclass
 20 from enum import Enum, auto                        20 from enum import Enum, auto
 21 from typing import Iterable, List, Optional, S     21 from typing import Iterable, List, Optional, Sequence, Tuple
 22                                                    22 
 23 import kunit_json                                  23 import kunit_json
 24 import kunit_kernel                                24 import kunit_kernel
 25 import kunit_parser                                25 import kunit_parser
 26 from kunit_printer import stdout                   26 from kunit_printer import stdout
 27                                                    27 
 28 class KunitStatus(Enum):                           28 class KunitStatus(Enum):
 29         SUCCESS = auto()                           29         SUCCESS = auto()
 30         CONFIG_FAILURE = auto()                    30         CONFIG_FAILURE = auto()
 31         BUILD_FAILURE = auto()                     31         BUILD_FAILURE = auto()
 32         TEST_FAILURE = auto()                      32         TEST_FAILURE = auto()
 33                                                    33 
 34 @dataclass                                         34 @dataclass
 35 class KunitResult:                                 35 class KunitResult:
 36         status: KunitStatus                        36         status: KunitStatus
 37         elapsed_time: float                        37         elapsed_time: float
 38                                                    38 
 39 @dataclass                                         39 @dataclass
 40 class KunitConfigRequest:                          40 class KunitConfigRequest:
 41         build_dir: str                             41         build_dir: str
 42         make_options: Optional[List[str]]          42         make_options: Optional[List[str]]
 43                                                    43 
 44 @dataclass                                         44 @dataclass
 45 class KunitBuildRequest(KunitConfigRequest):       45 class KunitBuildRequest(KunitConfigRequest):
 46         jobs: int                                  46         jobs: int
                                                   >>  47         alltests: bool
 47                                                    48 
 48 @dataclass                                         49 @dataclass
 49 class KunitParseRequest:                           50 class KunitParseRequest:
 50         raw_output: Optional[str]                  51         raw_output: Optional[str]
 51         json: Optional[str]                        52         json: Optional[str]
 52                                                    53 
 53 @dataclass                                         54 @dataclass
 54 class KunitExecRequest(KunitParseRequest):         55 class KunitExecRequest(KunitParseRequest):
 55         build_dir: str                             56         build_dir: str
 56         timeout: int                               57         timeout: int
                                                   >>  58         alltests: bool
 57         filter_glob: str                           59         filter_glob: str
 58         filter: str                            << 
 59         filter_action: Optional[str]           << 
 60         kernel_args: Optional[List[str]]           60         kernel_args: Optional[List[str]]
 61         run_isolated: Optional[str]                61         run_isolated: Optional[str]
 62         list_tests: bool                       << 
 63         list_tests_attr: bool                  << 
 64                                                    62 
 65 @dataclass                                         63 @dataclass
 66 class KunitRequest(KunitExecRequest, KunitBuil     64 class KunitRequest(KunitExecRequest, KunitBuildRequest):
 67         pass                                       65         pass
 68                                                    66 
 69                                                    67 
 70 def get_kernel_root_path() -> str:                 68 def get_kernel_root_path() -> str:
 71         path = sys.argv[0] if not __file__ els     69         path = sys.argv[0] if not __file__ else __file__
 72         parts = os.path.realpath(path).split('     70         parts = os.path.realpath(path).split('tools/testing/kunit')
 73         if len(parts) != 2:                        71         if len(parts) != 2:
 74                 sys.exit(1)                        72                 sys.exit(1)
 75         return parts[0]                            73         return parts[0]
 76                                                    74 
 77 def config_tests(linux: kunit_kernel.LinuxSour     75 def config_tests(linux: kunit_kernel.LinuxSourceTree,
 78                  request: KunitConfigRequest)      76                  request: KunitConfigRequest) -> KunitResult:
 79         stdout.print_with_timestamp('Configuri     77         stdout.print_with_timestamp('Configuring KUnit Kernel ...')
 80                                                    78 
 81         config_start = time.time()                 79         config_start = time.time()
 82         success = linux.build_reconfig(request     80         success = linux.build_reconfig(request.build_dir, request.make_options)
 83         config_end = time.time()                   81         config_end = time.time()
 84         status = KunitStatus.SUCCESS if succes !!  82         if not success:
 85         return KunitResult(status, config_end  !!  83                 return KunitResult(KunitStatus.CONFIG_FAILURE,
                                                   >>  84                                    config_end - config_start)
                                                   >>  85         return KunitResult(KunitStatus.SUCCESS,
                                                   >>  86                            config_end - config_start)
 86                                                    87 
 87 def build_tests(linux: kunit_kernel.LinuxSourc     88 def build_tests(linux: kunit_kernel.LinuxSourceTree,
 88                 request: KunitBuildRequest) ->     89                 request: KunitBuildRequest) -> KunitResult:
 89         stdout.print_with_timestamp('Building      90         stdout.print_with_timestamp('Building KUnit Kernel ...')
 90                                                    91 
 91         build_start = time.time()                  92         build_start = time.time()
 92         success = linux.build_kernel(request.j !!  93         success = linux.build_kernel(request.alltests,
                                                   >>  94                                      request.jobs,
 93                                      request.b     95                                      request.build_dir,
 94                                      request.m     96                                      request.make_options)
 95         build_end = time.time()                    97         build_end = time.time()
 96         status = KunitStatus.SUCCESS if succes !!  98         if not success:
 97         return KunitResult(status, build_end - !!  99                 return KunitResult(KunitStatus.BUILD_FAILURE,
                                                   >> 100                                    build_end - build_start)
                                                   >> 101         if not success:
                                                   >> 102                 return KunitResult(KunitStatus.BUILD_FAILURE,
                                                   >> 103                                    build_end - build_start)
                                                   >> 104         return KunitResult(KunitStatus.SUCCESS,
                                                   >> 105                            build_end - build_start)
 98                                                   106 
 99 def config_and_build_tests(linux: kunit_kernel    107 def config_and_build_tests(linux: kunit_kernel.LinuxSourceTree,
100                            request: KunitBuild    108                            request: KunitBuildRequest) -> KunitResult:
101         config_result = config_tests(linux, re    109         config_result = config_tests(linux, request)
102         if config_result.status != KunitStatus    110         if config_result.status != KunitStatus.SUCCESS:
103                 return config_result              111                 return config_result
104                                                   112 
105         return build_tests(linux, request)        113         return build_tests(linux, request)
106                                                   114 
107 def _list_tests(linux: kunit_kernel.LinuxSourc    115 def _list_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) -> List[str]:
108         args = ['kunit.action=list']              116         args = ['kunit.action=list']
109                                                << 
110         if request.kernel_args:                << 
111                 args.extend(request.kernel_arg << 
112                                                << 
113         output = linux.run_kernel(args=args,   << 
114                            timeout=request.tim << 
115                            filter_glob=request << 
116                            filter=request.filt << 
117                            filter_action=reque << 
118                            build_dir=request.b << 
119         lines = kunit_parser.extract_tap_lines << 
120         # Hack! Drop the dummy TAP version hea << 
121         lines.pop()                            << 
122                                                << 
123         # Filter out any extraneous non-test o << 
124         return [l for l in output if re.match( << 
125                                                << 
126 def _list_tests_attr(linux: kunit_kernel.Linux << 
127         args = ['kunit.action=list_attr']      << 
128                                                << 
129         if request.kernel_args:                   117         if request.kernel_args:
130                 args.extend(request.kernel_arg    118                 args.extend(request.kernel_args)
131                                                   119 
132         output = linux.run_kernel(args=args,      120         output = linux.run_kernel(args=args,
133                            timeout=request.tim !! 121                            timeout=None if request.alltests else request.timeout,
134                            filter_glob=request    122                            filter_glob=request.filter_glob,
135                            filter=request.filt << 
136                            filter_action=reque << 
137                            build_dir=request.b    123                            build_dir=request.build_dir)
138         lines = kunit_parser.extract_tap_lines    124         lines = kunit_parser.extract_tap_lines(output)
139         # Hack! Drop the dummy TAP version hea    125         # Hack! Drop the dummy TAP version header that the executor prints out.
140         lines.pop()                               126         lines.pop()
141                                                   127 
142         # Filter out any extraneous non-test o    128         # Filter out any extraneous non-test output that might have gotten mixed in.
143         return lines                           !! 129         return [l for l in lines if re.match(r'^[^\s.]+\.[^\s.]+$', l)]
144                                                   130 
145 def _suites_from_test_list(tests: List[str]) -    131 def _suites_from_test_list(tests: List[str]) -> List[str]:
146         """Extracts all the suites from an ord    132         """Extracts all the suites from an ordered list of tests."""
147         suites = []  # type: List[str]            133         suites = []  # type: List[str]
148         for t in tests:                           134         for t in tests:
149                 parts = t.split('.', maxsplit=    135                 parts = t.split('.', maxsplit=2)
150                 if len(parts) != 2:               136                 if len(parts) != 2:
151                         raise ValueError(f'int    137                         raise ValueError(f'internal KUnit error, test name should be of the form "<suite>.<test>", got "{t}"')
152                 suite, _ = parts               !! 138                 suite, case = parts
153                 if not suites or suites[-1] !=    139                 if not suites or suites[-1] != suite:
154                         suites.append(suite)      140                         suites.append(suite)
155         return suites                             141         return suites
156                                                   142 
                                                   >> 143 
                                                   >> 144 
157 def exec_tests(linux: kunit_kernel.LinuxSource    145 def exec_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) -> KunitResult:
158         filter_globs = [request.filter_glob]      146         filter_globs = [request.filter_glob]
159         if request.list_tests:                 << 
160                 output = _list_tests(linux, re << 
161                 for line in output:            << 
162                         print(line.rstrip())   << 
163                 return KunitResult(status=Kuni << 
164         if request.list_tests_attr:            << 
165                 attr_output = _list_tests_attr << 
166                 for line in attr_output:       << 
167                         print(line.rstrip())   << 
168                 return KunitResult(status=Kuni << 
169         if request.run_isolated:                  147         if request.run_isolated:
170                 tests = _list_tests(linux, req    148                 tests = _list_tests(linux, request)
171                 if request.run_isolated == 'te    149                 if request.run_isolated == 'test':
172                         filter_globs = tests      150                         filter_globs = tests
173                 elif request.run_isolated == ' !! 151                 if request.run_isolated == 'suite':
174                         filter_globs = _suites    152                         filter_globs = _suites_from_test_list(tests)
175                         # Apply the test-part     153                         # Apply the test-part of the user's glob, if present.
176                         if '.' in request.filt    154                         if '.' in request.filter_glob:
177                                 test_glob = re    155                                 test_glob = request.filter_glob.split('.', maxsplit=2)[1]
178                                 filter_globs =    156                                 filter_globs = [g + '.'+ test_glob for g in filter_globs]
179                                                   157 
180         metadata = kunit_json.Metadata(arch=li    158         metadata = kunit_json.Metadata(arch=linux.arch(), build_dir=request.build_dir, def_config='kunit_defconfig')
181                                                   159 
182         test_counts = kunit_parser.TestCounts(    160         test_counts = kunit_parser.TestCounts()
183         exec_time = 0.0                           161         exec_time = 0.0
184         for i, filter_glob in enumerate(filter    162         for i, filter_glob in enumerate(filter_globs):
185                 stdout.print_with_timestamp('S    163                 stdout.print_with_timestamp('Starting KUnit Kernel ({}/{})...'.format(i+1, len(filter_globs)))
186                                                   164 
187                 test_start = time.time()          165                 test_start = time.time()
188                 run_result = linux.run_kernel(    166                 run_result = linux.run_kernel(
189                         args=request.kernel_ar    167                         args=request.kernel_args,
190                         timeout=request.timeou !! 168                         timeout=None if request.alltests else request.timeout,
191                         filter_glob=filter_glo    169                         filter_glob=filter_glob,
192                         filter=request.filter, << 
193                         filter_action=request. << 
194                         build_dir=request.buil    170                         build_dir=request.build_dir)
195                                                   171 
196                 _, test_result = parse_tests(r    172                 _, test_result = parse_tests(request, metadata, run_result)
197                 # run_kernel() doesn't block o    173                 # run_kernel() doesn't block on the kernel exiting.
198                 # That only happens after we g    174                 # That only happens after we get the last line of output from `run_result`.
199                 # So exec_time here actually c    175                 # So exec_time here actually contains parsing + execution time, which is fine.
200                 test_end = time.time()            176                 test_end = time.time()
201                 exec_time += test_end - test_s    177                 exec_time += test_end - test_start
202                                                   178 
203                 test_counts.add_subtest_counts    179                 test_counts.add_subtest_counts(test_result.counts)
204                                                   180 
205         if len(filter_globs) == 1 and test_cou    181         if len(filter_globs) == 1 and test_counts.crashed > 0:
206                 bd = request.build_dir            182                 bd = request.build_dir
207                 print('The kernel seems to hav    183                 print('The kernel seems to have crashed; you can decode the stack traces with:')
208                 print('$ scripts/decode_stackt    184                 print('$ scripts/decode_stacktrace.sh {}/vmlinux {} < {} | tee {}/decoded.log | {} parse'.format(
209                                 bd, bd, kunit_    185                                 bd, bd, kunit_kernel.get_outfile_path(bd), bd, sys.argv[0]))
210                                                   186 
211         kunit_status = _map_to_overall_status(    187         kunit_status = _map_to_overall_status(test_counts.get_status())
212         return KunitResult(status=kunit_status    188         return KunitResult(status=kunit_status, elapsed_time=exec_time)
213                                                   189 
214 def _map_to_overall_status(test_status: kunit_    190 def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus:
215         if test_status in (kunit_parser.TestSt    191         if test_status in (kunit_parser.TestStatus.SUCCESS, kunit_parser.TestStatus.SKIPPED):
216                 return KunitStatus.SUCCESS        192                 return KunitStatus.SUCCESS
217         return KunitStatus.TEST_FAILURE           193         return KunitStatus.TEST_FAILURE
218                                                   194 
219 def parse_tests(request: KunitParseRequest, me    195 def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]:
220         parse_start = time.time()                 196         parse_start = time.time()
221                                                   197 
                                                   >> 198         test_result = kunit_parser.Test()
                                                   >> 199 
222         if request.raw_output:                    200         if request.raw_output:
223                 # Treat unparsed results as on    201                 # Treat unparsed results as one passing test.
224                 fake_test = kunit_parser.Test( !! 202                 test_result.status = kunit_parser.TestStatus.SUCCESS
225                 fake_test.status = kunit_parse !! 203                 test_result.counts.passed = 1
226                 fake_test.counts.passed = 1    << 
227                                                   204 
228                 output: Iterable[str] = input_    205                 output: Iterable[str] = input_data
229                 if request.raw_output == 'all'    206                 if request.raw_output == 'all':
230                         pass                      207                         pass
231                 elif request.raw_output == 'ku    208                 elif request.raw_output == 'kunit':
232                         output = kunit_parser.    209                         output = kunit_parser.extract_tap_lines(output)
233                 for line in output:               210                 for line in output:
234                         print(line.rstrip())      211                         print(line.rstrip())
235                 parse_time = time.time() - par << 
236                 return KunitResult(KunitStatus << 
237                                                << 
238                                                   212 
239         # Actually parse the test results.     !! 213         else:
240         test = kunit_parser.parse_run_tests(in !! 214                 test_result = kunit_parser.parse_run_tests(input_data)
241         parse_time = time.time() - parse_start !! 215         parse_end = time.time()
242                                                   216 
243         if request.json:                          217         if request.json:
244                 json_str = kunit_json.get_json    218                 json_str = kunit_json.get_json_result(
245                                         test=t !! 219                                         test=test_result,
246                                         metada    220                                         metadata=metadata)
247                 if request.json == 'stdout':      221                 if request.json == 'stdout':
248                         print(json_str)           222                         print(json_str)
249                 else:                             223                 else:
250                         with open(request.json    224                         with open(request.json, 'w') as f:
251                                 f.write(json_s    225                                 f.write(json_str)
252                         stdout.print_with_time    226                         stdout.print_with_timestamp("Test results stored in %s" %
253                                 os.path.abspat    227                                 os.path.abspath(request.json))
254                                                   228 
255         if test.status != kunit_parser.TestSta !! 229         if test_result.status != kunit_parser.TestStatus.SUCCESS:
256                 return KunitResult(KunitStatus !! 230                 return KunitResult(KunitStatus.TEST_FAILURE, parse_end - parse_start), test_result
257                                                   231 
258         return KunitResult(KunitStatus.SUCCESS !! 232         return KunitResult(KunitStatus.SUCCESS, parse_end - parse_start), test_result
259                                                   233 
260 def run_tests(linux: kunit_kernel.LinuxSourceT    234 def run_tests(linux: kunit_kernel.LinuxSourceTree,
261               request: KunitRequest) -> KunitR    235               request: KunitRequest) -> KunitResult:
262         run_start = time.time()                   236         run_start = time.time()
263                                                   237 
264         config_result = config_tests(linux, re    238         config_result = config_tests(linux, request)
265         if config_result.status != KunitStatus    239         if config_result.status != KunitStatus.SUCCESS:
266                 return config_result              240                 return config_result
267                                                   241 
268         build_result = build_tests(linux, requ    242         build_result = build_tests(linux, request)
269         if build_result.status != KunitStatus.    243         if build_result.status != KunitStatus.SUCCESS:
270                 return build_result               244                 return build_result
271                                                   245 
272         exec_result = exec_tests(linux, reques    246         exec_result = exec_tests(linux, request)
273                                                   247 
274         run_end = time.time()                     248         run_end = time.time()
275                                                   249 
276         stdout.print_with_timestamp((             250         stdout.print_with_timestamp((
277                 'Elapsed time: %.3fs total, %.    251                 'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' +
278                 'building, %.3fs running\n') %    252                 'building, %.3fs running\n') % (
279                                 run_end - run_    253                                 run_end - run_start,
280                                 config_result.    254                                 config_result.elapsed_time,
281                                 build_result.e    255                                 build_result.elapsed_time,
282                                 exec_result.el    256                                 exec_result.elapsed_time))
283         return exec_result                        257         return exec_result
284                                                   258 
285 # Problem:                                        259 # Problem:
286 # $ kunit.py run --json                           260 # $ kunit.py run --json
287 # works as one would expect and prints the par    261 # works as one would expect and prints the parsed test results as JSON.
288 # $ kunit.py run --json suite_name                262 # $ kunit.py run --json suite_name
289 # would *not* pass suite_name as the filter_gl    263 # would *not* pass suite_name as the filter_glob and print as json.
290 # argparse will consider it to be another way     264 # argparse will consider it to be another way of writing
291 # $ kunit.py run --json=suite_name                265 # $ kunit.py run --json=suite_name
292 # i.e. it would run all tests, and dump the js    266 # i.e. it would run all tests, and dump the json to a `suite_name` file.
293 # So we hackily automatically rewrite --json =    267 # So we hackily automatically rewrite --json => --json=stdout
294 pseudo_bool_flag_defaults = {                     268 pseudo_bool_flag_defaults = {
295                 '--json': 'stdout',               269                 '--json': 'stdout',
296                 '--raw_output': 'kunit',          270                 '--raw_output': 'kunit',
297 }                                                 271 }
298 def massage_argv(argv: Sequence[str]) -> Seque    272 def massage_argv(argv: Sequence[str]) -> Sequence[str]:
299         def massage_arg(arg: str) -> str:         273         def massage_arg(arg: str) -> str:
300                 if arg not in pseudo_bool_flag    274                 if arg not in pseudo_bool_flag_defaults:
301                         return arg                275                         return arg
302                 return  f'{arg}={pseudo_bool_f    276                 return  f'{arg}={pseudo_bool_flag_defaults[arg]}'
303         return list(map(massage_arg, argv))       277         return list(map(massage_arg, argv))
304                                                   278 
305 def get_default_jobs() -> int:                    279 def get_default_jobs() -> int:
306         return len(os.sched_getaffinity(0))       280         return len(os.sched_getaffinity(0))
307                                                   281 
308 def add_common_opts(parser: argparse.ArgumentP !! 282 def add_common_opts(parser) -> None:
309         parser.add_argument('--build_dir',        283         parser.add_argument('--build_dir',
310                             help='As in the ma    284                             help='As in the make command, it specifies the build '
311                             'directory.',         285                             'directory.',
312                             type=str, default=    286                             type=str, default='.kunit', metavar='DIR')
313         parser.add_argument('--make_options',     287         parser.add_argument('--make_options',
314                             help='X=Y make opt    288                             help='X=Y make option, can be repeated.',
315                             action='append', m    289                             action='append', metavar='X=Y')
316         parser.add_argument('--alltests',         290         parser.add_argument('--alltests',
317                             help='Run all KUni !! 291                             help='Run all KUnit tests through allyesconfig',
318                             action='store_true    292                             action='store_true')
319         parser.add_argument('--kunitconfig',      293         parser.add_argument('--kunitconfig',
320                              help='Path to Kco    294                              help='Path to Kconfig fragment that enables KUnit tests.'
321                              ' If given a dire    295                              ' If given a directory, (e.g. lib/kunit), "/.kunitconfig" '
322                              'will get  automa    296                              'will get  automatically appended. If repeated, the files '
323                              'blindly concaten    297                              'blindly concatenated, which might not work in all cases.',
324                              action='append',     298                              action='append', metavar='PATHS')
325         parser.add_argument('--kconfig_add',      299         parser.add_argument('--kconfig_add',
326                              help='Additional     300                              help='Additional Kconfig options to append to the '
327                              '.kunitconfig, e.    301                              '.kunitconfig, e.g. CONFIG_KASAN=y. Can be repeated.',
328                             action='append', m    302                             action='append', metavar='CONFIG_X=Y')
329                                                   303 
330         parser.add_argument('--arch',             304         parser.add_argument('--arch',
331                             help=('Specifies t    305                             help=('Specifies the architecture to run tests under. '
332                                   'The archite    306                                   'The architecture specified here must match the '
333                                   'string pass    307                                   'string passed to the ARCH make param, '
334                                   'e.g. i386,     308                                   'e.g. i386, x86_64, arm, um, etc. Non-UML '
335                                   'architectur    309                                   'architectures run on QEMU.'),
336                             type=str, default=    310                             type=str, default='um', metavar='ARCH')
337                                                   311 
338         parser.add_argument('--cross_compile',    312         parser.add_argument('--cross_compile',
339                             help=('Sets make\'    313                             help=('Sets make\'s CROSS_COMPILE variable; it should '
340                                   'be set to a    314                                   'be set to a toolchain path prefix (the prefix '
341                                   'of gcc and     315                                   'of gcc and other tools in your toolchain, for '
342                                   'example `sp    316                                   'example `sparc64-linux-gnu-` if you have the '
343                                   'sparc toolc    317                                   'sparc toolchain installed on your system, or '
344                                   '`$HOME/tool    318                                   '`$HOME/toolchains/microblaze/gcc-9.2.0-nolibc/microblaze-linux/bin/microblaze-linux-` '
345                                   'if you have    319                                   'if you have downloaded the microblaze toolchain '
346                                   'from the 0-    320                                   'from the 0-day website to a directory in your '
347                                   'home direct    321                                   'home directory called `toolchains`).'),
348                             metavar='PREFIX')     322                             metavar='PREFIX')
349                                                   323 
350         parser.add_argument('--qemu_config',      324         parser.add_argument('--qemu_config',
351                             help=('Takes a pat    325                             help=('Takes a path to a path to a file containing '
352                                   'a QemuArchP    326                                   'a QemuArchParams object.'),
353                             type=str, metavar=    327                             type=str, metavar='FILE')
354                                                   328 
355         parser.add_argument('--qemu_args',        329         parser.add_argument('--qemu_args',
356                             help='Additional Q    330                             help='Additional QEMU arguments, e.g. "-smp 8"',
357                             action='append', m    331                             action='append', metavar='')
358                                                   332 
359 def add_build_opts(parser: argparse.ArgumentPa !! 333 def add_build_opts(parser) -> None:
360         parser.add_argument('--jobs',             334         parser.add_argument('--jobs',
361                             help='As in the ma    335                             help='As in the make command, "Specifies  the number of '
362                             'jobs (commands) t    336                             'jobs (commands) to run simultaneously."',
363                             type=int, default=    337                             type=int, default=get_default_jobs(), metavar='N')
364                                                   338 
365 def add_exec_opts(parser: argparse.ArgumentPar !! 339 def add_exec_opts(parser) -> None:
366         parser.add_argument('--timeout',          340         parser.add_argument('--timeout',
367                             help='maximum numb    341                             help='maximum number of seconds to allow for all tests '
368                             'to run. This does    342                             'to run. This does not include time taken to build the '
369                             'tests.',             343                             'tests.',
370                             type=int,             344                             type=int,
371                             default=300,          345                             default=300,
372                             metavar='SECONDS')    346                             metavar='SECONDS')
373         parser.add_argument('filter_glob',        347         parser.add_argument('filter_glob',
374                             help='Filter which    348                             help='Filter which KUnit test suites/tests run at '
375                             'boot-time, e.g. l    349                             'boot-time, e.g. list* or list*.*del_test',
376                             type=str,             350                             type=str,
377                             nargs='?',            351                             nargs='?',
378                             default='',           352                             default='',
379                             metavar='filter_gl    353                             metavar='filter_glob')
380         parser.add_argument('--filter',        << 
381                             help='Filter KUnit << 
382                             'e.g. module=examp << 
383                             type=str,          << 
384                                 default='')    << 
385         parser.add_argument('--filter_action', << 
386                             help='If set to sk << 
387                                 'e.g. --filter << 
388                             type=str,          << 
389                                 choices=['skip << 
390         parser.add_argument('--kernel_args',      354         parser.add_argument('--kernel_args',
391                             help='Kernel comma    355                             help='Kernel command-line parameters. Maybe be repeated',
392                              action='append',     356                              action='append', metavar='')
393         parser.add_argument('--run_isolated',     357         parser.add_argument('--run_isolated', help='If set, boot the kernel for each '
394                             'individual suite/    358                             'individual suite/test. This is can be useful for debugging '
395                             'a non-hermetic te    359                             'a non-hermetic test, one that might pass/fail based on '
396                             'what ran before i    360                             'what ran before it.',
397                             type=str,             361                             type=str,
398                             choices=['suite',     362                             choices=['suite', 'test'])
399         parser.add_argument('--list_tests', he << 
400                             'run.',            << 
401                             action='store_true << 
402         parser.add_argument('--list_tests_attr << 
403                             'attributes.',     << 
404                             action='store_true << 
405                                                   363 
406 def add_parse_opts(parser: argparse.ArgumentPa !! 364 def add_parse_opts(parser) -> None:
407         parser.add_argument('--raw_output', he !! 365         parser.add_argument('--raw_output', help='If set don\'t format output from kernel. '
408                             'By default, filte !! 366                             'If set to --raw_output=kunit, filters to just KUnit output.',
409                             '--raw_output=all  << 
410                              type=str, nargs='    367                              type=str, nargs='?', const='all', default=None, choices=['all', 'kunit'])
411         parser.add_argument('--json',             368         parser.add_argument('--json',
412                             nargs='?',            369                             nargs='?',
413                             help='Prints parse !! 370                             help='Stores test results in a JSON, and either '
414                             'a filename is spe !! 371                             'prints to stdout or saves to file if a '
                                                   >> 372                             'filename is specified',
415                             type=str, const='s    373                             type=str, const='stdout', default=None, metavar='FILE')
416                                                   374 
417                                                   375 
418 def tree_from_args(cli_args: argparse.Namespac    376 def tree_from_args(cli_args: argparse.Namespace) -> kunit_kernel.LinuxSourceTree:
419         """Returns a LinuxSourceTree based on     377         """Returns a LinuxSourceTree based on the user's arguments."""
420         # Allow users to specify multiple argu    378         # Allow users to specify multiple arguments in one string, e.g. '-smp 8'
421         qemu_args: List[str] = []                 379         qemu_args: List[str] = []
422         if cli_args.qemu_args:                    380         if cli_args.qemu_args:
423                 for arg in cli_args.qemu_args:    381                 for arg in cli_args.qemu_args:
424                         qemu_args.extend(shlex    382                         qemu_args.extend(shlex.split(arg))
425                                                   383 
426         kunitconfigs = cli_args.kunitconfig if << 
427         if cli_args.alltests:                  << 
428                 # Prepend so user-specified op << 
429                 # --kunitconfig options to hav << 
430                 kunitconfigs = [kunit_kernel.A << 
431                                                << 
432         return kunit_kernel.LinuxSourceTree(cl    384         return kunit_kernel.LinuxSourceTree(cli_args.build_dir,
433                         kunitconfig_paths=kuni !! 385                         kunitconfig_paths=cli_args.kunitconfig,
434                         kconfig_add=cli_args.k    386                         kconfig_add=cli_args.kconfig_add,
435                         arch=cli_args.arch,       387                         arch=cli_args.arch,
436                         cross_compile=cli_args    388                         cross_compile=cli_args.cross_compile,
437                         qemu_config_path=cli_a    389                         qemu_config_path=cli_args.qemu_config,
438                         extra_qemu_args=qemu_a    390                         extra_qemu_args=qemu_args)
439                                                   391 
440                                                   392 
441 def run_handler(cli_args: argparse.Namespace)  !! 393 def main(argv):
442         if not os.path.exists(cli_args.build_d << 
443                 os.mkdir(cli_args.build_dir)   << 
444                                                << 
445         linux = tree_from_args(cli_args)       << 
446         request = KunitRequest(build_dir=cli_a << 
447                                         make_o << 
448                                         jobs=c << 
449                                         raw_ou << 
450                                         json=c << 
451                                         timeou << 
452                                         filter << 
453                                         filter << 
454                                         filter << 
455                                         kernel << 
456                                         run_is << 
457                                         list_t << 
458                                         list_t << 
459         result = run_tests(linux, request)     << 
460         if result.status != KunitStatus.SUCCES << 
461                 sys.exit(1)                    << 
462                                                << 
463                                                << 
464 def config_handler(cli_args: argparse.Namespac << 
465         if cli_args.build_dir and (            << 
466                         not os.path.exists(cli << 
467                 os.mkdir(cli_args.build_dir)   << 
468                                                << 
469         linux = tree_from_args(cli_args)       << 
470         request = KunitConfigRequest(build_dir << 
471                                                << 
472         result = config_tests(linux, request)  << 
473         stdout.print_with_timestamp((          << 
474                 'Elapsed time: %.3fs\n') % (   << 
475                         result.elapsed_time))  << 
476         if result.status != KunitStatus.SUCCES << 
477                 sys.exit(1)                    << 
478                                                << 
479                                                << 
480 def build_handler(cli_args: argparse.Namespace << 
481         linux = tree_from_args(cli_args)       << 
482         request = KunitBuildRequest(build_dir= << 
483                                         make_o << 
484                                         jobs=c << 
485         result = config_and_build_tests(linux, << 
486         stdout.print_with_timestamp((          << 
487                 'Elapsed time: %.3fs\n') % (   << 
488                         result.elapsed_time))  << 
489         if result.status != KunitStatus.SUCCES << 
490                 sys.exit(1)                    << 
491                                                << 
492                                                << 
493 def exec_handler(cli_args: argparse.Namespace) << 
494         linux = tree_from_args(cli_args)       << 
495         exec_request = KunitExecRequest(raw_ou << 
496                                         build_ << 
497                                         json=c << 
498                                         timeou << 
499                                         filter << 
500                                         filter << 
501                                         filter << 
502                                         kernel << 
503                                         run_is << 
504                                         list_t << 
505                                         list_t << 
506         result = exec_tests(linux, exec_reques << 
507         stdout.print_with_timestamp((          << 
508                 'Elapsed time: %.3fs\n') % (re << 
509         if result.status != KunitStatus.SUCCES << 
510                 sys.exit(1)                    << 
511                                                << 
512                                                << 
513 def parse_handler(cli_args: argparse.Namespace << 
514         if cli_args.file is None:              << 
515                 sys.stdin.reconfigure(errors=' << 
516                 kunit_output = sys.stdin  # ty << 
517         else:                                  << 
518                 with open(cli_args.file, 'r',  << 
519                         kunit_output = f.read( << 
520         # We know nothing about how the result << 
521         metadata = kunit_json.Metadata()       << 
522         request = KunitParseRequest(raw_output << 
523                                         json=c << 
524         result, _ = parse_tests(request, metad << 
525         if result.status != KunitStatus.SUCCES << 
526                 sys.exit(1)                    << 
527                                                << 
528                                                << 
529 subcommand_handlers_map = {                    << 
530         'run': run_handler,                    << 
531         'config': config_handler,              << 
532         'build': build_handler,                << 
533         'exec': exec_handler,                  << 
534         'parse': parse_handler                 << 
535 }                                              << 
536                                                << 
537                                                << 
538 def main(argv: Sequence[str]) -> None:         << 
539         parser = argparse.ArgumentParser(         394         parser = argparse.ArgumentParser(
540                         description='Helps wri    395                         description='Helps writing and running KUnit tests.')
541         subparser = parser.add_subparsers(dest    396         subparser = parser.add_subparsers(dest='subcommand')
542                                                   397 
543         # The 'run' command will config, build    398         # The 'run' command will config, build, exec, and parse in one go.
544         run_parser = subparser.add_parser('run    399         run_parser = subparser.add_parser('run', help='Runs KUnit tests.')
545         add_common_opts(run_parser)               400         add_common_opts(run_parser)
546         add_build_opts(run_parser)                401         add_build_opts(run_parser)
547         add_exec_opts(run_parser)                 402         add_exec_opts(run_parser)
548         add_parse_opts(run_parser)                403         add_parse_opts(run_parser)
549                                                   404 
550         config_parser = subparser.add_parser('    405         config_parser = subparser.add_parser('config',
551                                                   406                                                 help='Ensures that .config contains all of '
552                                                   407                                                 'the options in .kunitconfig')
553         add_common_opts(config_parser)            408         add_common_opts(config_parser)
554                                                   409 
555         build_parser = subparser.add_parser('b    410         build_parser = subparser.add_parser('build', help='Builds a kernel with KUnit tests')
556         add_common_opts(build_parser)             411         add_common_opts(build_parser)
557         add_build_opts(build_parser)              412         add_build_opts(build_parser)
558                                                   413 
559         exec_parser = subparser.add_parser('ex    414         exec_parser = subparser.add_parser('exec', help='Run a kernel with KUnit tests')
560         add_common_opts(exec_parser)              415         add_common_opts(exec_parser)
561         add_exec_opts(exec_parser)                416         add_exec_opts(exec_parser)
562         add_parse_opts(exec_parser)               417         add_parse_opts(exec_parser)
563                                                   418 
564         # The 'parse' option is special, as it    419         # The 'parse' option is special, as it doesn't need the kernel source
565         # (therefore there is no need for a bu    420         # (therefore there is no need for a build_dir, hence no add_common_opts)
566         # and the '--file' argument is not rel    421         # and the '--file' argument is not relevant to 'run', so isn't in
567         # add_parse_opts()                        422         # add_parse_opts()
568         parse_parser = subparser.add_parser('p    423         parse_parser = subparser.add_parser('parse',
569                                             he    424                                             help='Parses KUnit results from a file, '
570                                             'a    425                                             'and parses formatted results.')
571         add_parse_opts(parse_parser)              426         add_parse_opts(parse_parser)
572         parse_parser.add_argument('file',         427         parse_parser.add_argument('file',
573                                   help='Specif    428                                   help='Specifies the file to read results from.',
574                                   type=str, na    429                                   type=str, nargs='?', metavar='input_file')
575                                                   430 
576         cli_args = parser.parse_args(massage_a    431         cli_args = parser.parse_args(massage_argv(argv))
577                                                   432 
578         if get_kernel_root_path():                433         if get_kernel_root_path():
579                 os.chdir(get_kernel_root_path(    434                 os.chdir(get_kernel_root_path())
580                                                   435 
581         subcomand_handler = subcommand_handler !! 436         if cli_args.subcommand == 'run':
582                                                !! 437                 if not os.path.exists(cli_args.build_dir):
583         if subcomand_handler is None:          !! 438                         os.mkdir(cli_args.build_dir)
                                                   >> 439 
                                                   >> 440                 linux = tree_from_args(cli_args)
                                                   >> 441                 request = KunitRequest(build_dir=cli_args.build_dir,
                                                   >> 442                                        make_options=cli_args.make_options,
                                                   >> 443                                        jobs=cli_args.jobs,
                                                   >> 444                                        alltests=cli_args.alltests,
                                                   >> 445                                        raw_output=cli_args.raw_output,
                                                   >> 446                                        json=cli_args.json,
                                                   >> 447                                        timeout=cli_args.timeout,
                                                   >> 448                                        filter_glob=cli_args.filter_glob,
                                                   >> 449                                        kernel_args=cli_args.kernel_args,
                                                   >> 450                                        run_isolated=cli_args.run_isolated)
                                                   >> 451                 result = run_tests(linux, request)
                                                   >> 452                 if result.status != KunitStatus.SUCCESS:
                                                   >> 453                         sys.exit(1)
                                                   >> 454         elif cli_args.subcommand == 'config':
                                                   >> 455                 if cli_args.build_dir and (
                                                   >> 456                                 not os.path.exists(cli_args.build_dir)):
                                                   >> 457                         os.mkdir(cli_args.build_dir)
                                                   >> 458 
                                                   >> 459                 linux = tree_from_args(cli_args)
                                                   >> 460                 request = KunitConfigRequest(build_dir=cli_args.build_dir,
                                                   >> 461                                              make_options=cli_args.make_options)
                                                   >> 462                 result = config_tests(linux, request)
                                                   >> 463                 stdout.print_with_timestamp((
                                                   >> 464                         'Elapsed time: %.3fs\n') % (
                                                   >> 465                                 result.elapsed_time))
                                                   >> 466                 if result.status != KunitStatus.SUCCESS:
                                                   >> 467                         sys.exit(1)
                                                   >> 468         elif cli_args.subcommand == 'build':
                                                   >> 469                 linux = tree_from_args(cli_args)
                                                   >> 470                 request = KunitBuildRequest(build_dir=cli_args.build_dir,
                                                   >> 471                                             make_options=cli_args.make_options,
                                                   >> 472                                             jobs=cli_args.jobs,
                                                   >> 473                                             alltests=cli_args.alltests)
                                                   >> 474                 result = config_and_build_tests(linux, request)
                                                   >> 475                 stdout.print_with_timestamp((
                                                   >> 476                         'Elapsed time: %.3fs\n') % (
                                                   >> 477                                 result.elapsed_time))
                                                   >> 478                 if result.status != KunitStatus.SUCCESS:
                                                   >> 479                         sys.exit(1)
                                                   >> 480         elif cli_args.subcommand == 'exec':
                                                   >> 481                 linux = tree_from_args(cli_args)
                                                   >> 482                 exec_request = KunitExecRequest(raw_output=cli_args.raw_output,
                                                   >> 483                                                 build_dir=cli_args.build_dir,
                                                   >> 484                                                 json=cli_args.json,
                                                   >> 485                                                 timeout=cli_args.timeout,
                                                   >> 486                                                 alltests=cli_args.alltests,
                                                   >> 487                                                 filter_glob=cli_args.filter_glob,
                                                   >> 488                                                 kernel_args=cli_args.kernel_args,
                                                   >> 489                                                 run_isolated=cli_args.run_isolated)
                                                   >> 490                 result = exec_tests(linux, exec_request)
                                                   >> 491                 stdout.print_with_timestamp((
                                                   >> 492                         'Elapsed time: %.3fs\n') % (result.elapsed_time))
                                                   >> 493                 if result.status != KunitStatus.SUCCESS:
                                                   >> 494                         sys.exit(1)
                                                   >> 495         elif cli_args.subcommand == 'parse':
                                                   >> 496                 if cli_args.file is None:
                                                   >> 497                         sys.stdin.reconfigure(errors='backslashreplace')  # pytype: disable=attribute-error
                                                   >> 498                         kunit_output = sys.stdin
                                                   >> 499                 else:
                                                   >> 500                         with open(cli_args.file, 'r', errors='backslashreplace') as f:
                                                   >> 501                                 kunit_output = f.read().splitlines()
                                                   >> 502                 # We know nothing about how the result was created!
                                                   >> 503                 metadata = kunit_json.Metadata()
                                                   >> 504                 request = KunitParseRequest(raw_output=cli_args.raw_output,
                                                   >> 505                                             json=cli_args.json)
                                                   >> 506                 result, _ = parse_tests(request, metadata, kunit_output)
                                                   >> 507                 if result.status != KunitStatus.SUCCESS:
                                                   >> 508                         sys.exit(1)
                                                   >> 509         else:
584                 parser.print_help()               510                 parser.print_help()
585                 return                         << 
586                                                << 
587         subcomand_handler(cli_args)            << 
588                                                << 
589                                                   511 
590 if __name__ == '__main__':                        512 if __name__ == '__main__':
591         main(sys.argv[1:])                        513         main(sys.argv[1:])
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php