"""That every thread the tracker starts also ends when it is asked to stop. The rest of the suite stops a tracker too, so a thread left behind already shows up in teardown as the complaint that the tracker had to be killed. These ask for the arrangements that park a thread in a blocking read in the first place, and they time the exit, because a reader woken only by its own receive timeout passes a correctness check while taking a second over it. """ import time import unittest from harness import Tracker, TrackerTestCase # Generous enough for a platform where shutting the socket down does not wake # the reader and the receive timeout has to expire, tight enough that a reader # which is never woken at all fails instead of hanging the suite PATIENCE = 3.0 def time_the_exit(extra_config): tracker = Tracker(extra_config) try: # Serve one request of each kind first, so the threads that are about # to be joined have actually run tracker.announce(b"shutdown-probe\0\0\0\0\0\0") sock, connection_id = tracker.udp_connect() tracker.udp_announce(sock, connection_id, b"shutdown-probe\0\0\0\0\0\0") sock.close() started = time.time() complaints = tracker.stop() return time.time() - started, complaints finally: tracker._cleanup() class UdpWorkers(TrackerTestCase): config = "listen.udp.workers 8\n" def test_announce_reaches_one_of_eight_workers(self): """Keeps the workers from being merely started and never used.""" sock, connection_id = self.tracker.udp_connect() answer = self.tracker.udp_announce(sock, connection_id, self.hash_for("eight-workers")) sock.close() self.assertEqual(answer["seeders"], 1) class ShutdownEndsEveryThread(unittest.TestCase): def test_eight_udp_workers_are_joined(self): took, complaints = time_the_exit("listen.udp.workers 8\n") self.assertEqual(complaints, [], "the tracker reported:\n" + "\n".join(complaints)) self.assertLess(took, PATIENCE, "stopping eight udp workers took %.1f s" % took) def test_udp_in_the_event_loop_still_stops(self): """Worker count zero leaves no thread to join, which must also work.""" took, complaints = time_the_exit("listen.udp.workers 0\n") self.assertEqual(complaints, [], "the tracker reported:\n" + "\n".join(complaints)) self.assertLess(took, PATIENCE, "stopping without workers took %.1f s" % took)