@@ -45,10 +45,11 @@ class TestStatus(Enum):
45
45
FAILURE = auto ()
46
46
TEST_CRASHED = auto ()
47
47
NO_TESTS = auto ()
48
+ FAILURE_TO_PARSE_TESTS = auto ()
48
49
49
50
kunit_start_re = re .compile (r'TAP version [0-9]+$' )
50
51
kunit_end_re = re .compile ('(List of all partitions:|'
51
- 'Kernel panic - not syncing: VFS:|reboot: System halted )' )
52
+ 'Kernel panic - not syncing: VFS:)' )
52
53
53
54
def isolate_kunit_output (kernel_output ):
54
55
started = False
@@ -109,7 +110,7 @@ def save_non_diagnositic(lines: List[str], test_case: TestCase) -> None:
109
110
110
111
OK_NOT_OK_SUBTEST = re .compile (r'^[\s]+(ok|not ok) [0-9]+ - (.*)$' )
111
112
112
- OK_NOT_OK_MODULE = re .compile (r'^(ok|not ok) [0-9]+ - (.*)$' )
113
+ OK_NOT_OK_MODULE = re .compile (r'^(ok|not ok) ( [0-9]+) - (.*)$' )
113
114
114
115
def parse_ok_not_ok_test_case (lines : List [str ], test_case : TestCase ) -> bool :
115
116
save_non_diagnositic (lines , test_case )
@@ -197,7 +198,9 @@ def max_status(left: TestStatus, right: TestStatus) -> TestStatus:
197
198
else :
198
199
return TestStatus .SUCCESS
199
200
200
- def parse_ok_not_ok_test_suite (lines : List [str ], test_suite : TestSuite ) -> bool :
201
+ def parse_ok_not_ok_test_suite (lines : List [str ],
202
+ test_suite : TestSuite ,
203
+ expected_suite_index : int ) -> bool :
201
204
consume_non_diagnositic (lines )
202
205
if not lines :
203
206
test_suite .status = TestStatus .TEST_CRASHED
@@ -210,6 +213,12 @@ def parse_ok_not_ok_test_suite(lines: List[str], test_suite: TestSuite) -> bool:
210
213
test_suite .status = TestStatus .SUCCESS
211
214
else :
212
215
test_suite .status = TestStatus .FAILURE
216
+ suite_index = int (match .group (2 ))
217
+ if suite_index != expected_suite_index :
218
+ print_with_timestamp (
219
+ red ('[ERROR] ' ) + 'expected_suite_index ' +
220
+ str (expected_suite_index ) + ', but got ' +
221
+ str (suite_index ))
213
222
return True
214
223
else :
215
224
return False
@@ -222,7 +231,7 @@ def bubble_up_test_case_errors(test_suite: TestSuite) -> TestStatus:
222
231
max_test_case_status = bubble_up_errors (lambda x : x .status , test_suite .cases )
223
232
return max_status (max_test_case_status , test_suite .status )
224
233
225
- def parse_test_suite (lines : List [str ]) -> TestSuite :
234
+ def parse_test_suite (lines : List [str ], expected_suite_index : int ) -> TestSuite :
226
235
if not lines :
227
236
return None
228
237
consume_non_diagnositic (lines )
@@ -241,7 +250,7 @@ def parse_test_suite(lines: List[str]) -> TestSuite:
241
250
break
242
251
test_suite .cases .append (test_case )
243
252
expected_test_case_num -= 1
244
- if parse_ok_not_ok_test_suite (lines , test_suite ):
253
+ if parse_ok_not_ok_test_suite (lines , test_suite , expected_suite_index ):
245
254
test_suite .status = bubble_up_test_case_errors (test_suite )
246
255
return test_suite
247
256
elif not lines :
@@ -261,27 +270,51 @@ def parse_tap_header(lines: List[str]) -> bool:
261
270
else :
262
271
return False
263
272
273
+ TEST_PLAN = re .compile (r'[0-9]+\.\.([0-9]+)' )
274
+
275
+ def parse_test_plan (lines : List [str ]) -> int :
276
+ consume_non_diagnositic (lines )
277
+ match = TEST_PLAN .match (lines [0 ])
278
+ if match :
279
+ lines .pop (0 )
280
+ return int (match .group (1 ))
281
+ else :
282
+ return None
283
+
264
284
def bubble_up_suite_errors (test_suite_list : List [TestSuite ]) -> TestStatus :
265
285
return bubble_up_errors (lambda x : x .status , test_suite_list )
266
286
267
287
def parse_test_result (lines : List [str ]) -> TestResult :
268
288
consume_non_diagnositic (lines )
269
289
if not lines or not parse_tap_header (lines ):
270
290
return TestResult (TestStatus .NO_TESTS , [], lines )
291
+ expected_test_suite_num = parse_test_plan (lines )
292
+ if not expected_test_suite_num :
293
+ return TestResult (TestStatus .FAILURE_TO_PARSE_TESTS , [], lines )
271
294
test_suites = []
272
- test_suite = parse_test_suite (lines )
273
- while test_suite :
274
- test_suites .append (test_suite )
275
- test_suite = parse_test_suite (lines )
276
- return TestResult (bubble_up_suite_errors (test_suites ), test_suites , lines )
295
+ for i in range (1 , expected_test_suite_num + 1 ):
296
+ test_suite = parse_test_suite (lines , i )
297
+ if test_suite :
298
+ test_suites .append (test_suite )
299
+ else :
300
+ print_with_timestamp (
301
+ red ('[ERROR] ' ) + ' expected ' +
302
+ str (expected_test_suite_num ) +
303
+ ' test suites, but got ' + str (i - 2 ))
304
+ break
305
+ test_suite = parse_test_suite (lines , - 1 )
306
+ if test_suite :
307
+ print_with_timestamp (red ('[ERROR] ' ) +
308
+ 'got unexpected test suite: ' + test_suite .name )
309
+ if test_suites :
310
+ return TestResult (bubble_up_suite_errors (test_suites ), test_suites , lines )
311
+ else :
312
+ return TestResult (TestStatus .NO_TESTS , [], lines )
277
313
278
- def parse_run_tests ( kernel_output ) -> TestResult :
314
+ def print_and_count_results ( test_result : TestResult ) -> None :
279
315
total_tests = 0
280
316
failed_tests = 0
281
317
crashed_tests = 0
282
- test_result = parse_test_result (list (isolate_kunit_output (kernel_output )))
283
- if test_result .status == TestStatus .NO_TESTS :
284
- print_with_timestamp (red ('[ERROR] ' ) + 'no kunit output detected' )
285
318
for test_suite in test_result .suites :
286
319
if test_suite .status == TestStatus .SUCCESS :
287
320
print_suite_divider (green ('[PASSED] ' ) + test_suite .name )
@@ -303,6 +336,21 @@ def parse_run_tests(kernel_output) -> TestResult:
303
336
print_with_timestamp (red ('[FAILED] ' ) + test_case .name )
304
337
print_log (map (yellow , test_case .log ))
305
338
print_with_timestamp ('' )
339
+ return total_tests , failed_tests , crashed_tests
340
+
341
+ def parse_run_tests (kernel_output ) -> TestResult :
342
+ total_tests = 0
343
+ failed_tests = 0
344
+ crashed_tests = 0
345
+ test_result = parse_test_result (list (isolate_kunit_output (kernel_output )))
346
+ if test_result .status == TestStatus .NO_TESTS :
347
+ print (red ('[ERROR] ' ) + yellow ('no tests run!' ))
348
+ elif test_result .status == TestStatus .FAILURE_TO_PARSE_TESTS :
349
+ print (red ('[ERROR] ' ) + yellow ('could not parse test results!' ))
350
+ else :
351
+ (total_tests ,
352
+ failed_tests ,
353
+ crashed_tests ) = print_and_count_results (test_result )
306
354
print_with_timestamp (DIVIDER )
307
355
fmt = green if test_result .status == TestStatus .SUCCESS else red
308
356
print_with_timestamp (
0 commit comments