def test_runner_wrapper(suite, keep_alive_pipe, result_pipe, stdouterr_queue,
- logger):
+ partial_result_queue, logger):
sys.stdout = stdouterr_queue
sys.stderr = stdouterr_queue
VppTestCase.logger = logger
- unittest.installHandler()
result = VppTestRunner(keep_alive_pipe=keep_alive_pipe,
descriptions=descriptions,
verbosity=verbose,
+ results_pipe=partial_result_queue,
failfast=failfast).run(suite)
result_pipe.send(result)
result_pipe.close()
self.keep_alive_parent_end, self.keep_alive_child_end = Pipe(
duplex=False)
self.result_parent_end, self.result_child_end = Pipe(duplex=False)
+ self.partial_result_parent_end, self.partial_result_child_end = Pipe(
+ duplex=False)
self.testcase_suite = testcase_suite
self.stdouterr_queue = manager.Queue()
self.logger = get_parallel_logger(self.stdouterr_queue)
self.child = Process(target=test_runner_wrapper,
args=(testcase_suite, self.keep_alive_child_end,
self.result_child_end, self.stdouterr_queue,
- self.logger)
+ self.partial_result_child_end, self.logger)
)
self.child.start()
self.pid = self.child.pid
self.last_test_vpp_binary = None
self.last_test = None
self.result = None
+ self.vpp_pid = None
self.last_heard = time.time()
self.core_detected_at = None
self.failed_tests = []
- self.fail = False
- self.fail_addressed = False
+ self.partial_result = None
def close_pipes(self):
self.keep_alive_child_end.close()
self.result_child_end.close()
+ self.partial_result_child_end.close()
self.keep_alive_parent_end.close()
self.result_parent_end.close()
+ self.partial_result_parent_end.close()
def stdouterr_reader_wrapper(unread_testcases, finished_unread_testcases,
read_testcase = None
-def run_forked(testcases):
+def run_forked(testcase_suites):
wrapped_testcase_suites = set()
# suites are unhashable, need to use list
manager = StreamQueueManager()
manager.start()
for i in range(concurrent_tests):
- if len(testcases) > 0:
- wrapped_testcase_suite = TestCaseWrapper(testcases.pop(0), manager)
+ if len(testcase_suites) > 0:
+ wrapped_testcase_suite = TestCaseWrapper(testcase_suites.pop(0),
+ manager)
wrapped_testcase_suites.add(wrapped_testcase_suite)
unread_testcases.add(wrapped_testcase_suite)
# time.sleep(1)
for wrapped_testcase_suite in wrapped_testcase_suites:
readable = select.select(
[wrapped_testcase_suite.keep_alive_parent_end.fileno(),
- wrapped_testcase_suite.result_parent_end.fileno()],
+ wrapped_testcase_suite.result_parent_end.fileno(),
+ wrapped_testcase_suite.partial_result_parent_end.fileno()],
[], [], 1)[0]
if wrapped_testcase_suite.result_parent_end.fileno() in readable:
results.append(
finished_testcase_suites.add(wrapped_testcase_suite)
continue
+ if wrapped_testcase_suite.partial_result_parent_end.fileno() \
+ in readable:
+ while wrapped_testcase_suite.partial_result_parent_end.poll():
+ wrapped_testcase_suite.partial_result = \
+ wrapped_testcase_suite.partial_result_parent_end.recv()
+ wrapped_testcase_suite.last_heard = time.time()
+
if wrapped_testcase_suite.keep_alive_parent_end.fileno() \
in readable:
while wrapped_testcase_suite.keep_alive_parent_end.poll():
wrapped_testcase_suite.keep_alive_parent_end.recv()
wrapped_testcase_suite.last_heard = time.time()
- if not wrapped_testcase_suite.fail:
- if wrapped_testcase_suite.last_heard + \
- test_timeout < time.time() and \
- not os.path.isfile(
- "%s/_core_handled" %
- wrapped_testcase_suite.last_test_temp_dir):
- wrapped_testcase_suite.fail = True
- wrapped_testcase_suite.logger.critical(
- "Timeout while waiting for child test "
- "runner process (last test running was "
- "`%s' in `%s')!" %
- (wrapped_testcase_suite.last_test,
- wrapped_testcase_suite.last_test_temp_dir))
- elif not wrapped_testcase_suite.child.is_alive():
- wrapped_testcase_suite.fail = True
- wrapped_testcase_suite.logger.critical(
- "Child python process unexpectedly died "
- "(last test running was `%s' in `%s')!" %
- (wrapped_testcase_suite.last_test,
- wrapped_testcase_suite.last_test_temp_dir))
- elif wrapped_testcase_suite.last_test_temp_dir and \
- wrapped_testcase_suite.last_test_vpp_binary:
- core_path = "%s/core" % \
- wrapped_testcase_suite.last_test_temp_dir
- if os.path.isfile(core_path):
- if wrapped_testcase_suite.core_detected_at is None:
- wrapped_testcase_suite.core_detected_at = \
- time.time()
- elif wrapped_testcase_suite.core_detected_at + \
- core_timeout < time.time():
- if not os.path.isfile(
- "%s/_core_handled" %
- wrapped_testcase_suite.
- last_test_temp_dir):
- wrapped_testcase_suite.logger.critical(
- "Child python process unresponsive and "
- "core-file exists in test temporary "
- "directory!")
- wrapped_testcase_suite.fail = True
-
- if wrapped_testcase_suite.fail and not \
- wrapped_testcase_suite.fail_addressed:
+ fail = False
+ if wrapped_testcase_suite.last_heard + test_timeout < time.time() \
+ and not os.path.isfile(
+ "%s/_core_handled" %
+ wrapped_testcase_suite.last_test_temp_dir):
+ fail = True
+ wrapped_testcase_suite.logger.critical(
+ "Timeout while waiting for child test "
+ "runner process (last test running was "
+ "`%s' in `%s')!" %
+ (wrapped_testcase_suite.last_test,
+ wrapped_testcase_suite.last_test_temp_dir))
+ elif not wrapped_testcase_suite.child.is_alive():
+ fail = True
+ wrapped_testcase_suite.logger.critical(
+ "Child python process unexpectedly died "
+ "(last test running was `%s' in `%s')!" %
+ (wrapped_testcase_suite.last_test,
+ wrapped_testcase_suite.last_test_temp_dir))
+ elif wrapped_testcase_suite.last_test_temp_dir and \
+ wrapped_testcase_suite.last_test_vpp_binary:
+ core_path = "%s/core" % \
+ wrapped_testcase_suite.last_test_temp_dir
+ if os.path.isfile(core_path):
+ if wrapped_testcase_suite.core_detected_at is None:
+ wrapped_testcase_suite.core_detected_at = time.time()
+ elif wrapped_testcase_suite.core_detected_at + \
+ core_timeout < time.time():
+ if not os.path.isfile(
+ "%s/_core_handled" %
+ wrapped_testcase_suite.
+ last_test_temp_dir):
+ wrapped_testcase_suite.logger.critical(
+ "Child python process unresponsive and core-"
+ "file exists in test temporary directory!")
+ fail = True
+
+ if fail:
failed_dir = os.getenv('VPP_TEST_FAILED_DIR')
- lttd = os.path.basename(
- wrapped_testcase_suite.last_test_temp_dir)
+ if wrapped_testcase_suite.last_test_temp_dir:
+ lttd = os.path.basename(
+ wrapped_testcase_suite.last_test_temp_dir)
+ else:
+ lttd = None
link_path = '%s%s-FAILED' % (failed_dir, lttd)
wrapped_testcase_suite.logger.error(
"Creating a link to the failed test: %s -> %s" %
(link_path, lttd))
- if not os.path.exists(link_path):
+ if not os.path.exists(link_path) \
+ and wrapped_testcase_suite.last_test_temp_dir:
os.symlink(wrapped_testcase_suite.last_test_temp_dir,
link_path)
api_post_mortem_path = "/tmp/api_post_mortem.%d" % \
spawn_gdb(
wrapped_testcase_suite.last_test_vpp_binary,
core_path, wrapped_testcase_suite.logger)
- os.kill(wrapped_testcase_suite.child.pid, signal.SIGINT)
+ wrapped_testcase_suite.child.terminate()
try:
# terminating the child process tends to leave orphan
# VPP process around
except OSError:
# already dead
pass
- wrapped_testcase_suite.fail_addressed = True
+ results.append((wrapped_testcase_suite.testcase_suite,
+ wrapped_testcase_suite.partial_result))
+ finished_testcase_suites.add(wrapped_testcase_suite)
for finished_testcase in finished_testcase_suites:
finished_testcase.child.join()
wrapped_testcase_suites.remove(finished_testcase)
finished_unread_testcases.add(finished_testcase)
finished_testcase.stdouterr_queue.put(None)
- if len(testcases) > 0:
- new_testcase = TestCaseWrapper(testcases.pop(0), manager)
+ if len(testcase_suites) > 0:
+ new_testcase = TestCaseWrapper(testcase_suites.pop(0), manager)
wrapped_testcase_suites.add(new_testcase)
unread_testcases.add(new_testcase)
class FilterByClassList:
- def __init__(self, class_list):
- self.class_list = class_list
+ def __init__(self, classes_with_filenames):
+ self.classes_with_filenames = classes_with_filenames
def __call__(self, file_name, class_name, func_name):
- return class_name in self.class_list
+ return '.'.join([file_name, class_name]) in self.classes_with_filenames
def suite_from_failed(suite, failed):
+ failed = {x.rsplit('.', 1)[0] for x in failed}
filter_cb = FilterByClassList(failed)
suite = filter_tests(suite, filter_cb)
return suite
def add_result(self, testcase_suite, result):
retval = 0
- self.all_testcases += result.testsRun
- self.passed += result.passed
if result:
- # suite finished properly
- if not result.wasSuccessful():
+ self.all_testcases += result.testsRun
+ self.passed += len(result.passed)
+ if not len(result.passed) + len(result.skipped) \
+ == testcase_suite.countTestCases():
retval = 1
self.add_results(result.failures, self.failures_id)
self.expectedFailures_id)
self.add_results(result.unexpectedSuccesses,
self.unexpectedSuccesses_id)
+ else:
+ retval = -1
if retval != 0:
if concurrent_tests == 1:
if result:
- rerun_classes = {x[0].__class__.__name__ for
- x in result.errors}
- rerun_classes.update({x[0].__class__.__name__ for
- x in result.failures})
- self.rerun.append(suite_from_failed(testcase_suite,
- rerun_classes))
+ rerun_ids = set([])
+ skipped = [x.id() for (x, _) in result.skipped]
+ for testcase in testcase_suite:
+ tc_id = testcase.id()
+ if tc_id not in result.passed and \
+ tc_id not in skipped:
+ rerun_ids.add(tc_id)
+ if len(rerun_ids) > 0:
+ self.rerun.append(suite_from_failed(testcase_suite,
+ rerun_ids))
else:
self.rerun.append(testcase_suite)
else:
if concurrent_tests == 1:
new_suite = unittest.TestSuite()
for suite in suites:
- new_suite.addTest(suite)
+ new_suite.addTests(suite)
suites = [new_suite]