Renato Botelho do Couto | ead1e53 | 2019-10-31 13:31:07 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Damjan Marion | f56b77a | 2016-10-03 19:44:57 +0200 | [diff] [blame] | 2 | |
Klement Sekera | 993e0ed | 2017-03-16 09:14:59 +0100 | [diff] [blame] | 3 | import sys |
Dave Wallace | e2efd12 | 2017-09-30 22:04:21 -0400 | [diff] [blame] | 4 | import shutil |
Damjan Marion | f56b77a | 2016-10-03 19:44:57 +0200 | [diff] [blame] | 5 | import os |
Andrew Yourtchenko | d760f79 | 2018-10-03 11:38:31 +0200 | [diff] [blame] | 6 | import fnmatch |
Damjan Marion | f56b77a | 2016-10-03 19:44:57 +0200 | [diff] [blame] | 7 | import unittest |
Klement Sekera | 545be52 | 2018-02-16 19:25:06 +0100 | [diff] [blame] | 8 | import time |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 9 | import threading |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 10 | import traceback |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 11 | import signal |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 12 | import re |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 13 | from multiprocessing import Process, Pipe, get_context |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 14 | from multiprocessing.queues import Queue |
| 15 | from multiprocessing.managers import BaseManager |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 16 | from config import config, num_cpus, available_cpus, max_vpp_cpus |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 17 | from framework import ( |
| 18 | VppTestRunner, |
| 19 | VppTestCase, |
| 20 | get_testcase_doc_name, |
| 21 | get_test_description, |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 22 | ) |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 23 | from test_result_code import TestResultCode |
Klement Sekera | 152a9b6 | 2022-05-13 18:01:36 +0200 | [diff] [blame] | 24 | from debug import spawn_gdb |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 25 | from log import ( |
| 26 | get_parallel_logger, |
| 27 | double_line_delim, |
| 28 | RED, |
| 29 | YELLOW, |
| 30 | GREEN, |
| 31 | colorize, |
| 32 | single_line_delim, |
| 33 | ) |
Klement Sekera | fcbf444 | 2017-08-17 07:38:42 +0200 | [diff] [blame] | 34 | from discover_tests import discover_tests |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 35 | import sanity_run_vpp |
Klement Sekera | 9b6ece7 | 2018-03-23 10:50:11 +0100 | [diff] [blame] | 36 | from subprocess import check_output, CalledProcessError |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 37 | from util import check_core_path, get_core_path, is_core_present |
Klement Sekera | 993e0ed | 2017-03-16 09:14:59 +0100 | [diff] [blame] | 38 | |
Klement Sekera | 0574226 | 2018-03-14 18:14:49 +0100 | [diff] [blame] | 39 | # timeout which controls how long the child has to finish after seeing |
| 40 | # a core dump in test temporary directory. If this is exceeded, parent assumes |
Klement Sekera | eb506be | 2021-03-16 12:52:29 +0100 | [diff] [blame] | 41 | # that child process is stuck (e.g. waiting for event from vpp) and kill |
| 42 | # the child |
Klement Sekera | 0574226 | 2018-03-14 18:14:49 +0100 | [diff] [blame] | 43 | core_timeout = 3 |
| 44 | |
Klement Sekera | 909a6a1 | 2017-08-08 04:33:53 +0200 | [diff] [blame] | 45 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 46 | class StreamQueue(Queue): |
| 47 | def write(self, msg): |
| 48 | self.put(msg) |
| 49 | |
| 50 | def flush(self): |
| 51 | sys.__stdout__.flush() |
| 52 | sys.__stderr__.flush() |
| 53 | |
| 54 | def fileno(self): |
| 55 | return self._writer.fileno() |
| 56 | |
| 57 | |
| 58 | class StreamQueueManager(BaseManager): |
| 59 | pass |
| 60 | |
| 61 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 62 | StreamQueueManager.register("StreamQueue", StreamQueue) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 63 | |
| 64 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 65 | class TestResult(dict): |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 66 | def __init__(self, testcase_suite, testcases_by_id=None): |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 67 | super(TestResult, self).__init__() |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 68 | for trc in list(TestResultCode): |
| 69 | self[trc] = [] |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 70 | self.crashed = False |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 71 | self.testcase_suite = testcase_suite |
| 72 | self.testcases = [testcase for testcase in testcase_suite] |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 73 | self.testcases_by_id = testcases_by_id |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 74 | |
| 75 | def was_successful(self): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 76 | return ( |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 77 | 0 |
| 78 | == len(self[TestResultCode.FAIL]) |
| 79 | == len(self[TestResultCode.ERROR]) |
| 80 | == len(self[TestResultCode.UNEXPECTED_PASS]) |
| 81 | and len(self[TestResultCode.PASS]) |
| 82 | + len(self[TestResultCode.SKIP]) |
| 83 | + len(self[TestResultCode.SKIP_CPU_SHORTAGE]) |
| 84 | + len(self[TestResultCode.EXPECTED_FAIL]) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 85 | == self.testcase_suite.countTestCases() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 86 | ) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 87 | |
| 88 | def no_tests_run(self): |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 89 | return 0 == len(self[TestResultCode.TEST_RUN]) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 90 | |
| 91 | def process_result(self, test_id, result): |
| 92 | self[result].append(test_id) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 93 | |
| 94 | def suite_from_failed(self): |
| 95 | rerun_ids = set([]) |
| 96 | for testcase in self.testcase_suite: |
| 97 | tc_id = testcase.id() |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 98 | if ( |
| 99 | tc_id |
| 100 | not in self[TestResultCode.PASS] |
| 101 | + self[TestResultCode.SKIP] |
| 102 | + self[TestResultCode.SKIP_CPU_SHORTAGE] |
| 103 | + self[TestResultCode.EXPECTED_FAIL] |
| 104 | ): |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 105 | rerun_ids.add(tc_id) |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 106 | if rerun_ids: |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 107 | return suite_from_failed(self.testcase_suite, rerun_ids) |
| 108 | |
| 109 | def get_testcase_names(self, test_id): |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 110 | # could be tearDownClass (test_ipsec_esp.TestIpsecEsp1) |
| 111 | setup_teardown_match = re.match( |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 112 | r"((tearDownClass)|(setUpClass)) \((.+\..+)\)", test_id |
| 113 | ) |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 114 | if setup_teardown_match: |
| 115 | test_name, _, _, testcase_name = setup_teardown_match.groups() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 116 | if len(testcase_name.split(".")) == 2: |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 117 | for key in self.testcases_by_id.keys(): |
| 118 | if key.startswith(testcase_name): |
| 119 | testcase_name = key |
| 120 | break |
| 121 | testcase_name = self._get_testcase_doc_name(testcase_name) |
| 122 | else: |
Ole Trøan | 5ba9159 | 2018-11-22 10:01:09 +0000 | [diff] [blame] | 123 | test_name = self._get_test_description(test_id) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 124 | testcase_name = self._get_testcase_doc_name(test_id) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 125 | |
| 126 | return testcase_name, test_name |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 127 | |
Ole Trøan | 5ba9159 | 2018-11-22 10:01:09 +0000 | [diff] [blame] | 128 | def _get_test_description(self, test_id): |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 129 | if test_id in self.testcases_by_id: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 130 | desc = get_test_description(descriptions, self.testcases_by_id[test_id]) |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 131 | else: |
| 132 | desc = test_id |
| 133 | return desc |
Ole Trøan | 5ba9159 | 2018-11-22 10:01:09 +0000 | [diff] [blame] | 134 | |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 135 | def _get_testcase_doc_name(self, test_id): |
juraj.linkes | 2eca70d | 2018-12-13 11:10:47 +0100 | [diff] [blame] | 136 | if test_id in self.testcases_by_id: |
| 137 | doc_name = get_testcase_doc_name(self.testcases_by_id[test_id]) |
| 138 | else: |
| 139 | doc_name = test_id |
| 140 | return doc_name |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 141 | |
| 142 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 143 | def test_runner_wrapper( |
| 144 | suite, keep_alive_pipe, stdouterr_queue, finished_pipe, result_pipe, logger |
| 145 | ): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 146 | sys.stdout = stdouterr_queue |
| 147 | sys.stderr = stdouterr_queue |
juraj.linkes | dfb5f2a | 2018-11-09 11:58:54 +0100 | [diff] [blame] | 148 | VppTestCase.parallel_handler = logger.handlers[0] |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 149 | result = VppTestRunner( |
| 150 | keep_alive_pipe=keep_alive_pipe, |
| 151 | descriptions=descriptions, |
| 152 | verbosity=config.verbose, |
| 153 | result_pipe=result_pipe, |
| 154 | failfast=config.failfast, |
| 155 | print_summary=False, |
| 156 | ).run(suite) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 157 | finished_pipe.send(result.wasSuccessful()) |
| 158 | finished_pipe.close() |
Klement Sekera | 909a6a1 | 2017-08-08 04:33:53 +0200 | [diff] [blame] | 159 | keep_alive_pipe.close() |
| 160 | |
| 161 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 162 | class TestCaseWrapper(object): |
| 163 | def __init__(self, testcase_suite, manager): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 164 | self.keep_alive_parent_end, self.keep_alive_child_end = Pipe(duplex=False) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 165 | self.finished_parent_end, self.finished_child_end = Pipe(duplex=False) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 166 | self.result_parent_end, self.result_child_end = Pipe(duplex=False) |
| 167 | self.testcase_suite = testcase_suite |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 168 | self.stdouterr_queue = manager.StreamQueue(ctx=get_context()) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 169 | self.logger = get_parallel_logger(self.stdouterr_queue) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 170 | self.child = Process( |
| 171 | target=test_runner_wrapper, |
| 172 | args=( |
| 173 | testcase_suite, |
| 174 | self.keep_alive_child_end, |
| 175 | self.stdouterr_queue, |
| 176 | self.finished_child_end, |
| 177 | self.result_child_end, |
| 178 | self.logger, |
| 179 | ), |
| 180 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 181 | self.child.start() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 182 | self.last_test_temp_dir = None |
| 183 | self.last_test_vpp_binary = None |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 184 | self._last_test = None |
| 185 | self.last_test_id = None |
juraj.linkes | 721872e | 2018-09-05 18:13:45 +0200 | [diff] [blame] | 186 | self.vpp_pid = None |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 187 | self.last_heard = time.time() |
| 188 | self.core_detected_at = None |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 189 | self.testcases_by_id = {} |
| 190 | self.testclasess_with_core = {} |
| 191 | for testcase in self.testcase_suite: |
| 192 | self.testcases_by_id[testcase.id()] = testcase |
| 193 | self.result = TestResult(testcase_suite, self.testcases_by_id) |
| 194 | |
| 195 | @property |
| 196 | def last_test(self): |
| 197 | return self._last_test |
| 198 | |
| 199 | @last_test.setter |
| 200 | def last_test(self, test_id): |
| 201 | self.last_test_id = test_id |
| 202 | if test_id in self.testcases_by_id: |
| 203 | testcase = self.testcases_by_id[test_id] |
| 204 | self._last_test = testcase.shortDescription() |
| 205 | if not self._last_test: |
| 206 | self._last_test = str(testcase) |
| 207 | else: |
| 208 | self._last_test = test_id |
| 209 | |
| 210 | def add_testclass_with_core(self): |
| 211 | if self.last_test_id in self.testcases_by_id: |
| 212 | test = self.testcases_by_id[self.last_test_id] |
| 213 | class_name = unittest.util.strclass(test.__class__) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 214 | test_name = "'{}' ({})".format( |
| 215 | get_test_description(descriptions, test), self.last_test_id |
| 216 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 217 | else: |
| 218 | test_name = self.last_test_id |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 219 | class_name = re.match( |
| 220 | r"((tearDownClass)|(setUpClass)) " r"\((.+\..+)\)", test_name |
| 221 | ).groups()[3] |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 222 | if class_name not in self.testclasess_with_core: |
| 223 | self.testclasess_with_core[class_name] = ( |
| 224 | test_name, |
| 225 | self.last_test_vpp_binary, |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 226 | self.last_test_temp_dir, |
| 227 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 228 | |
| 229 | def close_pipes(self): |
| 230 | self.keep_alive_child_end.close() |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 231 | self.finished_child_end.close() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 232 | self.result_child_end.close() |
| 233 | self.keep_alive_parent_end.close() |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 234 | self.finished_parent_end.close() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 235 | self.result_parent_end.close() |
| 236 | |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 237 | def was_successful(self): |
| 238 | return self.result.was_successful() |
| 239 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 240 | @property |
| 241 | def cpus_used(self): |
| 242 | return self.testcase_suite.cpus_used |
| 243 | |
| 244 | def get_assigned_cpus(self): |
| 245 | return self.testcase_suite.get_assigned_cpus() |
| 246 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 247 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 248 | def stdouterr_reader_wrapper( |
| 249 | unread_testcases, finished_unread_testcases, read_testcases |
| 250 | ): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 251 | read_testcase = None |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 252 | while read_testcases.is_set() or unread_testcases: |
| 253 | if finished_unread_testcases: |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 254 | read_testcase = finished_unread_testcases.pop() |
| 255 | unread_testcases.remove(read_testcase) |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 256 | elif unread_testcases: |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 257 | read_testcase = unread_testcases.pop() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 258 | if read_testcase: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 259 | data = "" |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 260 | while data is not None: |
| 261 | sys.stdout.write(data) |
| 262 | data = read_testcase.stdouterr_queue.get() |
| 263 | |
| 264 | read_testcase.stdouterr_queue.close() |
| 265 | finished_unread_testcases.discard(read_testcase) |
| 266 | read_testcase = None |
| 267 | |
| 268 | |
Dmitry Valter | 3ace4d6 | 2022-03-26 15:43:14 +0000 | [diff] [blame] | 269 | def handle_failed_suite(logger, last_test_temp_dir, vpp_pid, vpp_binary): |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 270 | if last_test_temp_dir: |
| 271 | # Need to create link in case of a timeout or core dump without failure |
| 272 | lttd = os.path.basename(last_test_temp_dir) |
Klement Sekera | 152a9b6 | 2022-05-13 18:01:36 +0200 | [diff] [blame] | 273 | link_path = os.path.join(config.failed_dir, f"{lttd}-FAILED") |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 274 | if not os.path.exists(link_path): |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 275 | os.symlink(last_test_temp_dir, link_path) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 276 | logger.error( |
| 277 | "Symlink to failed testcase directory: %s -> %s" % (link_path, lttd) |
| 278 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 279 | |
| 280 | # Report core existence |
| 281 | core_path = get_core_path(last_test_temp_dir) |
| 282 | if os.path.exists(core_path): |
| 283 | logger.error( |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 284 | "Core-file exists in test temporary directory: %s!" % core_path |
| 285 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 286 | check_core_path(logger, core_path) |
Paul Vinciguerra | 38a4ec7 | 2018-11-28 11:34:21 -0800 | [diff] [blame] | 287 | logger.debug("Running 'file %s':" % core_path) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 288 | try: |
| 289 | info = check_output(["file", core_path]) |
| 290 | logger.debug(info) |
| 291 | except CalledProcessError as e: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 292 | logger.error( |
| 293 | "Subprocess returned with return code " |
| 294 | "while running `file' utility on core-file " |
| 295 | "returned: " |
| 296 | "rc=%s", |
| 297 | e.returncode, |
| 298 | ) |
Paul Vinciguerra | 38a4ec7 | 2018-11-28 11:34:21 -0800 | [diff] [blame] | 299 | except OSError as e: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 300 | logger.error( |
| 301 | "Subprocess returned with OS error while " |
| 302 | "running 'file' utility " |
| 303 | "on core-file: " |
| 304 | "(%s) %s", |
| 305 | e.errno, |
| 306 | e.strerror, |
| 307 | ) |
Paul Vinciguerra | 38a4ec7 | 2018-11-28 11:34:21 -0800 | [diff] [blame] | 308 | except Exception as e: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 309 | logger.exception("Unexpected error running `file' utility on core-file") |
Dmitry Valter | 3ace4d6 | 2022-03-26 15:43:14 +0000 | [diff] [blame] | 310 | logger.error(f"gdb {vpp_binary} {core_path}") |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 311 | |
| 312 | if vpp_pid: |
| 313 | # Copy api post mortem |
| 314 | api_post_mortem_path = "/tmp/api_post_mortem.%d" % vpp_pid |
| 315 | if os.path.isfile(api_post_mortem_path): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 316 | logger.error( |
| 317 | "Copying api_post_mortem.%d to %s" % (vpp_pid, last_test_temp_dir) |
| 318 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 319 | shutil.copy2(api_post_mortem_path, last_test_temp_dir) |
| 320 | |
| 321 | |
| 322 | def check_and_handle_core(vpp_binary, tempdir, core_crash_test): |
| 323 | if is_core_present(tempdir): |
Klement Sekera | f40ee3a | 2019-05-06 19:11:25 +0200 | [diff] [blame] | 324 | if debug_core: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 325 | print( |
| 326 | "VPP core detected in %s. Last test running was %s" |
| 327 | % (tempdir, core_crash_test) |
| 328 | ) |
Klement Sekera | f40ee3a | 2019-05-06 19:11:25 +0200 | [diff] [blame] | 329 | print(single_line_delim) |
| 330 | spawn_gdb(vpp_binary, get_core_path(tempdir)) |
| 331 | print(single_line_delim) |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 332 | elif config.compress_core: |
Klement Sekera | f40ee3a | 2019-05-06 19:11:25 +0200 | [diff] [blame] | 333 | print("Compressing core-file in test directory `%s'" % tempdir) |
| 334 | os.system("gzip %s" % get_core_path(tempdir)) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 335 | |
| 336 | |
| 337 | def handle_cores(failed_testcases): |
Klement Sekera | f40ee3a | 2019-05-06 19:11:25 +0200 | [diff] [blame] | 338 | for failed_testcase in failed_testcases: |
| 339 | tcs_with_core = failed_testcase.testclasess_with_core |
| 340 | if tcs_with_core: |
| 341 | for test, vpp_binary, tempdir in tcs_with_core.values(): |
| 342 | check_and_handle_core(vpp_binary, tempdir, test) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 343 | |
| 344 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 345 | def process_finished_testsuite( |
| 346 | wrapped_testcase_suite, finished_testcase_suites, failed_wrapped_testcases, results |
| 347 | ): |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 348 | results.append(wrapped_testcase_suite.result) |
| 349 | finished_testcase_suites.add(wrapped_testcase_suite) |
| 350 | stop_run = False |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 351 | if config.failfast and not wrapped_testcase_suite.was_successful(): |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 352 | stop_run = True |
| 353 | |
| 354 | if not wrapped_testcase_suite.was_successful(): |
| 355 | failed_wrapped_testcases.add(wrapped_testcase_suite) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 356 | handle_failed_suite( |
| 357 | wrapped_testcase_suite.logger, |
| 358 | wrapped_testcase_suite.last_test_temp_dir, |
| 359 | wrapped_testcase_suite.vpp_pid, |
| 360 | wrapped_testcase_suite.last_test_vpp_binary, |
| 361 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 362 | |
| 363 | return stop_run |
| 364 | |
| 365 | |
juraj.linkes | 721872e | 2018-09-05 18:13:45 +0200 | [diff] [blame] | 366 | def run_forked(testcase_suites): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 367 | wrapped_testcase_suites = set() |
Andrew Yourtchenko | a3b7c55 | 2020-08-26 14:33:54 +0000 | [diff] [blame] | 368 | solo_testcase_suites = [] |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 369 | |
| 370 | # suites are unhashable, need to use list |
| 371 | results = [] |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 372 | unread_testcases = set() |
| 373 | finished_unread_testcases = set() |
| 374 | manager = StreamQueueManager() |
| 375 | manager.start() |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 376 | tests_running = 0 |
| 377 | free_cpus = list(available_cpus) |
| 378 | |
| 379 | def on_suite_start(tc): |
| 380 | nonlocal tests_running |
| 381 | nonlocal free_cpus |
| 382 | tests_running = tests_running + 1 |
| 383 | |
| 384 | def on_suite_finish(tc): |
| 385 | nonlocal tests_running |
| 386 | nonlocal free_cpus |
| 387 | tests_running = tests_running - 1 |
| 388 | assert tests_running >= 0 |
| 389 | free_cpus.extend(tc.get_assigned_cpus()) |
| 390 | |
| 391 | def run_suite(suite): |
| 392 | nonlocal manager |
| 393 | nonlocal wrapped_testcase_suites |
| 394 | nonlocal unread_testcases |
| 395 | nonlocal free_cpus |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 396 | suite.assign_cpus(free_cpus[: suite.cpus_used]) |
| 397 | free_cpus = free_cpus[suite.cpus_used :] |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 398 | wrapper = TestCaseWrapper(suite, manager) |
| 399 | wrapped_testcase_suites.add(wrapper) |
| 400 | unread_testcases.add(wrapper) |
| 401 | on_suite_start(suite) |
| 402 | |
| 403 | def can_run_suite(suite): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 404 | return tests_running < max_concurrent_tests and ( |
| 405 | suite.cpus_used <= len(free_cpus) or suite.cpus_used > max_vpp_cpus |
| 406 | ) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 407 | |
| 408 | while free_cpus and testcase_suites: |
| 409 | a_suite = testcase_suites[0] |
| 410 | if a_suite.is_tagged_run_solo: |
Andrew Yourtchenko | a3b7c55 | 2020-08-26 14:33:54 +0000 | [diff] [blame] | 411 | a_suite = testcase_suites.pop(0) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 412 | solo_testcase_suites.append(a_suite) |
| 413 | continue |
| 414 | if can_run_suite(a_suite): |
| 415 | a_suite = testcase_suites.pop(0) |
| 416 | run_suite(a_suite) |
Andrew Yourtchenko | a3b7c55 | 2020-08-26 14:33:54 +0000 | [diff] [blame] | 417 | else: |
| 418 | break |
| 419 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 420 | if tests_running == 0 and solo_testcase_suites: |
| 421 | a_suite = solo_testcase_suites.pop(0) |
| 422 | run_suite(a_suite) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 423 | |
| 424 | read_from_testcases = threading.Event() |
| 425 | read_from_testcases.set() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 426 | stdouterr_thread = threading.Thread( |
| 427 | target=stdouterr_reader_wrapper, |
| 428 | args=(unread_testcases, finished_unread_testcases, read_from_testcases), |
| 429 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 430 | stdouterr_thread.start() |
| 431 | |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 432 | failed_wrapped_testcases = set() |
| 433 | stop_run = False |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 434 | |
| 435 | try: |
Klement Sekera | c7d5047 | 2023-04-14 17:43:35 +0200 | [diff] [blame] | 436 | while wrapped_testcase_suites or testcase_suites: |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 437 | finished_testcase_suites = set() |
| 438 | for wrapped_testcase_suite in wrapped_testcase_suites: |
| 439 | while wrapped_testcase_suite.result_parent_end.poll(): |
| 440 | wrapped_testcase_suite.result.process_result( |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 441 | *wrapped_testcase_suite.result_parent_end.recv() |
| 442 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 443 | wrapped_testcase_suite.last_heard = time.time() |
| 444 | |
| 445 | while wrapped_testcase_suite.keep_alive_parent_end.poll(): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 446 | ( |
| 447 | wrapped_testcase_suite.last_test, |
| 448 | wrapped_testcase_suite.last_test_vpp_binary, |
| 449 | wrapped_testcase_suite.last_test_temp_dir, |
| 450 | wrapped_testcase_suite.vpp_pid, |
| 451 | ) = wrapped_testcase_suite.keep_alive_parent_end.recv() |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 452 | wrapped_testcase_suite.last_heard = time.time() |
| 453 | |
| 454 | if wrapped_testcase_suite.finished_parent_end.poll(): |
| 455 | wrapped_testcase_suite.finished_parent_end.recv() |
| 456 | wrapped_testcase_suite.last_heard = time.time() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 457 | stop_run = ( |
| 458 | process_finished_testsuite( |
| 459 | wrapped_testcase_suite, |
| 460 | finished_testcase_suites, |
| 461 | failed_wrapped_testcases, |
| 462 | results, |
| 463 | ) |
| 464 | or stop_run |
| 465 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 466 | continue |
| 467 | |
| 468 | fail = False |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 469 | if wrapped_testcase_suite.last_heard + config.timeout < time.time(): |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 470 | fail = True |
| 471 | wrapped_testcase_suite.logger.critical( |
| 472 | "Child test runner process timed out " |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 473 | "(last test running was `%s' in `%s')!" |
| 474 | % ( |
| 475 | wrapped_testcase_suite.last_test, |
| 476 | wrapped_testcase_suite.last_test_temp_dir, |
| 477 | ) |
| 478 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 479 | elif not wrapped_testcase_suite.child.is_alive(): |
| 480 | fail = True |
| 481 | wrapped_testcase_suite.logger.critical( |
| 482 | "Child test runner process unexpectedly died " |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 483 | "(last test running was `%s' in `%s')!" |
| 484 | % ( |
| 485 | wrapped_testcase_suite.last_test, |
| 486 | wrapped_testcase_suite.last_test_temp_dir, |
| 487 | ) |
| 488 | ) |
| 489 | elif ( |
| 490 | wrapped_testcase_suite.last_test_temp_dir |
| 491 | and wrapped_testcase_suite.last_test_vpp_binary |
| 492 | ): |
| 493 | if is_core_present(wrapped_testcase_suite.last_test_temp_dir): |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 494 | wrapped_testcase_suite.add_testclass_with_core() |
| 495 | if wrapped_testcase_suite.core_detected_at is None: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 496 | wrapped_testcase_suite.core_detected_at = time.time() |
| 497 | elif ( |
| 498 | wrapped_testcase_suite.core_detected_at + core_timeout |
| 499 | < time.time() |
| 500 | ): |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 501 | wrapped_testcase_suite.logger.critical( |
| 502 | "Child test runner process unresponsive and " |
| 503 | "core-file exists in test temporary directory " |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 504 | "(last test running was `%s' in `%s')!" |
| 505 | % ( |
| 506 | wrapped_testcase_suite.last_test, |
| 507 | wrapped_testcase_suite.last_test_temp_dir, |
| 508 | ) |
| 509 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 510 | fail = True |
| 511 | |
| 512 | if fail: |
| 513 | wrapped_testcase_suite.child.terminate() |
| 514 | try: |
| 515 | # terminating the child process tends to leave orphan |
| 516 | # VPP process around |
| 517 | if wrapped_testcase_suite.vpp_pid: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 518 | os.kill(wrapped_testcase_suite.vpp_pid, signal.SIGTERM) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 519 | except OSError: |
| 520 | # already dead |
| 521 | pass |
| 522 | wrapped_testcase_suite.result.crashed = True |
| 523 | wrapped_testcase_suite.result.process_result( |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 524 | wrapped_testcase_suite.last_test_id, TestResultCode.ERROR |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 525 | ) |
| 526 | stop_run = ( |
| 527 | process_finished_testsuite( |
| 528 | wrapped_testcase_suite, |
| 529 | finished_testcase_suites, |
| 530 | failed_wrapped_testcases, |
| 531 | results, |
| 532 | ) |
| 533 | or stop_run |
| 534 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 535 | |
| 536 | for finished_testcase in finished_testcase_suites: |
Andrew Yourtchenko | 4269352 | 2019-11-05 01:08:26 +0100 | [diff] [blame] | 537 | # Somewhat surprisingly, the join below may |
| 538 | # timeout, even if client signaled that |
| 539 | # it finished - so we note it just in case. |
| 540 | join_start = time.time() |
| 541 | finished_testcase.child.join(test_finished_join_timeout) |
| 542 | join_end = time.time() |
| 543 | if join_end - join_start >= test_finished_join_timeout: |
| 544 | finished_testcase.logger.error( |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 545 | "Timeout joining finished test: %s (pid %d)" |
| 546 | % (finished_testcase.last_test, finished_testcase.child.pid) |
| 547 | ) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 548 | finished_testcase.close_pipes() |
| 549 | wrapped_testcase_suites.remove(finished_testcase) |
| 550 | finished_unread_testcases.add(finished_testcase) |
| 551 | finished_testcase.stdouterr_queue.put(None) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 552 | on_suite_finish(finished_testcase) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 553 | if stop_run: |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 554 | while testcase_suites: |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 555 | results.append(TestResult(testcase_suites.pop(0))) |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 556 | elif testcase_suites: |
Klement Sekera | c7d5047 | 2023-04-14 17:43:35 +0200 | [diff] [blame] | 557 | a_suite = testcase_suites[0] |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 558 | while a_suite and a_suite.is_tagged_run_solo: |
Klement Sekera | c7d5047 | 2023-04-14 17:43:35 +0200 | [diff] [blame] | 559 | testcase_suites.pop(0) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 560 | solo_testcase_suites.append(a_suite) |
Andrew Yourtchenko | a3b7c55 | 2020-08-26 14:33:54 +0000 | [diff] [blame] | 561 | if testcase_suites: |
Klement Sekera | c7d5047 | 2023-04-14 17:43:35 +0200 | [diff] [blame] | 562 | a_suite = testcase_suites[0] |
Andrew Yourtchenko | a3b7c55 | 2020-08-26 14:33:54 +0000 | [diff] [blame] | 563 | else: |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 564 | a_suite = None |
| 565 | if a_suite and can_run_suite(a_suite): |
Klement Sekera | c7d5047 | 2023-04-14 17:43:35 +0200 | [diff] [blame] | 566 | testcase_suites.pop(0) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 567 | run_suite(a_suite) |
| 568 | if solo_testcase_suites and tests_running == 0: |
| 569 | a_suite = solo_testcase_suites.pop(0) |
| 570 | run_suite(a_suite) |
Paul Vinciguerra | c0692a4 | 2019-03-15 19:16:50 -0700 | [diff] [blame] | 571 | time.sleep(0.1) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 572 | except Exception: |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 573 | for wrapped_testcase_suite in wrapped_testcase_suites: |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 574 | wrapped_testcase_suite.child.terminate() |
| 575 | wrapped_testcase_suite.stdouterr_queue.put(None) |
| 576 | raise |
| 577 | finally: |
| 578 | read_from_testcases.clear() |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 579 | stdouterr_thread.join(config.timeout) |
juraj.linkes | e6b58cf | 2018-11-29 09:56:35 +0100 | [diff] [blame] | 580 | manager.shutdown() |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 581 | |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 582 | handle_cores(failed_wrapped_testcases) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 583 | return results |
| 584 | |
| 585 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 586 | class TestSuiteWrapper(unittest.TestSuite): |
| 587 | cpus_used = 0 |
| 588 | |
| 589 | def __init__(self): |
| 590 | return super().__init__() |
| 591 | |
| 592 | def addTest(self, test): |
| 593 | self.cpus_used = max(self.cpus_used, test.get_cpus_required()) |
| 594 | super().addTest(test) |
| 595 | |
| 596 | def assign_cpus(self, cpus): |
| 597 | self.cpus = cpus |
| 598 | |
| 599 | def _handleClassSetUp(self, test, result): |
| 600 | if not test.__class__.skipped_due_to_cpu_lack: |
| 601 | test.assign_cpus(self.cpus) |
| 602 | super()._handleClassSetUp(test, result) |
| 603 | |
| 604 | def get_assigned_cpus(self): |
| 605 | return self.cpus |
| 606 | |
| 607 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 608 | class SplitToSuitesCallback: |
| 609 | def __init__(self, filter_callback): |
| 610 | self.suites = {} |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 611 | self.suite_name = "default" |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 612 | self.filter_callback = filter_callback |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 613 | self.filtered = TestSuiteWrapper() |
Klement Sekera | fcbf444 | 2017-08-17 07:38:42 +0200 | [diff] [blame] | 614 | |
| 615 | def __call__(self, file_name, cls, method): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 616 | test_method = cls(method) |
| 617 | if self.filter_callback(file_name, cls.__name__, method): |
| 618 | self.suite_name = file_name + cls.__name__ |
| 619 | if self.suite_name not in self.suites: |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 620 | self.suites[self.suite_name] = TestSuiteWrapper() |
Andrew Yourtchenko | 06f3281 | 2021-01-14 10:19:08 +0000 | [diff] [blame] | 621 | self.suites[self.suite_name].is_tagged_run_solo = False |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 622 | self.suites[self.suite_name].addTest(test_method) |
Andrew Yourtchenko | 06f3281 | 2021-01-14 10:19:08 +0000 | [diff] [blame] | 623 | if test_method.is_tagged_run_solo(): |
| 624 | self.suites[self.suite_name].is_tagged_run_solo = True |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 625 | |
| 626 | else: |
| 627 | self.filtered.addTest(test_method) |
Klement Sekera | fcbf444 | 2017-08-17 07:38:42 +0200 | [diff] [blame] | 628 | |
| 629 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 630 | def parse_test_filter(test_filter): |
| 631 | f = test_filter |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 632 | filter_file_name = None |
| 633 | filter_class_name = None |
| 634 | filter_func_name = None |
| 635 | if f: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 636 | if "." in f: |
| 637 | parts = f.split(".") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 638 | if len(parts) > 3: |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 639 | raise Exception(f"Invalid test filter: {test_filter}") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 640 | if len(parts) > 2: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 641 | if parts[2] not in ("*", ""): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 642 | filter_func_name = parts[2] |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 643 | if parts[1] not in ("*", ""): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 644 | filter_class_name = parts[1] |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 645 | if parts[0] not in ("*", ""): |
| 646 | if parts[0].startswith("test_"): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 647 | filter_file_name = parts[0] |
| 648 | else: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 649 | filter_file_name = "test_%s" % parts[0] |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 650 | else: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 651 | if f.startswith("test_"): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 652 | filter_file_name = f |
| 653 | else: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 654 | filter_file_name = "test_%s" % f |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 655 | if filter_file_name: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 656 | filter_file_name = "%s.py" % filter_file_name |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 657 | return filter_file_name, filter_class_name, filter_func_name |
| 658 | |
| 659 | |
| 660 | def filter_tests(tests, filter_cb): |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 661 | result = TestSuiteWrapper() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 662 | for t in tests: |
| 663 | if isinstance(t, unittest.suite.TestSuite): |
| 664 | # this is a bunch of tests, recursively filter... |
| 665 | x = filter_tests(t, filter_cb) |
| 666 | if x.countTestCases() > 0: |
| 667 | result.addTest(x) |
| 668 | elif isinstance(t, unittest.TestCase): |
| 669 | # this is a single test |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 670 | parts = t.id().split(".") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 671 | # t.id() for common cases like this: |
| 672 | # test_classifier.TestClassifier.test_acl_ip |
| 673 | # apply filtering only if it is so |
| 674 | if len(parts) == 3: |
| 675 | if not filter_cb(parts[0], parts[1], parts[2]): |
| 676 | continue |
| 677 | result.addTest(t) |
| 678 | else: |
| 679 | # unexpected object, don't touch it |
| 680 | result.addTest(t) |
| 681 | return result |
| 682 | |
| 683 | |
| 684 | class FilterByTestOption: |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 685 | def __init__(self, filters): |
| 686 | self.filters = filters |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 687 | |
| 688 | def __call__(self, file_name, class_name, func_name): |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 689 | def test_one( |
| 690 | filter_file_name, |
| 691 | filter_class_name, |
| 692 | filter_func_name, |
| 693 | file_name, |
| 694 | class_name, |
| 695 | func_name, |
| 696 | ): |
| 697 | if filter_file_name: |
| 698 | fn_match = fnmatch.fnmatch(file_name, filter_file_name) |
| 699 | if not fn_match: |
| 700 | return False |
| 701 | if filter_class_name and class_name != filter_class_name: |
Andrew Yourtchenko | d760f79 | 2018-10-03 11:38:31 +0200 | [diff] [blame] | 702 | return False |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 703 | if filter_func_name and func_name != filter_func_name: |
| 704 | return False |
| 705 | return True |
| 706 | |
| 707 | for filter_file_name, filter_class_name, filter_func_name in self.filters: |
| 708 | if test_one( |
| 709 | filter_file_name, |
| 710 | filter_class_name, |
| 711 | filter_func_name, |
| 712 | file_name, |
| 713 | class_name, |
| 714 | func_name, |
| 715 | ): |
| 716 | return True |
| 717 | |
| 718 | return False |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 719 | |
| 720 | |
| 721 | class FilterByClassList: |
juraj.linkes | 721872e | 2018-09-05 18:13:45 +0200 | [diff] [blame] | 722 | def __init__(self, classes_with_filenames): |
| 723 | self.classes_with_filenames = classes_with_filenames |
Klement Sekera | df2b980 | 2017-10-05 10:26:03 +0200 | [diff] [blame] | 724 | |
| 725 | def __call__(self, file_name, class_name, func_name): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 726 | return ".".join([file_name, class_name]) in self.classes_with_filenames |
Klement Sekera | df2b980 | 2017-10-05 10:26:03 +0200 | [diff] [blame] | 727 | |
| 728 | |
| 729 | def suite_from_failed(suite, failed): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 730 | failed = {x.rsplit(".", 1)[0] for x in failed} |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 731 | filter_cb = FilterByClassList(failed) |
| 732 | suite = filter_tests(suite, filter_cb) |
Klement Sekera | 4c5422e | 2018-06-22 13:19:45 +0200 | [diff] [blame] | 733 | return suite |
Klement Sekera | df2b980 | 2017-10-05 10:26:03 +0200 | [diff] [blame] | 734 | |
| 735 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 736 | class AllResults(dict): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 737 | def __init__(self): |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 738 | super(AllResults, self).__init__() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 739 | self.all_testcases = 0 |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 740 | self.results_per_suite = [] |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 741 | for trc in list(TestResultCode): |
| 742 | self[trc] = 0 |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 743 | self.rerun = [] |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 744 | self.testsuites_no_tests_run = [] |
Klement Sekera | 909a6a1 | 2017-08-08 04:33:53 +0200 | [diff] [blame] | 745 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 746 | def add_results(self, result): |
| 747 | self.results_per_suite.append(result) |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 748 | for trc in list(TestResultCode): |
| 749 | self[trc] += len(result[trc]) |
Klement Sekera | 0574226 | 2018-03-14 18:14:49 +0100 | [diff] [blame] | 750 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 751 | def add_result(self, result): |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 752 | retval = 0 |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 753 | self.all_testcases += result.testcase_suite.countTestCases() |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 754 | self.add_results(result) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 755 | |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 756 | if result.no_tests_run(): |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 757 | self.testsuites_no_tests_run.append(result.testcase_suite) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 758 | if result.crashed: |
| 759 | retval = -1 |
| 760 | else: |
| 761 | retval = 1 |
| 762 | elif not result.was_successful(): |
| 763 | retval = 1 |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 764 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 765 | if retval != 0: |
juraj.linkes | abec012 | 2018-11-16 17:28:56 +0100 | [diff] [blame] | 766 | self.rerun.append(result.testcase_suite) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 767 | |
| 768 | return retval |
| 769 | |
| 770 | def print_results(self): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 771 | print("") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 772 | print(double_line_delim) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 773 | print("TEST RESULTS:") |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 774 | |
| 775 | def indent_results(lines): |
| 776 | lines = list(filter(None, lines)) |
| 777 | maximum = max(lines, key=lambda x: x.index(":")) |
| 778 | maximum = 4 + maximum.index(":") |
| 779 | for l in lines: |
| 780 | padding = " " * (maximum - l.index(":")) |
| 781 | print(f"{padding}{l}") |
| 782 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 783 | indent_results( |
| 784 | [ |
| 785 | f"Scheduled tests: {self.all_testcases}", |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 786 | f"Executed tests: {self[TestResultCode.TEST_RUN]}", |
| 787 | f"Passed tests: {colorize(self[TestResultCode.PASS], GREEN)}", |
| 788 | f"Expected failures: {colorize(self[TestResultCode.EXPECTED_FAIL], GREEN)}" |
| 789 | if self[TestResultCode.EXPECTED_FAIL] |
| 790 | else None, |
| 791 | f"Skipped tests: {colorize(self[TestResultCode.SKIP], YELLOW)}" |
| 792 | if self[TestResultCode.SKIP] |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 793 | else None, |
| 794 | f"Not Executed tests: {colorize(self.not_executed, RED)}" |
| 795 | if self.not_executed |
| 796 | else None, |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 797 | f"Failures: {colorize(self[TestResultCode.FAIL], RED)}" |
| 798 | if self[TestResultCode.FAIL] |
| 799 | else None, |
| 800 | f"Unexpected passes: {colorize(self[TestResultCode.UNEXPECTED_PASS], RED)}" |
| 801 | if self[TestResultCode.UNEXPECTED_PASS] |
| 802 | else None, |
| 803 | f"Errors: {colorize(self[TestResultCode.ERROR], RED)}" |
| 804 | if self[TestResultCode.ERROR] |
| 805 | else None, |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 806 | "Tests skipped due to lack of CPUS: " |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 807 | f"{colorize(self[TestResultCode.SKIP_CPU_SHORTAGE], YELLOW)}" |
| 808 | if self[TestResultCode.SKIP_CPU_SHORTAGE] |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 809 | else None, |
| 810 | ] |
| 811 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 812 | |
| 813 | if self.all_failed > 0: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 814 | print("FAILURES AND ERRORS IN TESTS:") |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 815 | for result in self.results_per_suite: |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 816 | old_testcase_name = None |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 817 | for tr_code, headline in ( |
| 818 | (TestResultCode.FAIL, "FAILURE"), |
| 819 | (TestResultCode.ERROR, "ERROR"), |
| 820 | (TestResultCode.UNEXPECTED_PASS, "UNEXPECTED PASS"), |
| 821 | ): |
| 822 | if not result[tr_code]: |
| 823 | continue |
| 824 | |
| 825 | for failed_test_id in result[tr_code]: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 826 | new_testcase_name, test_name = result.get_testcase_names( |
| 827 | failed_test_id |
| 828 | ) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 829 | if new_testcase_name != old_testcase_name: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 830 | print( |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 831 | f" Testcase name: {colorize(new_testcase_name, RED)}" |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 832 | ) |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 833 | old_testcase_name = new_testcase_name |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 834 | print( |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 835 | f" {headline}: {colorize(test_name, RED)} [{failed_test_id}]" |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 836 | ) |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 837 | |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 838 | if self.testsuites_no_tests_run: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 839 | print("TESTCASES WHERE NO TESTS WERE SUCCESSFULLY EXECUTED:") |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 840 | tc_classes = set() |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 841 | for testsuite in self.testsuites_no_tests_run: |
| 842 | for testcase in testsuite: |
| 843 | tc_classes.add(get_testcase_doc_name(testcase)) |
| 844 | for tc_class in tc_classes: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 845 | print(" {}".format(colorize(tc_class, RED))) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 846 | |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 847 | if self[TestResultCode.SKIP_CPU_SHORTAGE]: |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 848 | print() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 849 | print( |
| 850 | colorize( |
| 851 | " SOME TESTS WERE SKIPPED BECAUSE THERE ARE NOT" |
| 852 | " ENOUGH CPUS AVAILABLE", |
| 853 | YELLOW, |
| 854 | ) |
| 855 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 856 | print(double_line_delim) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 857 | print("") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 858 | |
| 859 | @property |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 860 | def not_executed(self): |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 861 | return self.all_testcases - self[TestResultCode.TEST_RUN] |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 862 | |
| 863 | @property |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 864 | def all_failed(self): |
Klement Sekera | 47f3527 | 2023-03-29 16:04:58 +0200 | [diff] [blame] | 865 | return ( |
| 866 | self[TestResultCode.FAIL] |
| 867 | + self[TestResultCode.ERROR] |
| 868 | + self[TestResultCode.UNEXPECTED_PASS] |
| 869 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 870 | |
| 871 | |
| 872 | def parse_results(results): |
| 873 | """ |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 874 | Prints the number of scheduled, executed, not executed, passed, failed, |
| 875 | errored and skipped tests and details about failed and errored tests. |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 876 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 877 | Also returns all suites where any test failed. |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 878 | |
| 879 | :param results: |
| 880 | :return: |
| 881 | """ |
| 882 | |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 883 | results_per_suite = AllResults() |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 884 | crashed = False |
| 885 | failed = False |
juraj.linkes | cae64f8 | 2018-09-19 15:01:47 +0200 | [diff] [blame] | 886 | for result in results: |
| 887 | result_code = results_per_suite.add_result(result) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 888 | if result_code == 1: |
| 889 | failed = True |
| 890 | elif result_code == -1: |
| 891 | crashed = True |
| 892 | |
| 893 | results_per_suite.print_results() |
| 894 | |
| 895 | if crashed: |
| 896 | return_code = -1 |
| 897 | elif failed: |
| 898 | return_code = 1 |
| 899 | else: |
| 900 | return_code = 0 |
| 901 | return return_code, results_per_suite.rerun |
| 902 | |
| 903 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 904 | if __name__ == "__main__": |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 905 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 906 | print(f"Config is: {config}") |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 907 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 908 | if config.sanity: |
| 909 | print("Running sanity test case.") |
| 910 | try: |
| 911 | rc = sanity_run_vpp.main() |
| 912 | if rc != 0: |
| 913 | sys.exit(rc) |
| 914 | except Exception as e: |
| 915 | print(traceback.format_exc()) |
| 916 | print("Couldn't run sanity test case.") |
| 917 | sys.exit(-1) |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 918 | |
Andrew Yourtchenko | 4269352 | 2019-11-05 01:08:26 +0100 | [diff] [blame] | 919 | test_finished_join_timeout = 15 |
| 920 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 921 | debug_gdb = config.debug in ["gdb", "gdbserver", "attach"] |
| 922 | debug_core = config.debug == "core" |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 923 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 924 | run_interactive = debug_gdb or config.step or config.force_foreground |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 925 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 926 | max_concurrent_tests = 0 |
| 927 | print(f"OS reports {num_cpus} available cpu(s).") |
Paul Vinciguerra | 025cd9c | 2019-07-08 14:14:22 -0400 | [diff] [blame] | 928 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 929 | test_jobs = config.jobs |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 930 | if test_jobs == "auto": |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 931 | if run_interactive: |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 932 | max_concurrent_tests = 1 |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 933 | print("Interactive mode required, running tests consecutively.") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 934 | else: |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 935 | max_concurrent_tests = num_cpus |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 936 | print( |
| 937 | f"Running at most {max_concurrent_tests} python test " |
| 938 | "processes concurrently." |
| 939 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 940 | else: |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 941 | max_concurrent_tests = test_jobs |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 942 | print( |
| 943 | f"Running at most {max_concurrent_tests} python test processes " |
| 944 | "concurrently as set by 'TEST_JOBS'." |
| 945 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 946 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 947 | print(f"Using at most {max_vpp_cpus} cpus for VPP threads.") |
| 948 | |
| 949 | if run_interactive and max_concurrent_tests > 1: |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 950 | raise NotImplementedError( |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 951 | "Running tests interactively (DEBUG is gdb[server] or ATTACH or " |
| 952 | "STEP is set) in parallel (TEST_JOBS is more than 1) is not " |
| 953 | "supported" |
| 954 | ) |
Klement Sekera | 13a83ef | 2018-03-21 12:35:51 +0100 | [diff] [blame] | 955 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 956 | descriptions = True |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 957 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 958 | print("Running tests using custom test runner.") |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 959 | filters = [(parse_test_filter(f)) for f in config.filter.split(",")] |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 960 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 961 | print( |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 962 | "Selected filters: ", |
| 963 | "|".join( |
| 964 | f"file={filter_file}, class={filter_class}, function={filter_func}" |
| 965 | for filter_file, filter_class, filter_func in filters |
| 966 | ), |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 967 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 968 | |
Klement Sekera | 08c50e3 | 2023-04-14 17:44:04 +0200 | [diff] [blame] | 969 | filter_cb = FilterByTestOption(filters) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 970 | |
| 971 | cb = SplitToSuitesCallback(filter_cb) |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 972 | for d in config.test_src_dir: |
Klement Sekera | df2b980 | 2017-10-05 10:26:03 +0200 | [diff] [blame] | 973 | print("Adding tests from directory tree %s" % d) |
Saima Yunus | c7f93b3 | 2022-08-10 03:25:31 -0400 | [diff] [blame] | 974 | discover_tests(d, cb) |
Klement Sekera | 3f6ff19 | 2017-08-11 06:56:05 +0200 | [diff] [blame] | 975 | |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 976 | # suites are not hashable, need to use list |
| 977 | suites = [] |
| 978 | tests_amount = 0 |
| 979 | for testcase_suite in cb.suites.values(): |
| 980 | tests_amount += testcase_suite.countTestCases() |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 981 | if testcase_suite.cpus_used > max_vpp_cpus: |
| 982 | # here we replace test functions with lambdas to just skip them |
| 983 | # but we also replace setUp/tearDown functions to do nothing |
| 984 | # so that the test can be "started" and "stopped", so that we can |
| 985 | # still keep those prints (test description - SKIP), which are done |
| 986 | # in stopTest() (for that to trigger, test function must run) |
| 987 | for t in testcase_suite: |
| 988 | for m in dir(t): |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 989 | if m.startswith("test_"): |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 990 | setattr(t, m, lambda: t.skipTest("not enough cpus")) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 991 | setattr(t.__class__, "setUpClass", lambda: None) |
| 992 | setattr(t.__class__, "tearDownClass", lambda: None) |
| 993 | setattr(t, "setUp", lambda: None) |
| 994 | setattr(t, "tearDown", lambda: None) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 995 | t.__class__.skipped_due_to_cpu_lack = True |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 996 | suites.append(testcase_suite) |
Klement Sekera | bbfa5fd | 2018-06-27 13:54:32 +0200 | [diff] [blame] | 997 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 998 | print( |
| 999 | "%s out of %s tests match specified filters" |
| 1000 | % (tests_amount, tests_amount + cb.filtered.countTestCases()) |
| 1001 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1002 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 1003 | if not config.extended: |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1004 | print("Not running extended tests (some tests will be skipped)") |
| 1005 | |
Klement Sekera | b23ffd7 | 2021-05-31 16:08:53 +0200 | [diff] [blame] | 1006 | attempts = config.retries + 1 |
Klement Sekera | df2b980 | 2017-10-05 10:26:03 +0200 | [diff] [blame] | 1007 | if attempts > 1: |
| 1008 | print("Perform %s attempts to pass the suite..." % attempts) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1009 | |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 1010 | if run_interactive and suites: |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1011 | # don't fork if requiring interactive terminal |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1012 | print("Running tests in foreground in the current process") |
juraj.linkes | 46e8e91 | 2019-01-10 12:13:07 +0100 | [diff] [blame] | 1013 | full_suite = unittest.TestSuite() |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 1014 | free_cpus = list(available_cpus) |
| 1015 | cpu_shortage = False |
| 1016 | for suite in suites: |
| 1017 | if suite.cpus_used <= max_vpp_cpus: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1018 | suite.assign_cpus(free_cpus[: suite.cpus_used]) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 1019 | else: |
| 1020 | suite.assign_cpus([]) |
| 1021 | cpu_shortage = True |
Klement Sekera | d743dff | 2019-10-29 11:03:47 +0000 | [diff] [blame] | 1022 | full_suite.addTests(suites) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1023 | result = VppTestRunner( |
| 1024 | verbosity=config.verbose, failfast=config.failfast, print_summary=True |
| 1025 | ).run(full_suite) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 1026 | was_successful = result.wasSuccessful() |
| 1027 | if not was_successful: |
| 1028 | for test_case_info in result.failed_test_cases_info: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1029 | handle_failed_suite( |
| 1030 | test_case_info.logger, |
| 1031 | test_case_info.tempdir, |
| 1032 | test_case_info.vpp_pid, |
| 1033 | config.vpp, |
| 1034 | ) |
Klement Sekera | f40ee3a | 2019-05-06 19:11:25 +0200 | [diff] [blame] | 1035 | if test_case_info in result.core_crash_test_cases_info: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1036 | check_and_handle_core( |
| 1037 | test_case_info.vpp_bin_path, |
| 1038 | test_case_info.tempdir, |
| 1039 | test_case_info.core_crash_test, |
| 1040 | ) |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 1041 | |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 1042 | if cpu_shortage: |
| 1043 | print() |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1044 | print( |
| 1045 | colorize( |
| 1046 | "SOME TESTS WERE SKIPPED BECAUSE THERE ARE NOT" |
| 1047 | " ENOUGH CPUS AVAILABLE", |
| 1048 | YELLOW, |
| 1049 | ) |
| 1050 | ) |
Klement Sekera | 558ceab | 2021-04-08 19:37:41 +0200 | [diff] [blame] | 1051 | print() |
juraj.linkes | 40dd73b | 2018-09-21 13:55:16 +0200 | [diff] [blame] | 1052 | sys.exit(not was_successful) |
Klement Sekera | 13a83ef | 2018-03-21 12:35:51 +0100 | [diff] [blame] | 1053 | else: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1054 | print( |
| 1055 | "Running each VPPTestCase in a separate background process" |
| 1056 | f" with at most {max_concurrent_tests} parallel python test " |
| 1057 | "process(es)" |
| 1058 | ) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1059 | exit_code = 0 |
Naveen Joy | 2cbf2fb | 2019-03-06 10:41:06 -0800 | [diff] [blame] | 1060 | while suites and attempts > 0: |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1061 | results = run_forked(suites) |
| 1062 | exit_code, suites = parse_results(results) |
| 1063 | attempts -= 1 |
| 1064 | if exit_code == 0: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1065 | print("Test run was successful") |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1066 | else: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 1067 | print("%s attempt(s) left." % attempts) |
juraj.linkes | 184870a | 2018-07-16 14:22:01 +0200 | [diff] [blame] | 1068 | sys.exit(exit_code) |