~ [ 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.16.20)


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