Commit 0453f984 authored by Daniel Latypov's avatar Daniel Latypov Committed by Shuah Khan

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: default avatarDaniel Latypov <dlatypov@google.com>
Reviewed-by: default avatarDavid Gow <davidgow@google.com>
Reviewed-by: default avatarBrendan Higgins <brendanhiggins@google.com>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
parent 94507ee3
...@@ -124,7 +124,7 @@ def _list_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) ...@@ -124,7 +124,7 @@ def _list_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest)
lines.pop() lines.pop()
# Filter out any extraneous non-test output that might have gotten mixed in. # Filter out any extraneous non-test output that might have gotten mixed in.
return [l for l in lines if re.match('^[^\s.]+\.[^\s.]+$', l)] return [l for l in lines if re.match(r'^[^\s.]+\.[^\s.]+$', l)]
def _suites_from_test_list(tests: List[str]) -> List[str]: def _suites_from_test_list(tests: List[str]) -> List[str]:
"""Extracts all the suites from an ordered list of tests.""" """Extracts all the suites from an ordered list of tests."""
...@@ -188,8 +188,7 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) - ...@@ -188,8 +188,7 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) -
def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus: def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus:
if test_status in (kunit_parser.TestStatus.SUCCESS, kunit_parser.TestStatus.SKIPPED): if test_status in (kunit_parser.TestStatus.SUCCESS, kunit_parser.TestStatus.SKIPPED):
return KunitStatus.SUCCESS return KunitStatus.SUCCESS
else: return KunitStatus.TEST_FAILURE
return KunitStatus.TEST_FAILURE
def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]: def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]:
parse_start = time.time() parse_start = time.time()
...@@ -353,7 +352,7 @@ def add_exec_opts(parser) -> None: ...@@ -353,7 +352,7 @@ def add_exec_opts(parser) -> None:
'a non-hermetic test, one that might pass/fail based on ' 'a non-hermetic test, one that might pass/fail based on '
'what ran before it.', 'what ran before it.',
type=str, type=str,
choices=['suite', 'test']), choices=['suite', 'test'])
def add_parse_opts(parser) -> None: def add_parse_opts(parser) -> None:
parser.add_argument('--raw_output', help='If set don\'t format output from kernel. ' parser.add_argument('--raw_output', help='If set don\'t format output from kernel. '
...@@ -497,7 +496,7 @@ def main(argv, linux=None): ...@@ -497,7 +496,7 @@ def main(argv, linux=None):
if result.status != KunitStatus.SUCCESS: if result.status != KunitStatus.SUCCESS:
sys.exit(1) sys.exit(1)
elif cli_args.subcommand == 'parse': elif cli_args.subcommand == 'parse':
if cli_args.file == None: if cli_args.file is None:
sys.stdin.reconfigure(errors='backslashreplace') # pytype: disable=attribute-error sys.stdin.reconfigure(errors='backslashreplace') # pytype: disable=attribute-error
kunit_output = sys.stdin kunit_output = sys.stdin
else: else:
......
...@@ -20,16 +20,15 @@ class KconfigEntry: ...@@ -20,16 +20,15 @@ class KconfigEntry:
def __str__(self) -> str: def __str__(self) -> str:
if self.value == 'n': if self.value == 'n':
return r'# CONFIG_%s is not set' % (self.name) return f'# CONFIG_{self.name} is not set'
else: return f'CONFIG_{self.name}={self.value}'
return r'CONFIG_%s=%s' % (self.name, self.value)
class KconfigParseError(Exception): class KconfigParseError(Exception):
"""Error parsing Kconfig defconfig or .config.""" """Error parsing Kconfig defconfig or .config."""
class Kconfig(object): class Kconfig:
"""Represents defconfig or .config specified using the Kconfig language.""" """Represents defconfig or .config specified using the Kconfig language."""
def __init__(self) -> None: def __init__(self) -> None:
...@@ -49,7 +48,7 @@ class Kconfig(object): ...@@ -49,7 +48,7 @@ class Kconfig(object):
if a.value == 'n': if a.value == 'n':
continue continue
return False return False
elif a.value != b: if a.value != b:
return False return False
return True return True
...@@ -91,6 +90,5 @@ def parse_from_string(blob: str) -> Kconfig: ...@@ -91,6 +90,5 @@ def parse_from_string(blob: str) -> Kconfig:
if line[0] == '#': if line[0] == '#':
continue continue
else: raise KconfigParseError('Failed to parse: ' + line)
raise KconfigParseError('Failed to parse: ' + line)
return kconfig return kconfig
...@@ -8,12 +8,9 @@ ...@@ -8,12 +8,9 @@
from dataclasses import dataclass from dataclasses import dataclass
import json import json
import os from typing import Any, Dict
import kunit_parser
from kunit_parser import Test, TestStatus from kunit_parser import Test, TestStatus
from typing import Any, Dict
@dataclass @dataclass
class Metadata: class Metadata:
......
...@@ -38,7 +38,7 @@ class BuildError(Exception): ...@@ -38,7 +38,7 @@ class BuildError(Exception):
"""Represents an error trying to build the Linux kernel.""" """Represents an error trying to build the Linux kernel."""
class LinuxSourceTreeOperations(object): class LinuxSourceTreeOperations:
"""An abstraction over command line operations performed on a source tree.""" """An abstraction over command line operations performed on a source tree."""
def __init__(self, linux_arch: str, cross_compile: Optional[str]): def __init__(self, linux_arch: str, cross_compile: Optional[str]):
...@@ -53,7 +53,7 @@ class LinuxSourceTreeOperations(object): ...@@ -53,7 +53,7 @@ class LinuxSourceTreeOperations(object):
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
raise ConfigError(e.output.decode()) raise ConfigError(e.output.decode())
def make_arch_qemuconfig(self, kconfig: kunit_config.Kconfig) -> None: def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> None:
pass pass
def make_allyesconfig(self, build_dir: str, make_options) -> None: def make_allyesconfig(self, build_dir: str, make_options) -> None:
...@@ -182,7 +182,7 @@ def get_source_tree_ops(arch: str, cross_compile: Optional[str]) -> LinuxSourceT ...@@ -182,7 +182,7 @@ def get_source_tree_ops(arch: str, cross_compile: Optional[str]) -> LinuxSourceT
config_path = os.path.join(QEMU_CONFIGS_DIR, arch + '.py') config_path = os.path.join(QEMU_CONFIGS_DIR, arch + '.py')
if arch == 'um': if arch == 'um':
return LinuxSourceTreeOperationsUml(cross_compile=cross_compile) return LinuxSourceTreeOperationsUml(cross_compile=cross_compile)
elif os.path.isfile(config_path): if os.path.isfile(config_path):
return get_source_tree_ops_from_qemu_config(config_path, cross_compile)[1] return get_source_tree_ops_from_qemu_config(config_path, cross_compile)[1]
options = [f[:-3] for f in os.listdir(QEMU_CONFIGS_DIR) if f.endswith('.py')] options = [f[:-3] for f in os.listdir(QEMU_CONFIGS_DIR) if f.endswith('.py')]
...@@ -213,7 +213,7 @@ def get_source_tree_ops_from_qemu_config(config_path: str, ...@@ -213,7 +213,7 @@ def get_source_tree_ops_from_qemu_config(config_path: str,
return params.linux_arch, LinuxSourceTreeOperationsQemu( return params.linux_arch, LinuxSourceTreeOperationsQemu(
params, cross_compile=cross_compile) params, cross_compile=cross_compile)
class LinuxSourceTree(object): class LinuxSourceTree:
"""Represents a Linux kernel source tree with KUnit tests.""" """Represents a Linux kernel source tree with KUnit tests."""
def __init__( def __init__(
...@@ -368,6 +368,6 @@ class LinuxSourceTree(object): ...@@ -368,6 +368,6 @@ class LinuxSourceTree(object):
waiter.join() waiter.join()
subprocess.call(['stty', 'sane']) subprocess.call(['stty', 'sane'])
def signal_handler(self, sig, frame) -> None: def signal_handler(self, unused_sig, unused_frame) -> None:
logging.error('Build interruption occurred. Cleaning console.') logging.error('Build interruption occurred. Cleaning console.')
subprocess.call(['stty', 'sane']) subprocess.call(['stty', 'sane'])
...@@ -15,10 +15,9 @@ import sys ...@@ -15,10 +15,9 @@ import sys
import datetime import datetime
from enum import Enum, auto from enum import Enum, auto
from functools import reduce
from typing import Iterable, Iterator, List, Optional, Tuple from typing import Iterable, Iterator, List, Optional, Tuple
class Test(object): class Test:
""" """
A class to represent a test parsed from KTAP results. All KTAP A class to represent a test parsed from KTAP results. All KTAP
results within a test log are stored in a main Test object as results within a test log are stored in a main Test object as
...@@ -126,17 +125,16 @@ class TestCounts: ...@@ -126,17 +125,16 @@ class TestCounts:
""" """
if self.total() == 0: if self.total() == 0:
return TestStatus.NO_TESTS return TestStatus.NO_TESTS
elif self.crashed: if self.crashed:
# Crashes should take priority. # Crashes should take priority.
return TestStatus.TEST_CRASHED return TestStatus.TEST_CRASHED
elif self.failed: if self.failed:
return TestStatus.FAILURE return TestStatus.FAILURE
elif self.passed: if self.passed:
# No failures or crashes, looks good! # No failures or crashes, looks good!
return TestStatus.SUCCESS return TestStatus.SUCCESS
else: # We have only skipped tests.
# We have only skipped tests. return TestStatus.SKIPPED
return TestStatus.SKIPPED
def add_status(self, status: TestStatus) -> None: def add_status(self, status: TestStatus) -> None:
"""Increments the count for `status`.""" """Increments the count for `status`."""
...@@ -381,7 +379,7 @@ def peek_test_name_match(lines: LineStream, test: Test) -> bool: ...@@ -381,7 +379,7 @@ def peek_test_name_match(lines: LineStream, test: Test) -> bool:
if not match: if not match:
return False return False
name = match.group(4) name = match.group(4)
return (name == test.name) return name == test.name
def parse_test_result(lines: LineStream, test: Test, def parse_test_result(lines: LineStream, test: Test,
expected_num: int) -> bool: expected_num: int) -> bool:
...@@ -553,17 +551,16 @@ def format_test_result(test: Test) -> str: ...@@ -553,17 +551,16 @@ def format_test_result(test: Test) -> str:
String containing formatted test result String containing formatted test result
""" """
if test.status == TestStatus.SUCCESS: if test.status == TestStatus.SUCCESS:
return (green('[PASSED] ') + test.name) return green('[PASSED] ') + test.name
elif test.status == TestStatus.SKIPPED: if test.status == TestStatus.SKIPPED:
return (yellow('[SKIPPED] ') + test.name) return yellow('[SKIPPED] ') + test.name
elif test.status == TestStatus.NO_TESTS: if test.status == TestStatus.NO_TESTS:
return (yellow('[NO TESTS RUN] ') + test.name) return yellow('[NO TESTS RUN] ') + test.name
elif test.status == TestStatus.TEST_CRASHED: if test.status == TestStatus.TEST_CRASHED:
print_log(test.log)
return (red('[CRASHED] ') + test.name)
else:
print_log(test.log) print_log(test.log)
return (red('[FAILED] ') + test.name) return red('[CRASHED] ') + test.name
print_log(test.log)
return red('[FAILED] ') + test.name
def print_test_result(test: Test) -> None: def print_test_result(test: Test) -> None:
""" """
...@@ -607,7 +604,7 @@ def print_summary_line(test: Test) -> None: ...@@ -607,7 +604,7 @@ def print_summary_line(test: Test) -> None:
""" """
if test.status == TestStatus.SUCCESS: if test.status == TestStatus.SUCCESS:
color = green color = green
elif test.status == TestStatus.SKIPPED or test.status == TestStatus.NO_TESTS: elif test.status in (TestStatus.SKIPPED, TestStatus.NO_TESTS):
color = yellow color = yellow
else: else:
color = red color = red
......
...@@ -251,8 +251,8 @@ class KUnitParserTest(unittest.TestCase): ...@@ -251,8 +251,8 @@ class KUnitParserTest(unittest.TestCase):
def test_ignores_hyphen(self): def test_ignores_hyphen(self):
hyphen_log = test_data_path('test_strip_hyphen.log') hyphen_log = test_data_path('test_strip_hyphen.log')
file = open(hyphen_log) with open(hyphen_log) as file:
result = kunit_parser.parse_run_tests(file.readlines()) result = kunit_parser.parse_run_tests(file.readlines())
# A skipped test does not fail the whole suite. # A skipped test does not fail the whole suite.
self.assertEqual( self.assertEqual(
...@@ -347,7 +347,7 @@ class LineStreamTest(unittest.TestCase): ...@@ -347,7 +347,7 @@ class LineStreamTest(unittest.TestCase):
called_times = 0 called_times = 0
def generator(): def generator():
nonlocal called_times nonlocal called_times
for i in range(1,5): for _ in range(1,5):
called_times += 1 called_times += 1
yield called_times, str(called_times) yield called_times, str(called_times)
...@@ -553,7 +553,8 @@ class KUnitMainTest(unittest.TestCase): ...@@ -553,7 +553,8 @@ class KUnitMainTest(unittest.TestCase):
def test_exec_no_tests(self): def test_exec_no_tests(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0']) self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0'])
with self.assertRaises(SystemExit) as e: with self.assertRaises(SystemExit) as e:
kunit.main(['run'], self.linux_source_mock) kunit.main(['run'], self.linux_source_mock)
self.assertEqual(e.exception.code, 1)
self.linux_source_mock.run_kernel.assert_called_once_with( self.linux_source_mock.run_kernel.assert_called_once_with(
args=None, build_dir='.kunit', filter_glob='', timeout=300) args=None, build_dir='.kunit', filter_glob='', timeout=300)
self.print_mock.assert_any_call(StrContains(' 0 tests run!')) self.print_mock.assert_any_call(StrContains(' 0 tests run!'))
...@@ -588,6 +589,7 @@ class KUnitMainTest(unittest.TestCase): ...@@ -588,6 +589,7 @@ class KUnitMainTest(unittest.TestCase):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
with self.assertRaises(SystemExit) as e: with self.assertRaises(SystemExit) as e:
kunit.main(['run', '--raw_output=invalid'], self.linux_source_mock) kunit.main(['run', '--raw_output=invalid'], self.linux_source_mock)
self.assertNotEqual(e.exception.code, 0)
def test_run_raw_output_does_not_take_positional_args(self): def test_run_raw_output_does_not_take_positional_args(self):
# --raw_output is a string flag, but we don't want it to consume # --raw_output is a string flag, but we don't want it to consume
......
...@@ -14,7 +14,7 @@ import shutil ...@@ -14,7 +14,7 @@ import shutil
import subprocess import subprocess
import sys import sys
import textwrap import textwrap
from typing import Dict, List, Sequence, Tuple from typing import Dict, List, Sequence
ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__)) ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__))
TIMEOUT = datetime.timedelta(minutes=5).total_seconds() TIMEOUT = datetime.timedelta(minutes=5).total_seconds()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment