"""What the expiry sweep finds after a connection has already gone. A plain request is answered and the connection closed by http_senddata, not by the sweep. If that path leaves the descriptor's slot behind, the sweep walks into it once the client timeout has passed and frees a cookie that is already gone. Under the sanitizer build that is reported, and teardown turns it into a failure. The two numbers below mirror OT_CLIENT_TIMEOUT and OT_CLIENT_TIMEOUT_CHECKINTERVAL in FEATURES_integration. """ import time import unittest from harness import TrackerTestCase CLIENT_TIMEOUT = 5 CHECK_INTERVAL = 1 class ExpirySweep(TrackerTestCase): def test_an_answered_request_leaves_nothing_behind(self): info_hash = self.hash_for("expiry-sweep") self.assertEqual(self.tracker.announce(info_hash)[b"complete"], 1) # Long enough for the slot to expire and for a sweep to visit it time.sleep(CLIENT_TIMEOUT + 3 * CHECK_INTERVAL) self.assertEqual(self.tracker.torrent_count(), 1, "the tracker stopped serving while sweeping") def test_a_connection_that_never_speaks_is_swept(self): """The other side of it: a slot that really is live must still go.""" import socket idle = socket.create_connection(("127.0.0.1", self.tracker.port), timeout=5) try: time.sleep(CLIENT_TIMEOUT + 3 * CHECK_INTERVAL) idle.settimeout(5) self.assertEqual(idle.recv(64), b"", "the tracker held a connection that never sent a request") finally: idle.close()