From 5c91eb03a7f5b5c2c45f4ab65d9dab5673ec6079 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Wed, 7 Oct 2026 11:42:41 +0200 Subject: [PATCH] test(dispatcher): cancel queued deliveries when disconnect_slot releases several wrappers --- tests/unit_tests/test_bec_dispatcher.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/unit_tests/test_bec_dispatcher.py b/tests/unit_tests/test_bec_dispatcher.py index e3b14884..a4830760 100644 --- a/tests/unit_tests/test_bec_dispatcher.py +++ b/tests/unit_tests/test_bec_dispatcher.py @@ -652,3 +652,27 @@ def test_qthreadsafe_callback_checks_lambda_owner_at_delivery(qapp, teardown): qapp.processEvents() assert calls == [] + + +@pytest.mark.parametrize("topics", [["span-a", "span-b"], None], ids=["topic-list", "no-topics"]) +def test_dispatcher_disconnect_slot_spanning_wrappers_cancels_queued_deliveries( + bec_dispatcher, qapp, topics +): + # disconnect_slot may release several wrappers of the same callback at once (a topic list + # spanning registrations, or no topics at all); every fully emptied wrapper must be + # invalidated so deliveries that are already queued for it are dropped. + callback = mock.Mock(spec=[]) + bec_dispatcher.connect_slot(callback, "span-a", cb_info={"scan": "a"}) + bec_dispatcher.connect_slot(callback, "span-b", cb_info={"scan": "b"}) + wrappers = [slot for slot in bec_dispatcher._registered_slots if slot.cb is callback] + assert len(wrappers) == 2 + for wrapper in wrappers: + _queue_callback(wrapper) + + bec_dispatcher.disconnect_slot(callback, topics) + + for wrapper in wrappers: + _queue_callback(wrapper) # in-flight emissions after the release + qapp.processEvents() + callback.assert_not_called() + assert not any(slot.cb is callback for slot in bec_dispatcher._registered_slots)