"""
.. module:: results
:platform: Linux
:synopsis: module containing suites data definition
.. moduleauthor:: Andrea Cervesato <andrea.cervesato@suse.com>
"""
from typing import (
List,
Optional,
)
from libkirk.data import (
Suite,
Test,
)
[docs]
class ResultStatus:
"""
Overall status of the test. This is a specific flag that is used to
recognize final test status. For example, we might have 10 tests passing
inside a single test binary, but the overall status of the test is fine, so
we assign a PASS status.
"""
PASS = 0
"""
Test has passed.
"""
BROK = 2
"""
Test is broken.
"""
WARN = 4
"""
Test warnings received.
"""
FAIL = 16
"""
Test has failed.
"""
CONF = 32
"""
Test can't run because of configuration error.
"""
[docs]
class Results:
"""
Base class for results.
"""
@property
def exec_time(self) -> float:
"""
:return: Test execution time in seconds.
:rtype: float
"""
raise NotImplementedError()
@property
def failed(self) -> int:
"""
:return: Number of failures.
:rtype: int
"""
raise NotImplementedError()
@property
def passed(self) -> int:
"""
:return: Number of passed tests.
:rtype: int
"""
raise NotImplementedError()
@property
def broken(self) -> int:
"""
:return: Number of broken tests.
:rtype: int
"""
raise NotImplementedError()
@property
def skipped(self) -> int:
"""
:return: Number of skipped tests.
:rtype: int
"""
raise NotImplementedError()
@property
def warnings(self) -> int:
"""
:return: Number of warnings.
:rtype: int
"""
raise NotImplementedError()
[docs]
class TestResults(Results):
"""
Test results definition.
"""
def __init__(
self,
test: Test,
failed: int = 0,
passed: int = 0,
broken: int = 0,
skipped: int = 0,
warnings: int = 0,
exec_time: float = 0.0,
status: int = ResultStatus.PASS,
retcode: int = 0,
stdout: str = "",
) -> None:
"""
:param test: Test object declaration.
:type test: Test
:param failed: number of TFAIL.
:type failed: int
:param passed: number of TPASS.
:type passed: int
:param broken: number of TBROK.
:type broken: int
:param skipped: number of TSKIP.
:type skipped: int
:param warnings: number of TWARN.
:type warnings: int
:param exec_time: Time for test's execution.
:type exec_time: float
:param status: Overall status of the test.
:type status: int
:param retcode: Return code of the executed test.
:type retcode: int
:param stdout: Stdout of the test.
:type stdout: str
"""
if not test:
raise ValueError("Empty test object")
self._test = test
self._failed = failed
self._passed = passed
self._broken = broken
self._skipped = skipped
self._warns = warnings
self._exec_time = exec_time
self._status = status
self._retcode = retcode
self._stdout = stdout
def __repr__(self) -> str:
return (
f"test: '{self._test}', "
f"failed: '{self._failed}', "
f"passed: {self._passed}, "
f"broken: {self._broken}, "
f"skipped: {self._skipped}, "
f"warnings: {self._warns}, "
f"exec_time: {self._exec_time}, "
f"status: {self._status}, "
f"retcode: {self._retcode}, "
f"stdout: {repr(self._stdout)}"
)
@property
def test(self) -> Test:
"""
:return: Test object.
:rtype: Test
"""
return self._test
@property
def return_code(self) -> int:
"""
:return: Return code after execution.
:rtype: int
"""
return self._retcode
@property
def stdout(self) -> str:
"""
:return: Test process stdout.
:rtype: str
"""
return self._stdout
@property
def status(self) -> int:
"""
:return: Test result status.
:rtype: int
"""
return self._status
@property
def exec_time(self) -> float:
return self._exec_time
@property
def failed(self) -> int:
return self._failed
@property
def passed(self) -> int:
return self._passed
@property
def broken(self) -> int:
return self._broken
@property
def skipped(self) -> int:
return self._skipped
@property
def warnings(self) -> int:
return self._warns
[docs]
class SuiteResults(Results):
"""
Testing suite results definition.
"""
def __init__(
self,
suite: Suite,
tests: Optional[List[TestResults]] = None,
distro: Optional[str] = None,
distro_ver: Optional[str] = None,
kernel: Optional[str] = None,
cmdline: Optional[str] = None,
arch: Optional[str] = None,
cpu: Optional[str] = None,
swap: Optional[str] = None,
ram: Optional[str] = None,
) -> None:
"""
:param suite: Test object declaration.
:type suite: Suite
:param tests: List of the tests results.
:type tests: list(TestResults)
:param distro: Distribution name.
:type distro: str
:param distro_ver: Distribution version.
:type distro_ver: str
:param kernel: Kernel version.
:type kernel: str
:param cmdline: /proc/cmdline.
:type cmdline: str
:param arch: OS architecture.
:type arch: str
:param cpu: CPU type info.
:type cpu: str
:param swap: Swap memory info.
:type swap: str
:param ram: RAM info.
:type ram: str
"""
if not suite:
raise ValueError("Empty suite object")
self._suite = suite
self._tests = tests if tests is not None else []
self._distro = distro
self._distro_ver = distro_ver
self._kernel = kernel
self._cmdline = cmdline
self._arch = arch
self._cpu = cpu
self._swap = swap
self._ram = ram
def __repr__(self) -> str:
return (
f"suite: '{self._suite}', "
f"tests: '{self._tests}', "
f"distro: {self._distro}, "
f"distro_ver: {self._distro_ver}, "
f"kernel: {self._kernel}, "
f"cmdline: {self._cmdline}, "
f"arch: {self._arch}, "
f"cpu: {self._cpu}, "
f"swap: {self._swap}, "
f"ram: {self._ram}"
)
@property
def suite(self) -> Suite:
"""
:returns: Testing suite.
:rtype: Suite
"""
return self._suite
@property
def tests_results(self) -> List[TestResults]:
"""
:returns: list of all tests results.
:rtype: list(TestResults)
"""
return self._tests
def _get_result(self, attr: str) -> int:
"""
Return the total number of results.
"""
res = 0
for test in self._tests:
res += getattr(test, attr)
return res
@property
def distro(self) -> Optional[str]:
"""
:return: Linux distribution name.
:rtype: str | None
"""
return self._distro
@property
def distro_ver(self) -> Optional[str]:
"""
:return: Linux distribution version.
:rtype: str | None
"""
return self._distro_ver
@property
def kernel(self) -> Optional[str]:
"""
:return: Kernel version.
:rtype: str | None
"""
return self._kernel
@property
def cmdline(self) -> Optional[str]:
"""
:return: /proc/cmdline.
:rtype: str | None
"""
return self._cmdline
@property
def arch(self) -> Optional[str]:
"""
:return: Operating system architecture.
:rtype: str | None
"""
return self._arch
@property
def cpu(self) -> Optional[str]:
"""
:return: Current CPU type.
:rtype: str | None
"""
return self._cpu
@property
def swap(self) -> Optional[str]:
"""
:return: Current swap memory occupation.
:rtype: str | None
"""
return self._swap
@property
def ram(self) -> Optional[str]:
"""
:return: Current RAM occupation.
:rtype: str | None
"""
return self._ram
@property
def exec_time(self) -> float:
return self._get_result("exec_time")
@property
def failed(self) -> int:
return self._get_result("failed")
@property
def passed(self) -> int:
return self._get_result("passed")
@property
def broken(self) -> int:
return self._get_result("broken")
@property
def skipped(self) -> int:
return self._get_result("skipped")
@property
def warnings(self) -> int:
return self._get_result("warnings")