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