Lines Matching +full:line +full:- +full:name

1 # SPDX-License-Identifier: GPL-2.0
4 # results with reader-friendly format. Stores and returns test results in a
29 status : TestStatus - status of the test
30 name : str - name of the test
31 expected_count : int - expected number of subtests (0 if single
33 subtests : List[Test] - list of subtests
34 log : List[str] - log of KTAP lines that correspond to the test
35 counts : TestCounts - counts of the test statuses and errors of
39 def __init__(self) -> None:
42 self.name = ''
48 def __str__(self) -> str:
50 return (f'Test({self.status}, {self.name}, {self.expected_count}, '
53 def __repr__(self) -> str:
57 def add_error(self, error_message: str) -> None:
60 stdout.print_with_timestamp(stdout.red('[ERROR]') + f' Test: {self.name}: {error_message}')
62 def ok_status(self) -> bool:
87 def __str__(self) -> str:
95 def total(self) -> int:
102 def add_subtest_counts(self, counts: TestCounts) -> None:
109 counts - a different TestCounts object whose counts
118 def get_status(self) -> TestStatus:
135 def add_status(self, status: TestStatus) -> None:
150 (line#, text).
164 def _get_next(self) -> None:
165 """Advances the LineSteam to the next line, if necessary."""
175 def peek(self) -> str:
176 """Returns the current line, without advancing the LineStream.
181 def pop(self) -> str:
182 """Returns the current line and advances the LineStream to
183 the next line.
187 raise ValueError(f'LineStream: going past EOF, last line was {s}')
191 def __bool__(self) -> bool:
197 def __iter__(self) -> Iterator[str]:
204 def line_number(self) -> int:
205 """Returns the line number of the current line."""
211 KTAP_START = re.compile(r'\s*KTAP version ([0-9]+)$')
212 TAP_START = re.compile(r'\s*TAP version ([0-9]+)$')
214 'Kernel panic - not syncing: VFS:|reboot: System halted)')
217 def extract_tap_lines(kernel_output: Iterable[str]) -> LineStream:
220 -> Iterator[Tuple[int, str]]:
223 for line in kernel_output:
225 line = line.rstrip() # remove trailing \n
226 if not started and KTAP_START.search(line):
228 # to number of characters before version line
230 line.split('KTAP version')[0])
232 yield line_num, line[prefix_len:]
233 elif not started and TAP_START.search(line):
235 # to number of characters before version line
236 prefix_len = len(line.split('TAP version')[0])
238 yield line_num, line[prefix_len:]
239 elif started and KTAP_END.search(line):
244 line = line[prefix_len:]
245 yield line_num, line
246 elif EXECUTOR_ERROR.search(line):
247 yield line_num, line
254 version_type: str, test: Test) -> None:
260 version_num - The inputted version number from the parsed KTAP or TAP
261 header line
262 accepted_version - List of accepted KTAP or TAP versions
263 version_type - 'KTAP' or 'TAP' depending on the type of
264 version line.
265 test - Test object for current test being parsed
272 def parse_ktap_header(lines: LineStream, test: Test) -> bool:
274 Parses KTAP/TAP header line and checks version number.
275 Returns False if fails to parse KTAP/TAP header line.
278 - 'KTAP version [version number]'
279 - 'TAP version [version number]'
282 lines - LineStream of KTAP output to parse
283 test - Test object for current test being parsed
286 True if successfully parsed KTAP/TAP header line
303 def parse_test_header(lines: LineStream, test: Test) -> bool:
305 Parses test header and stores test name in test object.
306 Returns False if fails to parse test header line.
309 - '# Subtest: [test name]'
312 lines - LineStream of KTAP output to parse
313 test - Test object for current test being parsed
316 True if successfully parsed test header line
321 test.name = match.group(1)
325 TEST_PLAN = re.compile(r'^\s*1\.\.([0-9]+)')
327 def parse_test_plan(lines: LineStream, test: Test) -> bool:
329 Parses test plan line and stores the expected number of subtests in
335 - '1..[number of subtests]'
338 lines - LineStream of KTAP output to parse
339 test - Test object for current test being parsed
342 True if successfully parsed test plan line
353 TEST_RESULT = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?([^#]*)( # .*)?$')
355 TEST_RESULT_SKIP = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?(.*) # SKIP(.*)$')
357 def peek_test_name_match(lines: LineStream, test: Test) -> bool:
359 Matches current line with the format of a test result line and checks
360 if the name matches the name of the current test.
361 Returns False if fails to match format or name.
364 - '[ok|not ok] [test number] [-] [test name] [optional skip
368 lines - LineStream of KTAP output to parse
369 test - Test object for current test being parsed
372 True if matched a test result line and the name matching the
373 expected test name
375 line = lines.peek()
376 match = TEST_RESULT.match(line)
379 name = match.group(4)
380 return name == test.name
383 expected_num: int) -> bool:
385 Parses test result line and stores the status and name in the test
388 Returns False if fails to parse test result line.
394 - '[ok|not ok] [test number] [-] [test name] [optional skip
398 lines - LineStream of KTAP output to parse
399 test - Test object for current test being parsed
400 expected_num - expected test number for current test
403 True if successfully parsed a test result line.
405 line = lines.peek()
406 match = TEST_RESULT.match(line)
407 skip_match = TEST_RESULT_SKIP.match(line)
409 # Check if line matches test result line format
414 # Set name of test object
416 test.name = skip_match.group(4)
418 test.name = match.group(4)
435 def parse_diagnostic(lines: LineStream) -> List[str]:
437 Parse lines that do not match the format of a test result line or
438 test header line and returns them in list.
440 Line formats that are not parsed:
441 - '# Subtest: [test name]'
442 - '[ok|not ok] [test number] [-] [test name] [optional skip
444 - 'KTAP version [version number]'
447 lines - LineStream of KTAP output to parse
464 def format_test_divider(message: str, len_message: int) -> str:
472 message - message to be centered in divider line
473 len_message - length of the message to be printed such that
482 difference = len(DIVIDER) - len_message - 2 # 2 spaces added
486 len_2 = difference - len_1
489 def print_test_header(test: Test) -> None:
491 Prints test header with test name and optionally the expected number
498 test - Test object representing current test being printed
500 message = test.name
502 # Add a leading space before the subtest counts only if a test name
503 # is provided using a "# Subtest" header line.
512 def print_log(log: Iterable[str]) -> None:
515 for line in formatted.splitlines():
516 stdout.print_with_timestamp(stdout.yellow(line))
518 def format_test_result(test: Test) -> str:
521 name.
527 test - Test object representing current test being printed
533 return stdout.green('[PASSED] ') + test.name
535 return stdout.yellow('[SKIPPED] ') + test.name
537 return stdout.yellow('[NO TESTS RUN] ') + test.name
540 return stdout.red('[CRASHED] ') + test.name
542 return stdout.red('[FAILED] ') + test.name
544 def print_test_result(test: Test) -> None:
546 Prints result line with status of test.
552 test - Test object representing current test being printed
556 def print_test_footer(test: Test) -> None:
564 test - Test object representing current test being printed
568 len(message) - stdout.color_len()))
572 def _summarize_failed_tests(test: Test) -> str:
575 def failed_names(test: Test, parent_name: str) -> List[str]:
576 # Note: we use 'main' internally for the top-level test.
578 full_name = test.name
580 full_name = parent_name + '.' + test.name
586 # Don't summarize it down "the top-level test failed", though.
604 def print_summary_line(test: Test) -> None:
606 Prints summary line of test object. Color of line is dependent on
608 skipped, and red if the test fails or crashes. Summary line contains
616 test - Test object representing current test being printed
626 # Summarize failures that might have gone off-screen since we had a lot
637 def bubble_up_test_results(test: Test) -> None:
645 test - Test object for current test being parsed
657 def parse_test(lines: LineStream, expected_num: int, log: List[str], is_subtest: bool) -> Test:
661 information (status, name) about the test and the Test objects for
667 - Main KTAP/TAP header
675 - Subtest header (must include either the KTAP version line or
676 "# Subtest" header line)
678 Example (preferred format with both KTAP version line and
679 "# Subtest" line):
682 # Subtest: name
685 ok 1 name
687 Example (only "# Subtest" line):
689 # Subtest: name
692 ok 1 name
694 Example (only KTAP version line, compliant with KTAP v1 spec):
699 ok 1 name
701 - Test result line
705 ok 1 - test
708 lines - LineStream of KTAP output to parse
709 expected_num - expected test number for test to be parsed
710 log - list of strings containing any preceding diagnostic lines
712 is_subtest - boolean indicating whether test is a subtest
725 # If parsing the main/top-level test, parse KTAP version line and
727 test.name = "main"
734 # the KTAP version line and/or subtest header line
739 # If KTAP version line and/or subtest header is found, attempt
751 # result line with matching name to subtest header is found
775 # If not main test, look for test result line
777 if test.name != "" and not peek_test_name_match(lines, test):
778 test.add_error('missing subtest result line!')
801 def parse_run_tests(kernel_output: Iterable[str]) -> Test:
804 results and print condensed test results and summary line.
807 kernel_output - Iterable object contains lines of kernel output
810 Test - the main test object with all subtests.
816 test.name = '<missing>'