Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kunit: tool: misc cleanups

This primarily comes from running pylint over kunit tool code and
ignoring some warnings we don't care about.
If we ever got a fully clean setup, we could add this to run_checks.py,
but we're not there yet.

Fix things like
* Drop unused imports
* check `is None`, not `== None` (see PEP 8)
* remove redundant parens around returns
* remove redundant `else` / convert `elif` to `if` where appropriate
* rename make_arch_qemuconfig() param to base_kunitconfig (this is the
name used in the subclass, and it's a better one)
* kunit_tool_test: check the exit code for SystemExit (could be 0)

Signed-off-by: Daniel Latypov <dlatypov@google.com>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Daniel Latypov and committed by
Shuah Khan
0453f984 94507ee3

+39 -46
+4 -5
tools/testing/kunit/kunit.py
··· 124 124 lines.pop() 125 125 126 126 # Filter out any extraneous non-test output that might have gotten mixed in. 127 - return [l for l in lines if re.match('^[^\s.]+\.[^\s.]+$', l)] 127 + return [l for l in lines if re.match(r'^[^\s.]+\.[^\s.]+$', l)] 128 128 129 129 def _suites_from_test_list(tests: List[str]) -> List[str]: 130 130 """Extracts all the suites from an ordered list of tests.""" ··· 188 188 def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus: 189 189 if test_status in (kunit_parser.TestStatus.SUCCESS, kunit_parser.TestStatus.SKIPPED): 190 190 return KunitStatus.SUCCESS 191 - else: 192 - return KunitStatus.TEST_FAILURE 191 + return KunitStatus.TEST_FAILURE 193 192 194 193 def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]: 195 194 parse_start = time.time() ··· 352 353 'a non-hermetic test, one that might pass/fail based on ' 353 354 'what ran before it.', 354 355 type=str, 355 - choices=['suite', 'test']), 356 + choices=['suite', 'test']) 356 357 357 358 def add_parse_opts(parser) -> None: 358 359 parser.add_argument('--raw_output', help='If set don\'t format output from kernel. ' ··· 496 497 if result.status != KunitStatus.SUCCESS: 497 498 sys.exit(1) 498 499 elif cli_args.subcommand == 'parse': 499 - if cli_args.file == None: 500 + if cli_args.file is None: 500 501 sys.stdin.reconfigure(errors='backslashreplace') # pytype: disable=attribute-error 501 502 kunit_output = sys.stdin 502 503 else:
+5 -7
tools/testing/kunit/kunit_config.py
··· 20 20 21 21 def __str__(self) -> str: 22 22 if self.value == 'n': 23 - return r'# CONFIG_%s is not set' % (self.name) 24 - else: 25 - return r'CONFIG_%s=%s' % (self.name, self.value) 23 + return f'# CONFIG_{self.name} is not set' 24 + return f'CONFIG_{self.name}={self.value}' 26 25 27 26 28 27 class KconfigParseError(Exception): 29 28 """Error parsing Kconfig defconfig or .config.""" 30 29 31 30 32 - class Kconfig(object): 31 + class Kconfig: 33 32 """Represents defconfig or .config specified using the Kconfig language.""" 34 33 35 34 def __init__(self) -> None: ··· 48 49 if a.value == 'n': 49 50 continue 50 51 return False 51 - elif a.value != b: 52 + if a.value != b: 52 53 return False 53 54 return True 54 55 ··· 90 91 91 92 if line[0] == '#': 92 93 continue 93 - else: 94 - raise KconfigParseError('Failed to parse: ' + line) 94 + raise KconfigParseError('Failed to parse: ' + line) 95 95 return kconfig
+1 -4
tools/testing/kunit/kunit_json.py
··· 8 8 9 9 from dataclasses import dataclass 10 10 import json 11 - import os 12 - 13 - import kunit_parser 11 + from typing import Any, Dict 14 12 15 13 from kunit_parser import Test, TestStatus 16 - from typing import Any, Dict 17 14 18 15 @dataclass 19 16 class Metadata:
+5 -5
tools/testing/kunit/kunit_kernel.py
··· 38 38 """Represents an error trying to build the Linux kernel.""" 39 39 40 40 41 - class LinuxSourceTreeOperations(object): 41 + class LinuxSourceTreeOperations: 42 42 """An abstraction over command line operations performed on a source tree.""" 43 43 44 44 def __init__(self, linux_arch: str, cross_compile: Optional[str]): ··· 53 53 except subprocess.CalledProcessError as e: 54 54 raise ConfigError(e.output.decode()) 55 55 56 - def make_arch_qemuconfig(self, kconfig: kunit_config.Kconfig) -> None: 56 + def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> None: 57 57 pass 58 58 59 59 def make_allyesconfig(self, build_dir: str, make_options) -> None: ··· 182 182 config_path = os.path.join(QEMU_CONFIGS_DIR, arch + '.py') 183 183 if arch == 'um': 184 184 return LinuxSourceTreeOperationsUml(cross_compile=cross_compile) 185 - elif os.path.isfile(config_path): 185 + if os.path.isfile(config_path): 186 186 return get_source_tree_ops_from_qemu_config(config_path, cross_compile)[1] 187 187 188 188 options = [f[:-3] for f in os.listdir(QEMU_CONFIGS_DIR) if f.endswith('.py')] ··· 213 213 return params.linux_arch, LinuxSourceTreeOperationsQemu( 214 214 params, cross_compile=cross_compile) 215 215 216 - class LinuxSourceTree(object): 216 + class LinuxSourceTree: 217 217 """Represents a Linux kernel source tree with KUnit tests.""" 218 218 219 219 def __init__( ··· 368 368 waiter.join() 369 369 subprocess.call(['stty', 'sane']) 370 370 371 - def signal_handler(self, sig, frame) -> None: 371 + def signal_handler(self, unused_sig, unused_frame) -> None: 372 372 logging.error('Build interruption occurred. Cleaning console.') 373 373 subprocess.call(['stty', 'sane'])
+17 -20
tools/testing/kunit/kunit_parser.py
··· 15 15 16 16 import datetime 17 17 from enum import Enum, auto 18 - from functools import reduce 19 18 from typing import Iterable, Iterator, List, Optional, Tuple 20 19 21 - class Test(object): 20 + class Test: 22 21 """ 23 22 A class to represent a test parsed from KTAP results. All KTAP 24 23 results within a test log are stored in a main Test object as ··· 125 126 """ 126 127 if self.total() == 0: 127 128 return TestStatus.NO_TESTS 128 - elif self.crashed: 129 + if self.crashed: 129 130 # Crashes should take priority. 130 131 return TestStatus.TEST_CRASHED 131 - elif self.failed: 132 + if self.failed: 132 133 return TestStatus.FAILURE 133 - elif self.passed: 134 + if self.passed: 134 135 # No failures or crashes, looks good! 135 136 return TestStatus.SUCCESS 136 - else: 137 - # We have only skipped tests. 138 - return TestStatus.SKIPPED 137 + # We have only skipped tests. 138 + return TestStatus.SKIPPED 139 139 140 140 def add_status(self, status: TestStatus) -> None: 141 141 """Increments the count for `status`.""" ··· 379 381 if not match: 380 382 return False 381 383 name = match.group(4) 382 - return (name == test.name) 384 + return name == test.name 383 385 384 386 def parse_test_result(lines: LineStream, test: Test, 385 387 expected_num: int) -> bool: ··· 551 553 String containing formatted test result 552 554 """ 553 555 if test.status == TestStatus.SUCCESS: 554 - return (green('[PASSED] ') + test.name) 555 - elif test.status == TestStatus.SKIPPED: 556 - return (yellow('[SKIPPED] ') + test.name) 557 - elif test.status == TestStatus.NO_TESTS: 558 - return (yellow('[NO TESTS RUN] ') + test.name) 559 - elif test.status == TestStatus.TEST_CRASHED: 556 + return green('[PASSED] ') + test.name 557 + if test.status == TestStatus.SKIPPED: 558 + return yellow('[SKIPPED] ') + test.name 559 + if test.status == TestStatus.NO_TESTS: 560 + return yellow('[NO TESTS RUN] ') + test.name 561 + if test.status == TestStatus.TEST_CRASHED: 560 562 print_log(test.log) 561 - return (red('[CRASHED] ') + test.name) 562 - else: 563 - print_log(test.log) 564 - return (red('[FAILED] ') + test.name) 563 + return red('[CRASHED] ') + test.name 564 + print_log(test.log) 565 + return red('[FAILED] ') + test.name 565 566 566 567 def print_test_result(test: Test) -> None: 567 568 """ ··· 604 607 """ 605 608 if test.status == TestStatus.SUCCESS: 606 609 color = green 607 - elif test.status == TestStatus.SKIPPED or test.status == TestStatus.NO_TESTS: 610 + elif test.status in (TestStatus.SKIPPED, TestStatus.NO_TESTS): 608 611 color = yellow 609 612 else: 610 613 color = red
+6 -4
tools/testing/kunit/kunit_tool_test.py
··· 251 251 252 252 def test_ignores_hyphen(self): 253 253 hyphen_log = test_data_path('test_strip_hyphen.log') 254 - file = open(hyphen_log) 255 - result = kunit_parser.parse_run_tests(file.readlines()) 254 + with open(hyphen_log) as file: 255 + result = kunit_parser.parse_run_tests(file.readlines()) 256 256 257 257 # A skipped test does not fail the whole suite. 258 258 self.assertEqual( ··· 347 347 called_times = 0 348 348 def generator(): 349 349 nonlocal called_times 350 - for i in range(1,5): 350 + for _ in range(1,5): 351 351 called_times += 1 352 352 yield called_times, str(called_times) 353 353 ··· 553 553 def test_exec_no_tests(self): 554 554 self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0']) 555 555 with self.assertRaises(SystemExit) as e: 556 - kunit.main(['run'], self.linux_source_mock) 556 + kunit.main(['run'], self.linux_source_mock) 557 + self.assertEqual(e.exception.code, 1) 557 558 self.linux_source_mock.run_kernel.assert_called_once_with( 558 559 args=None, build_dir='.kunit', filter_glob='', timeout=300) 559 560 self.print_mock.assert_any_call(StrContains(' 0 tests run!')) ··· 589 588 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 590 589 with self.assertRaises(SystemExit) as e: 591 590 kunit.main(['run', '--raw_output=invalid'], self.linux_source_mock) 591 + self.assertNotEqual(e.exception.code, 0) 592 592 593 593 def test_run_raw_output_does_not_take_positional_args(self): 594 594 # --raw_output is a string flag, but we don't want it to consume
+1 -1
tools/testing/kunit/run_checks.py
··· 14 14 import subprocess 15 15 import sys 16 16 import textwrap 17 - from typing import Dict, List, Sequence, Tuple 17 + from typing import Dict, List, Sequence 18 18 19 19 ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__)) 20 20 TIMEOUT = datetime.timedelta(minutes=5).total_seconds()