Skip to content

Commit 3e01116

Browse files
cartertinneyCopilot
andcommitted
tests: require explicit polling timeouts
Make every poll_until and async_poll_until call state its timeout so bounded waiting is visible at the assertion site rather than hidden by a helper default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7972d81 commit 3e01116

4 files changed

Lines changed: 41 additions & 33 deletions

File tree

‎tests/conftest.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
def poll_until():
1717
"""Return a helper that polls a condition without exceeding a timeout."""
1818

19-
def poll_until_condition(condition, timeout=5, interval=0.01):
19+
def poll_until_condition(condition, *, timeout, interval=0.01):
2020
deadline = time.monotonic() + timeout
2121
while not condition():
2222
remaining = deadline - time.monotonic()
@@ -31,7 +31,7 @@ def poll_until_condition(condition, timeout=5, interval=0.01):
3131
def async_poll_until():
3232
"""Return an async helper that polls a condition without blocking the event loop."""
3333

34-
async def poll_until_condition(condition, timeout=5, interval=0.01):
34+
async def poll_until_condition(condition, *, timeout, interval=0.01):
3535
async def poll_condition():
3636
while not condition():
3737
await asyncio.sleep(interval)

‎tests/unit/common/pipeline/test_pipeline_stages_base.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def test_invoke_handler(self, mocker, stage, event, poll_until):
188188
stage.on_connected_handler = mock_handler
189189
stage.handle_pipeline_event(event)
190190
# Wait for the handler invocation to complete
191-
poll_until(lambda: mock_handler.call_count >= 1)
191+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
192192
assert mock_handler.call_count == 1
193193
assert mock_handler.call_args == mocker.call()
194194

@@ -209,7 +209,7 @@ def test_invoke_handler(self, mocker, stage, event, poll_until):
209209
stage.on_disconnected_handler = mock_handler
210210
stage.handle_pipeline_event(event)
211211
# Wait for the handler invocation to complete
212-
poll_until(lambda: mock_handler.call_count >= 1)
212+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
213213
assert mock_handler.call_count == 1
214214
assert mock_handler.call_args == mocker.call()
215215

@@ -230,7 +230,7 @@ def test_invoke_handler(self, mocker, stage, event, poll_until):
230230
stage.on_new_sastoken_required_handler = mock_handler
231231
stage.handle_pipeline_event(event)
232232
# Wait for the handler invocation to complete
233-
poll_until(lambda: mock_handler.call_count >= 1)
233+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
234234
assert mock_handler.call_count == 1
235235
assert mock_handler.call_args == mocker.call()
236236

@@ -253,7 +253,7 @@ def test_invoke_handler(self, mocker, stage, event, poll_until):
253253
stage.on_background_exception_handler = mock_handler
254254
stage.handle_pipeline_event(event)
255255
# Wait for the handler invocation to complete
256-
poll_until(lambda: mock_handler.call_count >= 1)
256+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
257257
assert mock_handler.call_count == 1
258258
assert mock_handler.call_args == mocker.call(event.e)
259259

@@ -274,7 +274,7 @@ def test_invoke_handler(self, mocker, stage, event, poll_until):
274274
stage.on_pipeline_event_handler = mock_handler
275275
stage.handle_pipeline_event(event)
276276
# Wait for the handler invocation to complete
277-
poll_until(lambda: mock_handler.call_count >= 1)
277+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
278278
assert mock_handler.call_count == 1
279279
assert mock_handler.call_args == mocker.call(event)
280280

‎tests/unit/iothub/aio/test_async_handler_manager.py‎

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ async def test_handler_invoked(
413413
mock_obj = mocker.MagicMock()
414414
inbox.put(mock_obj)
415415
# Wait for the handler invocation to complete
416-
await async_poll_until(lambda: handler_checker.handler_called)
416+
await async_poll_until(lambda: handler_checker.handler_called, timeout=5)
417417

418418
# Handler has been called with the item from the inbox
419419
assert handler_checker.handler_called is True
@@ -441,7 +441,7 @@ async def test_handler_invoked_multiple(
441441
for _ in range(5):
442442
inbox.put(mocker.MagicMock())
443443
# Wait for all handler invocations to complete
444-
await async_poll_until(lambda: handler_checker.handler_call_count >= 5)
444+
await async_poll_until(lambda: handler_checker.handler_call_count >= 5, timeout=5)
445445

446446
# Handler has been called 5 times
447447
assert handler_checker.handler_call_count == 5
@@ -550,7 +550,7 @@ async def coro_handler(arg):
550550
# Add an item to corresponding inbox, triggering the handler
551551
inbox.put(mocker.MagicMock())
552552
# Wait for the background exception handler to be called
553-
await async_poll_until(lambda: background_exc_spy.call_count >= 1)
553+
await async_poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
554554
# Background exception handler was called
555555
assert background_exc_spy.call_count == 1
556556
e = background_exc_spy.call_args[0][0]
@@ -567,7 +567,7 @@ async def coro_handler(arg):
567567
# Add an item to corresponding inbox, triggering the handler
568568
inbox.put(mocker.MagicMock())
569569
# Wait for the background exception handler to be called
570-
await async_poll_until(lambda: background_exc_spy.call_count >= 1)
570+
await async_poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
571571
# Background exception handler was called
572572
assert background_exc_spy.call_count == 1
573573
e = background_exc_spy.call_args[0][0]
@@ -595,21 +595,25 @@ def handler1(arg):
595595

596596
inbox.put(mocker.MagicMock())
597597
# Wait for handler1 to replace itself with handler2
598-
await async_poll_until(lambda: getattr(handler_manager, handler_name) is handler2)
598+
await async_poll_until(
599+
lambda: getattr(handler_manager, handler_name) is handler2, timeout=5
600+
)
599601
# The set handler (handler1) has been replaced with a new handler (handler2)
600602
assert getattr(handler_manager, handler_name) is not handler1
601603
assert getattr(handler_manager, handler_name) is handler2
602604
# Add a new item to the inbox
603605
inbox.put(mocker.MagicMock())
604606
# Wait for handler2 to replace itself with the mock
605-
await async_poll_until(lambda: getattr(handler_manager, handler_name) is mock_handler)
607+
await async_poll_until(
608+
lambda: getattr(handler_manager, handler_name) is mock_handler, timeout=5
609+
)
606610
# The set handler (handler2) has now been replaced by a mock handler
607611
assert getattr(handler_manager, handler_name) is not handler2
608612
assert getattr(handler_manager, handler_name) is mock_handler
609613
# Add a new item to the inbox
610614
inbox.put(mocker.MagicMock())
611615
# Wait for the mock handler invocation to complete
612-
await async_poll_until(lambda: mock_handler.call_count >= 1)
616+
await async_poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
613617
# The mock was now called
614618
assert getattr(handler_manager, handler_name).call_count == 1
615619

@@ -702,7 +706,7 @@ async def test_handler_invoked(
702706
# Add the event to the client inbox
703707
inbox.put(event)
704708
# Wait for the handler invocation to complete
705-
await async_poll_until(lambda: handler_checker.handler_call_count >= 1)
709+
await async_poll_until(lambda: handler_checker.handler_call_count >= 1, timeout=5)
706710

707711
# Handler has been called with the arguments from the event
708712
assert handler_checker.handler_call_count == 1
@@ -712,7 +716,7 @@ async def test_handler_invoked(
712716
non_matching_event = client_event.ClientEvent("NON_MATCHING_EVENT")
713717
inbox.put(non_matching_event)
714718
# Wait for the runner to consume the non-matching event
715-
await async_poll_until(inbox.empty)
719+
await async_poll_until(inbox.empty, timeout=5)
716720

717721
# Handler has not been called again
718722
assert handler_checker.handler_call_count == 1
@@ -739,7 +743,7 @@ async def test_handler_invoked_multiple(
739743
for _ in range(5):
740744
inbox.put(event)
741745
# Wait for all handler invocations to complete
742-
await async_poll_until(lambda: handler_checker.handler_call_count >= 5)
746+
await async_poll_until(lambda: handler_checker.handler_call_count >= 5, timeout=5)
743747

744748
# Handler has been called 5 times
745749
assert handler_checker.handler_call_count == 5
@@ -773,7 +777,7 @@ async def coro_handler(*args):
773777
# Add an item to corresponding inbox, triggering the handler
774778
inbox.put(event)
775779
# Wait for the background exception handler to be called
776-
await async_poll_until(lambda: background_exc_spy.call_count >= 1)
780+
await async_poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
777781
# Background exception handler was called
778782
assert background_exc_spy.call_count == 1
779783
e = background_exc_spy.call_args[0][0]
@@ -790,7 +794,7 @@ async def coro_handler(*args):
790794
# Add an item to corresponding inbox, triggering the handler
791795
inbox.put(event)
792796
# Wait for the background exception handler to be called
793-
await async_poll_until(lambda: background_exc_spy.call_count >= 1)
797+
await async_poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
794798
# Background exception handler was called
795799
assert background_exc_spy.call_count == 1
796800
e = background_exc_spy.call_args[0][0]
@@ -818,21 +822,25 @@ def handler1(*args):
818822

819823
inbox.put(event)
820824
# Wait for handler1 to replace itself with handler2
821-
await async_poll_until(lambda: getattr(handler_manager, handler_name) is handler2)
825+
await async_poll_until(
826+
lambda: getattr(handler_manager, handler_name) is handler2, timeout=5
827+
)
822828
# The set handler (handler1) has been replaced with a new handler (handler2)
823829
assert getattr(handler_manager, handler_name) is not handler1
824830
assert getattr(handler_manager, handler_name) is handler2
825831
# Add a new item to the inbox
826832
inbox.put(event)
827833
# Wait for handler2 to replace itself with the mock
828-
await async_poll_until(lambda: getattr(handler_manager, handler_name) is mock_handler)
834+
await async_poll_until(
835+
lambda: getattr(handler_manager, handler_name) is mock_handler, timeout=5
836+
)
829837
# The set handler (handler2) has now been replaced by a mock handler
830838
assert getattr(handler_manager, handler_name) is not handler2
831839
assert getattr(handler_manager, handler_name) is mock_handler
832840
# Add a new item to the inbox
833841
inbox.put(event)
834842
# Wait for the mock handler invocation to complete
835-
await async_poll_until(lambda: mock_handler.call_count >= 1)
843+
await async_poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
836844
# The mock was now called
837845
assert getattr(handler_manager, handler_name).call_count == 1
838846

‎tests/unit/iothub/test_sync_handler_manager.py‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ def test_handler_invoked(self, mocker, handler_name, handler_manager, inbox, pol
363363
mock_obj = mocker.MagicMock()
364364
inbox.put(mock_obj)
365365
# Wait for the handler invocation to complete
366-
poll_until(lambda: mock_handler.call_count >= 1)
366+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
367367

368368
# Handler has been called with the item from the inbox
369369
assert mock_handler.call_count == 1
@@ -385,7 +385,7 @@ def test_handler_invoked_multiple(
385385
for _ in range(5):
386386
inbox.put(mocker.MagicMock())
387387
# Wait for all handler invocations to complete
388-
poll_until(lambda: mock_handler.call_count >= 5)
388+
poll_until(lambda: mock_handler.call_count >= 5, timeout=5)
389389

390390
# Handler has been called 5 times
391391
assert mock_handler.call_count == 5
@@ -485,7 +485,7 @@ def test_exception_in_handler(
485485
# Add an item to corresponding inbox, triggering the handler
486486
inbox.put(mocker.MagicMock())
487487
# Wait for the background exception handler to be called
488-
poll_until(lambda: background_exc_spy.call_count >= 1)
488+
poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
489489
# Handler has now been called
490490
assert mock_handler.call_count == 1
491491
# Background exception handler was called
@@ -506,14 +506,14 @@ def handler(arg):
506506

507507
inbox.put(mocker.MagicMock())
508508
# Wait for the handler to replace itself with the mock
509-
poll_until(lambda: getattr(handler_manager, handler_name) is not handler)
509+
poll_until(lambda: getattr(handler_manager, handler_name) is not handler, timeout=5)
510510
# Handler has been replaced with a mock, but the mock has not been invoked
511511
assert getattr(handler_manager, handler_name) is not handler
512512
assert getattr(handler_manager, handler_name).call_count == 0
513513
# Add a new item to the inbox
514514
inbox.put(mocker.MagicMock())
515515
# Wait for the mock handler invocation to complete
516-
poll_until(lambda: getattr(handler_manager, handler_name).call_count >= 1)
516+
poll_until(lambda: getattr(handler_manager, handler_name).call_count >= 1, timeout=5)
517517
# The mock was now called
518518
assert getattr(handler_manager, handler_name).call_count == 1
519519

@@ -597,7 +597,7 @@ def test_handler_invoked(self, mocker, handler_name, handler_manager, inbox, eve
597597
# Add the event to the client event inbox
598598
inbox.put(event)
599599
# Wait for the handler invocation to complete
600-
poll_until(lambda: mock_handler.call_count >= 1)
600+
poll_until(lambda: mock_handler.call_count >= 1, timeout=5)
601601

602602
# Handler has been called with the arguments from the event
603603
assert mock_handler.call_count == 1
@@ -607,7 +607,7 @@ def test_handler_invoked(self, mocker, handler_name, handler_manager, inbox, eve
607607
non_matching_event = client_event.ClientEvent("NON_MATCHING_EVENT")
608608
inbox.put(non_matching_event)
609609
# Wait for the runner to consume the non-matching event
610-
poll_until(inbox.empty)
610+
poll_until(inbox.empty, timeout=5)
611611

612612
# Handler has not been called again
613613
assert mock_handler.call_count == 1
@@ -628,7 +628,7 @@ def test_handler_invoked_multiple(
628628
for _ in range(5):
629629
inbox.put(event)
630630
# Wait for all handler invocations to complete
631-
poll_until(lambda: mock_handler.call_count >= 5)
631+
poll_until(lambda: mock_handler.call_count >= 5, timeout=5)
632632

633633
# Handler has been called 5 times
634634
assert mock_handler.call_count == 5
@@ -652,7 +652,7 @@ def test_exception_in_handler(
652652
# Add the event to the client event inbox, triggering the handler
653653
inbox.put(event)
654654
# Wait for the background exception handler to be called
655-
poll_until(lambda: background_exc_spy.call_count >= 1)
655+
poll_until(lambda: background_exc_spy.call_count >= 1, timeout=5)
656656
# Handler has now been called
657657
assert mock_handler.call_count == 1
658658
# Background exception handler was called
@@ -673,14 +673,14 @@ def handler(*args):
673673

674674
inbox.put(event)
675675
# Wait for the handler to replace itself with the mock
676-
poll_until(lambda: getattr(handler_manager, handler_name) is not handler)
676+
poll_until(lambda: getattr(handler_manager, handler_name) is not handler, timeout=5)
677677
# Handler has been replaced with a mock, but the mock has not been invoked
678678
assert getattr(handler_manager, handler_name) is not handler
679679
assert getattr(handler_manager, handler_name).call_count == 0
680680
# Add a new event to the inbox
681681
inbox.put(event)
682682
# Wait for the mock handler invocation to complete
683-
poll_until(lambda: getattr(handler_manager, handler_name).call_count >= 1)
683+
poll_until(lambda: getattr(handler_manager, handler_name).call_count >= 1, timeout=5)
684684
# The mock was now called
685685
assert getattr(handler_manager, handler_name).call_count == 1
686686

0 commit comments

Comments
 (0)