Lines Matching full:test

3 # Parses KTAP test results from a kernel dmesg log and incrementally prints
4 # results with reader-friendly format. Stores and returns test results in a
5 # Test object.
21 class Test: class
23 A class to represent a test parsed from KTAP results. All KTAP
24 results within a test log are stored in a main Test object as
28 status : TestStatus - status of the test
29 name : str - name of the test
31 test case and None if unknown expected number of subtests)
32 subtests : List[Test] - list of subtests
33 log : List[str] - log of KTAP lines that correspond to the test
34 counts : TestCounts - counts of the test statuses and errors of
35 subtests or of the test itself if the test is a single
36 test case.
39 """Creates Test object with default attributes."""
43 self.subtests = [] # type: List[Test]
48 """Returns string representation of a Test class object."""
49 return (f'Test({self.status}, {self.name}, {self.expected_count}, '
53 """Returns string representation of a Test class object."""
57 """Records an error that occurred while parsing this test."""
59 stdout.print_with_timestamp(stdout.red('[ERROR]') + f' Test: {self.name}: {error_message}')
62 """An enumeration class to represent the status of a test."""
72 Tracks the counts of statuses of all test cases and any errors within
73 a Test.
80 errors : int - the number of errors in the test and subtests
83 """Creates TestCounts object with counts of all test
84 statuses and test errors set to 0.
101 """Returns the total number of test cases within a test
102 object, where a test case is a test with no subtests.
111 parent test.
124 """Returns the aggregated status of a Test using test
259 version_type: str, test: Test) -> None: argument
261 Adds error to test object if version number is too high or too
270 test - Test object for current test being parsed
273 test.add_error(f'{version_type} version lower than expected!')
275 test.add_error(f'{version_type} version higer than expected!')
277 def parse_ktap_header(lines: LineStream, test: Test) -> bool: argument
288 test - Test object for current test being parsed
297 check_version(version_num, KTAP_VERSIONS, 'KTAP', test)
300 check_version(version_num, TAP_VERSIONS, 'TAP', test)
303 test.log.append(lines.pop())
308 def parse_test_header(lines: LineStream, test: Test) -> bool: argument
310 Parses test header and stores test name in test object.
311 Returns False if fails to parse test header line.
314 - '# Subtest: [test name]'
318 test - Test object for current test being parsed
321 True if successfully parsed test header line
326 test.log.append(lines.pop())
327 test.name = match.group(1)
332 def parse_test_plan(lines: LineStream, test: Test) -> bool: argument
334 Parses test plan line and stores the expected number of subtests in
335 test object. Reports an error if expected count is 0.
336 Returns False and sets expected_count to None if there is no valid test
344 test - Test object for current test being parsed
347 True if successfully parsed test plan line
351 test.expected_count = None
353 test.log.append(lines.pop())
355 test.expected_count = expected_count
362 def peek_test_name_match(lines: LineStream, test: Test) -> bool: argument
364 Matches current line with the format of a test result line and checks
365 if the name matches the name of the current test.
369 - '[ok|not ok] [test number] [-] [test name] [optional skip
374 test - Test object for current test being parsed
377 True if matched a test result line and the name matching the
378 expected test name
385 return name == test.name
387 def parse_test_result(lines: LineStream, test: Test, argument
390 Parses test result line and stores the status and name in the test
391 object. Reports an error if the test number does not match expected
392 test number.
393 Returns False if fails to parse test result line.
399 - '[ok|not ok] [test number] [-] [test name] [optional skip
404 test - Test object for current test being parsed
405 expected_num - expected test number for current test
408 True if successfully parsed a test result line.
414 # Check if line matches test result line format
417 test.log.append(lines.pop())
419 # Set name of test object
421 test.name = skip_match.group(4)
423 test.name = match.group(4)
425 # Check test num
428 test.add_error(f'Expected test number {expected_num} but found {num}')
430 # Set status of test object
433 test.status = TestStatus.SKIPPED
435 test.status = TestStatus.SUCCESS
437 test.status = TestStatus.FAILURE
442 Parse lines that do not match the format of a test result line or
443 test header line and returns them in list.
446 - '# Subtest: [test name]'
447 - '[ok|not ok] [test number] [-] [test name] [optional skip
492 def print_test_header(test: Test) -> None: argument
494 Prints test header with test name and optionally the expected number
501 test - Test object representing current test being printed
503 message = test.name
504 if test.expected_count:
505 if test.expected_count == 1:
508 message += f' ({test.expected_count} subtests)'
512 """Prints all strings in saved log for test in yellow."""
516 def format_test_result(test: Test) -> str: argument
518 Returns string with formatted test result with colored status and test
525 test - Test object representing current test being printed
528 String containing formatted test result
530 if test.status == TestStatus.SUCCESS:
531 return stdout.green('[PASSED] ') + test.name
532 if test.status == TestStatus.SKIPPED:
533 return stdout.yellow('[SKIPPED] ') + test.name
534 if test.status == TestStatus.NO_TESTS:
535 return stdout.yellow('[NO TESTS RUN] ') + test.name
536 if test.status == TestStatus.TEST_CRASHED:
537 print_log(test.log)
538 return stdout.red('[CRASHED] ') + test.name
539 print_log(test.log)
540 return stdout.red('[FAILED] ') + test.name
542 def print_test_result(test: Test) -> None: argument
544 Prints result line with status of test.
550 test - Test object representing current test being printed
552 stdout.print_with_timestamp(format_test_result(test))
554 def print_test_footer(test: Test) -> None: argument
556 Prints test footer with status of test.
562 test - Test object representing current test being printed
564 message = format_test_result(test)
568 def print_summary_line(test: Test) -> None: argument
570 Prints summary line of test object. Color of line is dependent on
571 status of test. Color is green if test passes, yellow if test is
572 skipped, and red if the test fails or crashes. Summary line contains
573 counts of the statuses of the tests subtests or the test itself if it
580 test - Test object representing current test being printed
582 if test.status == TestStatus.SUCCESS:
584 elif test.status in (TestStatus.SKIPPED, TestStatus.NO_TESTS):
588 stdout.print_with_timestamp(color(f'Testing complete. {test.counts}'))
592 def bubble_up_test_results(test: Test) -> None: argument
594 If the test has subtests, add the test counts of the subtests to the
595 test and check if any of the tests crashed and if so set the test
596 status to crashed. Otherwise if the test has no subtests add the
597 status of the test to the test counts.
600 test - Test object for current test being parsed
602 subtests = test.subtests
603 counts = test.counts
604 status = test.status
609 elif test.counts.get_status() == TestStatus.TEST_CRASHED:
610 test.status = TestStatus.TEST_CRASHED
612 def parse_test(lines: LineStream, expected_num: int, log: List[str]) -> Test:
614 Finds next test to parse in LineStream, creates new Test object,
615 parses any subtests of the test, populates Test object with all
616 information (status, name) about the test and the Test objects for
617 any subtests, and then returns the Test object. The method accepts
620 Accepted test formats:
639 - Test result line
643 ok 1 - test
647 expected_num - expected test number for test to be parsed
649 corresponding to the current test
652 Test object populated with characteristics and any subtests
654 test = Test()
655 test.log.extend(log)
657 main = parse_ktap_header(lines, test)
660 # test plan
661 test.name = "main"
662 parse_test_plan(lines, test)
665 # If KTAP/TAP header is not found, test must be subtest
666 # header or test result line so parse attempt to parser
668 parent_test = parse_test_header(lines, test)
671 # test plan and print header
672 parse_test_plan(lines, test)
673 print_test_header(test)
674 expected_count = test.expected_count
680 # if expected number of tests is unknown break when test
684 sub_test = Test()
685 if not lines or (peek_test_name_match(lines, test) and
688 # If parser reaches end of test before
691 test.add_error('missing expected subtest!')
693 test.counts.add_status(
697 test.log.extend(sub_log)
703 test.subtests = subtests
705 # If not main test, look for test result line
706 test.log.extend(parse_diagnostic(lines))
707 if (parent_test and peek_test_name_match(lines, test)) or \
709 parse_test_result(lines, test, expected_num)
711 test.add_error('missing subtest result line!')
715 # Don't override a bad status if this test had one reported.
716 # Assumption: no subtests means CRASHED is from Test.__init__()
717 if test.status in (TestStatus.TEST_CRASHED, TestStatus.SUCCESS):
718 test.status = TestStatus.NO_TESTS
719 test.add_error('0 tests run!')
721 # Add statuses to TestCounts attribute in Test object
722 bubble_up_test_results(test)
724 # If test has subtests and is not the main test object, print
726 print_test_footer(test)
728 print_test_result(test)
729 return test
731 def parse_run_tests(kernel_output: Iterable[str]) -> Test:
733 Using kernel output, extract KTAP lines, parse the lines for test
734 results and print condensed test results and summary line.
740 Test - the main test object with all subtests.
744 test = Test()
746 test.name = '<missing>'
747 test.add_error('could not find any KTAP output!')
748 test.status = TestStatus.FAILURE_TO_PARSE_TESTS
750 test = parse_test(lines, 0, [])
751 if test.status != TestStatus.NO_TESTS:
752 test.status = test.counts.get_status()
754 print_summary_line(test)
755 return test