From 1edacf35bb32161a84115b2aabf806f042948031 Mon Sep 17 00:00:00 2001 From: Maximilian Pilz Date: Mon, 23 Jan 2023 21:37:48 +0100 Subject: [PATCH] fix child_processes being empty and exit from main loop when is_alive of another process returns False --- src/mpunittest/result.py | 2 +- src/mpunittest/runner.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/mpunittest/result.py b/src/mpunittest/result.py index ad54ed7..a54c721 100644 --- a/src/mpunittest/result.py +++ b/src/mpunittest/result.py @@ -131,7 +131,7 @@ def addUnexpectedSuccess( self.test_id_to_result_mapping[test.id()] = MergeableResult.Result.FAIL def wasSuccessful(self) -> bool: - # TODO: implement while considering expected failures + # TODO: consider expected failures return self.overall_result() == self.Result.PASS def stop(self) -> None: diff --git a/src/mpunittest/runner.py b/src/mpunittest/runner.py index e812a9e..38ff8aa 100644 --- a/src/mpunittest/runner.py +++ b/src/mpunittest/runner.py @@ -89,6 +89,7 @@ def __init__(self, :param daemons: will be used as daemon flag for process creation :param result_class: type to instantiate for saving unittest results """ + assert process_count > 0 self._process_count = process_count if mp_context is None: @@ -203,6 +204,11 @@ def discover_and_run( process_conn_with_process_tuples.append((respective_parent_conn, child_conn, child_process)) parent_conn_to_process_mapping[respective_parent_conn] = child_process + child_processes.append(child_process) + + assert set(child_processes) == \ + set(parent_conn_to_process_mapping.values()) == \ + set((p for _, __, p in process_conn_with_process_tuples)) self._logger.debug('primary runner process will start discovery in directory "%s" ' 'with pattern "%s" and top level directory "%s"', @@ -224,6 +230,7 @@ def discover_and_run( for conn, _, process in process_conn_with_process_tuples: try: test_id = test_ids.pop() + # TODO: check whether it is writeable conn.send(test_id) # TODO: consider doing this in while True loop below self._logger.info('primary runner process delegated run of %s to %s', test_id, process.name) @@ -242,7 +249,16 @@ def discover_and_run( test_results = list() + assert child_processes + loop_counter = 0 while True: + if loop_counter == 0: + if not all(map(multiprocessing.Process.is_alive, child_processes)): + raise RuntimeError('At least one process terminated prematurely.') + + loop_counter += 1 + loop_counter %= 100 + if platform.system() != 'Windows': read_events = read_selector.select(timeout=0.001) for key, mask in read_events: @@ -317,6 +333,7 @@ def discover_and_run( respective_parent_conn.close() self._logger.debug('will wait for child processes to finish') + assert child_processes for child_process in child_processes: child_process.join() exit_code = child_process.exitcode