|
13 | 13 | # License for the specific language governing permissions and limitations |
14 | 14 | # under the License. |
15 | 15 |
|
| 16 | +import threading |
| 17 | +import time |
16 | 18 | from unittest import mock |
17 | 19 |
|
18 | 20 | from futurist import periodics |
|
35 | 37 | from neutron.tests.unit import testlib_api |
36 | 38 |
|
37 | 39 |
|
| 40 | +class TestMaintenanceThread(base.BaseTestCase): |
| 41 | + |
| 42 | + def test_start_bounds_thread_pool_executor(self): |
| 43 | + """Verify MaintenanceThread runs periodic tasks with one worker.""" |
| 44 | + num_tasks = 5 |
| 45 | + run_counter = [0] * num_tasks |
| 46 | + active_threads = [] |
| 47 | + target_runs = 5 |
| 48 | + |
| 49 | + class _PeriodicTask: |
| 50 | + def __init__(self, idx): |
| 51 | + self.idx = idx |
| 52 | + |
| 53 | + @periodics.periodic(spacing=0.05) |
| 54 | + def trivial_task(self): |
| 55 | + run_counter[self.idx] += 1 |
| 56 | + active_threads.append(threading.active_count()) |
| 57 | + time.sleep(0) |
| 58 | + if run_counter[self.idx] >= target_runs: |
| 59 | + raise periodics.NeverAgain |
| 60 | + |
| 61 | + mt = maintenance.MaintenanceThread() |
| 62 | + for idx in range(num_tasks): |
| 63 | + mt.add_periodics(_PeriodicTask(idx)) |
| 64 | + |
| 65 | + threads_before = threading.active_count() |
| 66 | + mt.start() |
| 67 | + threads_after_start = threading.active_count() |
| 68 | + self.assertGreater(threads_after_start, threads_before) |
| 69 | + |
| 70 | + executor = mt._worker._executor_factory() |
| 71 | + # Let some tasks be executed. |
| 72 | + time.sleep(2) |
| 73 | + threads_after_wait = threading.active_count() |
| 74 | + self.assertEqual(threads_after_wait, threads_after_start + 1) |
| 75 | + |
| 76 | + executor.shutdown(wait=False) |
| 77 | + mt._thread.join(timeout=3) |
| 78 | + threads_end = threading.active_count() |
| 79 | + self.assertEqual(threads_end, threads_after_wait) |
| 80 | + self.assertTrue(all(target_runs == _c for _c in run_counter)) |
| 81 | + |
| 82 | + |
38 | 83 | class TestHasLockPeriodicDecorator(base.BaseTestCase): |
39 | 84 |
|
40 | 85 | def test_decorator_no_limit_have_lock(self): |
|
0 commit comments