summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/signals/tests.py41
1 files changed, 25 insertions, 16 deletions
diff --git a/tests/signals/tests.py b/tests/signals/tests.py
index e304424eb8..ea2fe39fb8 100644
--- a/tests/signals/tests.py
+++ b/tests/signals/tests.py
@@ -1,4 +1,5 @@
import contextvars
+import gc
from inspect import markcoroutinefunction
from unittest import mock
@@ -14,26 +15,34 @@ from .models import Author, Book, Car, Page, Person
class BaseSignalSetup:
+ def _signal_counts(self):
+ # Clear dead receivers before counting.
+ counts = []
+ for signal in (
+ signals.pre_save,
+ signals.post_save,
+ signals.pre_delete,
+ signals.post_delete,
+ ):
+ with signal.lock:
+ signal._clear_dead_receivers()
+ counts.append(len(signal.receivers))
+ return tuple(counts)
+
def setUp(self):
- # Save up the number of connected signals so that we can check at the
- # end that all the signals we register get properly unregistered
- # (#9989)
- self.pre_signals = (
- len(signals.pre_save.receivers),
- len(signals.post_save.receivers),
- len(signals.pre_delete.receivers),
- len(signals.post_delete.receivers),
- )
+ # The count comparison in tearDown() is a regression check for
+ # Signal.disconnect() failing to remove entries (#9989). Collect first
+ # so the baseline contains only reachable receivers; a receiver
+ # connected elsewhere in the suite and then garbage-collected could
+ # linger as a dead weakref, inflating the count (#29187). No collection
+ # in tearDown(): a weak receiver kept alive by a cycle should be
+ # counted, to catch a forgotten disconnect.
+ gc.collect()
+ self.pre_signals = self._signal_counts()
def tearDown(self):
# All our signals got disconnected properly.
- post_signals = (
- len(signals.pre_save.receivers),
- len(signals.post_save.receivers),
- len(signals.pre_delete.receivers),
- len(signals.post_delete.receivers),
- )
- self.assertEqual(self.pre_signals, post_signals)
+ self.assertEqual(self.pre_signals, self._signal_counts())
class SignalTests(BaseSignalSetup, TestCase):