|
16 | 16 | import queue |
17 | 17 | import threading |
18 | 18 | import time |
| 19 | +import warnings |
19 | 20 |
|
20 | 21 | import mock |
21 | 22 |
|
@@ -61,6 +62,24 @@ def callback(*args, **kwargs): |
61 | 62 | assert sorted(called_with) == expected_calls |
62 | 63 |
|
63 | 64 |
|
| 65 | +def test_schedule_after_executor_shutdown_warning(): |
| 66 | + def callback(*args, **kwargs): |
| 67 | + pass |
| 68 | + |
| 69 | + scheduler_ = scheduler.ThreadScheduler() |
| 70 | + |
| 71 | + scheduler_.schedule(callback, "arg1", kwarg1="meep") |
| 72 | + scheduler_._executor.shutdown() |
| 73 | + |
| 74 | + with warnings.catch_warnings(record=True) as warned: |
| 75 | + scheduler_.schedule(callback, "arg2", kwarg2="boop") |
| 76 | + |
| 77 | + assert len(warned) == 1 |
| 78 | + assert issubclass(warned[0].category, RuntimeWarning) |
| 79 | + warning_msg = str(warned[0].message) |
| 80 | + assert "after executor shutdown" in warning_msg |
| 81 | + |
| 82 | + |
64 | 83 | def test_shutdown_nonblocking_by_default(): |
65 | 84 | called_with = [] |
66 | 85 | at_least_one_called = threading.Event() |
@@ -125,3 +144,30 @@ def callback(message): |
125 | 144 |
|
126 | 145 | err_msg = "Shutdown did not wait for the already running callbacks to complete." |
127 | 146 | assert at_least_one_completed.is_set(), err_msg |
| 147 | + |
| 148 | + |
| 149 | +def test_shutdown_handles_executor_queue_sentinels(): |
| 150 | + at_least_one_called = threading.Event() |
| 151 | + |
| 152 | + def callback(_): |
| 153 | + at_least_one_called.set() |
| 154 | + time.sleep(1.0) |
| 155 | + |
| 156 | + executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) |
| 157 | + scheduler_ = scheduler.ThreadScheduler(executor=executor) |
| 158 | + |
| 159 | + scheduler_.schedule(callback, "message_1") |
| 160 | + scheduler_.schedule(callback, "message_2") |
| 161 | + scheduler_.schedule(callback, "message_3") |
| 162 | + |
| 163 | + # Simulate executor shutdown from another thread. |
| 164 | + executor._work_queue.put(None) |
| 165 | + executor._work_queue.put(None) |
| 166 | + |
| 167 | + at_least_one_called.wait() |
| 168 | + dropped = scheduler_.shutdown(await_msg_callbacks=True) |
| 169 | + |
| 170 | + assert len(set(dropped)) == 2 # Also test for item uniqueness. |
| 171 | + for msg in dropped: |
| 172 | + assert msg is not None |
| 173 | + assert msg.startswith("message_") |
0 commit comments