def test_InfiniteProcess__catches_error_in_teardown_after_loop(mocker): expected_error = ValueError("error during teardown") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatRaisesErrorInTeardown(error_queue) mocker.patch("builtins.print", autospec=True) # don't print the error message to stdout p.run(num_iterations=1) assert error_queue.empty() is False actual_error, _ = error_queue.get_nowait() assert isinstance(actual_error, type(expected_error)) assert str(actual_error) == str(expected_error)
def test_invoke_process_run_and_check_errors__raises_and_logs_error_for_InfiniteProcess( mocker, ): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatRaisesError(error_queue) mocked_log = mocker.patch.object(logging, "exception", autospec=True) mocker.patch("builtins.print", autospec=True) # don't print the error message to stdout with pytest.raises(ValueError, match="test message"): invoke_process_run_and_check_errors(p) assert error_queue.empty() is True # the error should have been popped off the queu assert mocked_log.call_count == 1
def test_InfiniteProcess__catches_error_in_setup_before_loop_and_does_not_run_iteration_or_teardown( mocker, ): expected_error = ValueError("error during setup") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatRaisesErrorInSetup(error_queue) mocker.patch("builtins.print", autospec=True) # don't print the error message to stdout p.run(num_iterations=1) assert error_queue.empty() is False actual_error, _ = error_queue.get_nowait() assert p.get_num_iterations() == 0 assert p.is_teardown_complete() is False assert isinstance(actual_error, type(expected_error)) assert str(actual_error) == str(expected_error)
def test_InfiniteProcess__queue_is_populated_with_error_occuring_during_run__and_stop_is_called( mocker, ): expected_error = ValueError("test message") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatRaisesError(error_queue) mocker.patch("builtins.print", autospec=True) # don't print the error message to stdout spied_stop = mocker.spy(p, "stop") p.run() assert error_queue.empty() is False assert spied_stop.call_count == 1 actual_error, _ = error_queue.get() assert isinstance(actual_error, type(expected_error)) assert str(actual_error) == str(expected_error)
def test_invoke_process_run_and_check_errors__passes_values_for_InfiniteProcess(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatCountsIterations(error_queue) invoke_process_run_and_check_errors(p) # runs once by default assert p.get_num_iterations() == 1 invoke_process_run_and_check_errors(p, num_iterations=2) assert p.get_num_iterations() == 3
def test_InfiniteProcess_can_be_run_and_soft_stopped(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) p.start() assert p.is_alive() is True p.soft_stop() p.join() assert p.is_alive() is False assert p.exitcode == 0
def test_invoke_process_run_and_check_errors__does_not_run_setup_or_teardown_by_default(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatTracksSetup(error_queue) invoke_process_run_and_check_errors(p) # runs once by default assert p.get_num_iterations() == 1 assert p.is_setup() is False assert p.is_teardown_complete() is False invoke_process_run_and_check_errors(p, num_iterations=2) assert p.get_num_iterations() == 3
def simple_infinite_looper(): p = InfiniteLoopingParallelismMixIn( SimpleMultiprocessingQueue(), logging.INFO, threading.Event(), threading.Event(), threading.Event(), threading.Event(), threading.Event(), minimum_iteration_duration_seconds=0.01, ) return p
def test_InfiniteProcess__queue_is_populated_with_error_occuring_during_live_spawned_run( mocker, ): # spied_print_exception = mocker.spy( # parallelism_framework, "print_exception" # ) # Eli (3/13/20) can't figure out why this isn't working (call count never gets to 1), so just asserting about print instead mocker.patch("builtins.print", autospec=True) # don't print the error message to stdout expected_error = ValueError("test message") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatRaisesError(error_queue) p.start() p.join() assert error_queue.empty() is False actual_error, actual_stack_trace = error_queue.get() # assert spied_print_exception.call_count == 1 # assert mocked_print.call_count==1 assert isinstance(actual_error, type(expected_error)) assert str(actual_error) == str(expected_error) assert p.exitcode == 0 # When errors are handled, the error code is 0 # assert actual_error == expected_error # Eli (12/24/19): for some reason this asserting doesn't pass...not sure why....so testing class type and str instead assert 'raise ValueError("test message")' in actual_stack_trace
def test_InfiniteProcess_super_InfiniteLoopingParallelismMixIn_is_called_during_init( mocker, ): mocked_init = mocker.patch.object(InfiniteLoopingParallelismMixIn, "__init__") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) # mocked_init.assert_called_once_with(p, error_queue, logging.INFO,MockAny(multiprocessing.Event),MockAny(multiprocessing.Event)) mocked_init.assert_called_once_with( p, error_queue, *init_test_args_InfiniteLoopingParallelismMixIn, minimum_iteration_duration_seconds=0.01, )
def test_put_log_message_into_queue__does_not_sleep_after_putting_message_into_simplequeue( mocker, ): spied_sleep = mocker.spy(time, "sleep") sq = SimpleMultiprocessingQueue() msg = "hey there" put_log_message_into_queue( logging.ERROR, msg, sq, logging.WARNING, pause_after_put=True, ) spied_sleep.assert_not_called()
def test_InfiniteProcess__pause_and_resume_work_while_running(): test_queue = SimpleMultiprocessingQueue() error_queue = multiprocessing.Queue() p = InfiniteProcessThatPopulatesQueue(test_queue, error_queue) p.start() seconds_to_sleep_while_queue_populating = 2 # Eli (12/14/20): in GitHub Windows containers, 0.05 seconds was too short, so just bumping up to 1 second # Tanner (1/31/21): bumping to 2 seconds after another CI issue time.sleep( seconds_to_sleep_while_queue_populating) # let the queue populate p.pause() items_in_queue_at_pause = [] while test_queue.empty() is False: items_in_queue_at_pause.append(test_queue.get()) time.sleep( SECONDS_TO_SLEEP_BETWEEN_CHECKING_QUEUE_SIZE ) # don't relentlessly poll the queue # Eli (2/10/21): There was an odd hanging that occurred once during CI in a windows container...possibly due to relentlessly checking empty/get of the queue(?) https://github.com/CuriBio/stdlib-utils/pull/87/checks?check_run_id=1856410303 assert len(items_in_queue_at_pause) > 0 last_item_in_queue_at_pause = items_in_queue_at_pause[-1] time.sleep(seconds_to_sleep_while_queue_populating ) # give the queue time to populate if pause was unsuccessful assert test_queue.empty() is True p.resume() time.sleep(seconds_to_sleep_while_queue_populating ) # give the queue time to populate hard_stop_results = p.hard_stop() p.join() assert len(hard_stop_results["fatal_error_reporter"]) == 0 items_in_queue_at_stop = [] while test_queue.empty() is False: items_in_queue_at_stop.append(test_queue.get()) time.sleep( SECONDS_TO_SLEEP_BETWEEN_CHECKING_QUEUE_SIZE ) # don't relentlessly poll the queue # Eli (2/10/21): There was an odd hanging that occurred once during CI in a windows container...possibly due to relentlessly checking empty/get of the queue(?) https://github.com/CuriBio/stdlib-utils/pull/87/checks?check_run_id=1856410303 assert len(items_in_queue_at_stop) > 0 assert items_in_queue_at_stop[0] - 1 == last_item_in_queue_at_pause
def test_InfiniteProcess_run_calls___commands_for_each_run_iteration(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatCountsIterations(error_queue) mocker.patch.object(p, "is_stopped", autospec=True, return_value=True) p.run() assert p.get_num_iterations() == 1
def test_InfiniteProcess_internal_logging_level_can_be_set(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue, logging_level=logging.DEBUG) assert p.get_logging_level() == logging.DEBUG
def test_InfiniteProcess_can_set_minimum_iteration_duration(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue, minimum_iteration_duration_seconds=0.22) assert p.get_minimum_iteration_duration_seconds() == 0.22
def test_invoke_process_run_and_check_errors__runs_teardown_with_given_kwarg(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatTracksSetup(error_queue) invoke_process_run_and_check_errors(p, perform_teardown_after_loop=True) # runs once by default assert p.get_num_iterations() == 1 assert p.is_teardown_complete() is True
def test_InfiniteProcess_super_Process_is_called_during_init(mocker): mocked_init = mocker.patch.object(Process, "__init__") error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) mocked_init.assert_called_once_with(p)
def test_SimpleMultiprocessingQueue__get_nowait__returns_value_if_present(): test_queue = SimpleMultiprocessingQueue() expected = "blah" test_queue.put(expected) actual = test_queue.get_nowait() assert actual == expected
def test_SimpleMultiprocessingQueue__put_nowait__adds_value_to_queue(): test_queue = SimpleMultiprocessingQueue() expected = "blah7" test_queue.put_nowait(expected) actual = test_queue.get_nowait() assert actual == expected
def test_InfiniteProcess__calls_teardown_after_loop(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) p.run(num_iterations=1) assert error_queue.empty() is True assert p.is_teardown_complete() is True
def test_InfiniteProcess__calls_setup_before_loop(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatTracksSetup(error_queue) p.run(num_iterations=1) assert error_queue.empty() is True assert p.is_setup() is True
def test_SimpleMultiprocessingQueue__get_nowait__raises_error_if_empty(): test_queue = SimpleMultiprocessingQueue() with pytest.raises(queue.Empty): test_queue.get_nowait()
def test_InfiniteProcess__will_not_soft_stop_when_told_not_to(): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcessThatCannotBeSoftStopped(error_queue) p.soft_stop() p.run(num_iterations=1) assert p.is_stopped() is False
def test_InfiniteProcess__run_can_be_executed_just_once(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) spied_is_stopped = mocker.spy(p, "is_stopped") p.run(num_iterations=1) spied_is_stopped.assert_called_once()
def test_InfiniteProcess__run_can_be_executed_just_four_cycles(mocker): error_queue = SimpleMultiprocessingQueue() p = InfiniteProcess(error_queue) spied_is_stopped = mocker.spy(p, "is_stopped") p.run(num_iterations=4) assert spied_is_stopped.call_count == 4