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