mirror of
https://github.com/python/cpython.git
synced 2025-09-30 12:21:51 +00:00
[3.6] bpo-31234: Join threads in tests (#3589)
* bpo-31234: Join threads in tests (#3572) Call thread.join() on threads to prevent the "dangling threads" warning. (cherry picked from commit18e95b4176
) * bpo-31234: Join threads in test_hashlib (#3573) * bpo-31234: Join threads in test_hashlib Use thread.join() to wait until the parallel hash tasks complete rather than using events. Calling thread.join() prevent "dangling thread" warnings. * test_hashlib: minor PEP 8 coding style fixes (cherry picked from commit8dcf22f442
) * bpo-31234: Join threads in test_threading (#3579) Call thread.join() to prevent the "dangling thread" warning. (cherry picked from commitb8c7be2c52
) * bpo-31234: Join threads in test_queue (#3586) Call thread.join() to prevent the "dangling thread" warning. (cherry picked from commit167cbde50a
) * bpo-31234: Join timers in test_threading (#3598) Call the .join() method of threading.Timer timers to prevent the "threading_cleanup() failed to cleanup 1 threads" warning. (cherry picked from commitda3e5cf961
)
This commit is contained in:
parent
4d72945a28
commit
2c1c2ca254
7 changed files with 58 additions and 36 deletions
|
@ -776,6 +776,7 @@ class FutureTests(BaseTestCase):
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
self.assertEqual(f1.result(timeout=5), 42)
|
self.assertEqual(f1.result(timeout=5), 42)
|
||||||
|
t.join()
|
||||||
|
|
||||||
def test_result_with_cancel(self):
|
def test_result_with_cancel(self):
|
||||||
# TODO(brian@sweetapp.com): This test is timing dependent.
|
# TODO(brian@sweetapp.com): This test is timing dependent.
|
||||||
|
@ -789,6 +790,7 @@ class FutureTests(BaseTestCase):
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
self.assertRaises(futures.CancelledError, f1.result, timeout=5)
|
self.assertRaises(futures.CancelledError, f1.result, timeout=5)
|
||||||
|
t.join()
|
||||||
|
|
||||||
def test_exception_with_timeout(self):
|
def test_exception_with_timeout(self):
|
||||||
self.assertRaises(futures.TimeoutError,
|
self.assertRaises(futures.TimeoutError,
|
||||||
|
@ -817,6 +819,7 @@ class FutureTests(BaseTestCase):
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
self.assertTrue(isinstance(f1.exception(timeout=5), OSError))
|
self.assertTrue(isinstance(f1.exception(timeout=5), OSError))
|
||||||
|
t.join()
|
||||||
|
|
||||||
@test.support.reap_threads
|
@test.support.reap_threads
|
||||||
def test_main():
|
def test_main():
|
||||||
|
|
|
@ -1614,6 +1614,9 @@ class ThreadingTest(unittest.TestCase):
|
||||||
for sig in Signals[self.decimal]:
|
for sig in Signals[self.decimal]:
|
||||||
self.assertFalse(DefaultContext.flags[sig])
|
self.assertFalse(DefaultContext.flags[sig])
|
||||||
|
|
||||||
|
th1.join()
|
||||||
|
th2.join()
|
||||||
|
|
||||||
DefaultContext.prec = save_prec
|
DefaultContext.prec = save_prec
|
||||||
DefaultContext.Emax = save_emax
|
DefaultContext.Emax = save_emax
|
||||||
DefaultContext.Emin = save_emin
|
DefaultContext.Emin = save_emin
|
||||||
|
|
|
@ -753,25 +753,25 @@ class HashLibTestCase(unittest.TestCase):
|
||||||
data = smallest_data * 200000
|
data = smallest_data * 200000
|
||||||
expected_hash = hashlib.sha1(data*num_threads).hexdigest()
|
expected_hash = hashlib.sha1(data*num_threads).hexdigest()
|
||||||
|
|
||||||
def hash_in_chunks(chunk_size, event):
|
def hash_in_chunks(chunk_size):
|
||||||
index = 0
|
index = 0
|
||||||
while index < len(data):
|
while index < len(data):
|
||||||
hasher.update(data[index:index + chunk_size])
|
hasher.update(data[index:index + chunk_size])
|
||||||
index += chunk_size
|
index += chunk_size
|
||||||
event.set()
|
|
||||||
|
|
||||||
events = []
|
threads = []
|
||||||
for threadnum in range(num_threads):
|
for threadnum in range(num_threads):
|
||||||
chunk_size = len(data) // (10 ** threadnum)
|
chunk_size = len(data) // (10 ** threadnum)
|
||||||
self.assertGreater(chunk_size, 0)
|
self.assertGreater(chunk_size, 0)
|
||||||
self.assertEqual(chunk_size % len(smallest_data), 0)
|
self.assertEqual(chunk_size % len(smallest_data), 0)
|
||||||
event = threading.Event()
|
thread = threading.Thread(target=hash_in_chunks,
|
||||||
events.append(event)
|
args=(chunk_size,))
|
||||||
threading.Thread(target=hash_in_chunks,
|
threads.append(thread)
|
||||||
args=(chunk_size, event)).start()
|
|
||||||
|
|
||||||
for event in events:
|
for thread in threads:
|
||||||
event.wait()
|
thread.start()
|
||||||
|
for thread in threads:
|
||||||
|
thread.join()
|
||||||
|
|
||||||
self.assertEqual(expected_hash, hasher.hexdigest())
|
self.assertEqual(expected_hash, hasher.hexdigest())
|
||||||
|
|
||||||
|
|
|
@ -46,28 +46,27 @@ class _TriggerThread(threading.Thread):
|
||||||
|
|
||||||
class BlockingTestMixin:
|
class BlockingTestMixin:
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.t = None
|
|
||||||
|
|
||||||
def do_blocking_test(self, block_func, block_args, trigger_func, trigger_args):
|
def do_blocking_test(self, block_func, block_args, trigger_func, trigger_args):
|
||||||
self.t = _TriggerThread(trigger_func, trigger_args)
|
thread = _TriggerThread(trigger_func, trigger_args)
|
||||||
self.t.start()
|
thread.start()
|
||||||
|
try:
|
||||||
self.result = block_func(*block_args)
|
self.result = block_func(*block_args)
|
||||||
# If block_func returned before our thread made the call, we failed!
|
# If block_func returned before our thread made the call, we failed!
|
||||||
if not self.t.startedEvent.is_set():
|
if not thread.startedEvent.is_set():
|
||||||
self.fail("blocking function '%r' appeared not to block" %
|
self.fail("blocking function '%r' appeared not to block" %
|
||||||
block_func)
|
block_func)
|
||||||
self.t.join(10) # make sure the thread terminates
|
return self.result
|
||||||
if self.t.is_alive():
|
finally:
|
||||||
|
thread.join(10) # make sure the thread terminates
|
||||||
|
if thread.is_alive():
|
||||||
self.fail("trigger function '%r' appeared to not return" %
|
self.fail("trigger function '%r' appeared to not return" %
|
||||||
trigger_func)
|
trigger_func)
|
||||||
return self.result
|
|
||||||
|
|
||||||
# Call this instead if block_func is supposed to raise an exception.
|
# Call this instead if block_func is supposed to raise an exception.
|
||||||
def do_exceptional_blocking_test(self,block_func, block_args, trigger_func,
|
def do_exceptional_blocking_test(self,block_func, block_args, trigger_func,
|
||||||
trigger_args, expected_exception_class):
|
trigger_args, expected_exception_class):
|
||||||
self.t = _TriggerThread(trigger_func, trigger_args)
|
thread = _TriggerThread(trigger_func, trigger_args)
|
||||||
self.t.start()
|
thread.start()
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
block_func(*block_args)
|
block_func(*block_args)
|
||||||
|
@ -77,11 +76,11 @@ class BlockingTestMixin:
|
||||||
self.fail("expected exception of kind %r" %
|
self.fail("expected exception of kind %r" %
|
||||||
expected_exception_class)
|
expected_exception_class)
|
||||||
finally:
|
finally:
|
||||||
self.t.join(10) # make sure the thread terminates
|
thread.join(10) # make sure the thread terminates
|
||||||
if self.t.is_alive():
|
if thread.is_alive():
|
||||||
self.fail("trigger function '%r' appeared to not return" %
|
self.fail("trigger function '%r' appeared to not return" %
|
||||||
trigger_func)
|
trigger_func)
|
||||||
if not self.t.startedEvent.is_set():
|
if not thread.startedEvent.is_set():
|
||||||
self.fail("trigger thread ended but event never set")
|
self.fail("trigger thread ended but event never set")
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,8 +158,11 @@ class BaseQueueTestMixin(BlockingTestMixin):
|
||||||
|
|
||||||
def queue_join_test(self, q):
|
def queue_join_test(self, q):
|
||||||
self.cum = 0
|
self.cum = 0
|
||||||
|
threads = []
|
||||||
for i in (0,1):
|
for i in (0,1):
|
||||||
threading.Thread(target=self.worker, args=(q,)).start()
|
thread = threading.Thread(target=self.worker, args=(q,))
|
||||||
|
thread.start()
|
||||||
|
threads.append(thread)
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
q.put(i)
|
q.put(i)
|
||||||
q.join()
|
q.join()
|
||||||
|
@ -169,6 +171,8 @@ class BaseQueueTestMixin(BlockingTestMixin):
|
||||||
for i in (0,1):
|
for i in (0,1):
|
||||||
q.put(-1) # instruct the threads to close
|
q.put(-1) # instruct the threads to close
|
||||||
q.join() # verify that you can join twice
|
q.join() # verify that you can join twice
|
||||||
|
for thread in threads:
|
||||||
|
thread.join()
|
||||||
|
|
||||||
def test_queue_task_done(self):
|
def test_queue_task_done(self):
|
||||||
# Test to make sure a queue task completed successfully.
|
# Test to make sure a queue task completed successfully.
|
||||||
|
|
|
@ -604,7 +604,9 @@ class TooLongLineTests(unittest.TestCase):
|
||||||
self.sock.settimeout(15)
|
self.sock.settimeout(15)
|
||||||
self.port = support.bind_port(self.sock)
|
self.port = support.bind_port(self.sock)
|
||||||
servargs = (self.evt, self.respdata, self.sock)
|
servargs = (self.evt, self.respdata, self.sock)
|
||||||
threading.Thread(target=server, args=servargs).start()
|
thread = threading.Thread(target=server, args=servargs)
|
||||||
|
thread.start()
|
||||||
|
self.addCleanup(thread.join)
|
||||||
self.evt.wait()
|
self.evt.wait()
|
||||||
self.evt.clear()
|
self.evt.clear()
|
||||||
|
|
||||||
|
|
|
@ -575,6 +575,7 @@ class ThreadTests(BaseTestCase):
|
||||||
self.assertFalse(t.is_alive())
|
self.assertFalse(t.is_alive())
|
||||||
# And verify the thread disposed of _tstate_lock.
|
# And verify the thread disposed of _tstate_lock.
|
||||||
self.assertIsNone(t._tstate_lock)
|
self.assertIsNone(t._tstate_lock)
|
||||||
|
t.join()
|
||||||
|
|
||||||
def test_repr_stopped(self):
|
def test_repr_stopped(self):
|
||||||
# Verify that "stopped" shows up in repr(Thread) appropriately.
|
# Verify that "stopped" shows up in repr(Thread) appropriately.
|
||||||
|
@ -601,6 +602,7 @@ class ThreadTests(BaseTestCase):
|
||||||
break
|
break
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
self.assertIn(LOOKING_FOR, repr(t)) # we waited at least 5 seconds
|
self.assertIn(LOOKING_FOR, repr(t)) # we waited at least 5 seconds
|
||||||
|
t.join()
|
||||||
|
|
||||||
def test_BoundedSemaphore_limit(self):
|
def test_BoundedSemaphore_limit(self):
|
||||||
# BoundedSemaphore should raise ValueError if released too often.
|
# BoundedSemaphore should raise ValueError if released too often.
|
||||||
|
@ -915,6 +917,7 @@ class ThreadingExceptionTests(BaseTestCase):
|
||||||
thread = threading.Thread()
|
thread = threading.Thread()
|
||||||
thread.start()
|
thread.start()
|
||||||
self.assertRaises(RuntimeError, thread.start)
|
self.assertRaises(RuntimeError, thread.start)
|
||||||
|
thread.join()
|
||||||
|
|
||||||
def test_joining_current_thread(self):
|
def test_joining_current_thread(self):
|
||||||
current_thread = threading.current_thread()
|
current_thread = threading.current_thread()
|
||||||
|
@ -928,6 +931,7 @@ class ThreadingExceptionTests(BaseTestCase):
|
||||||
thread = threading.Thread()
|
thread = threading.Thread()
|
||||||
thread.start()
|
thread.start()
|
||||||
self.assertRaises(RuntimeError, setattr, thread, "daemon", True)
|
self.assertRaises(RuntimeError, setattr, thread, "daemon", True)
|
||||||
|
thread.join()
|
||||||
|
|
||||||
def test_releasing_unacquired_lock(self):
|
def test_releasing_unacquired_lock(self):
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
@ -1090,6 +1094,8 @@ class TimerTests(BaseTestCase):
|
||||||
self.callback_event.wait()
|
self.callback_event.wait()
|
||||||
self.assertEqual(len(self.callback_args), 2)
|
self.assertEqual(len(self.callback_args), 2)
|
||||||
self.assertEqual(self.callback_args, [((), {}), ((), {})])
|
self.assertEqual(self.callback_args, [((), {}), ((), {})])
|
||||||
|
timer1.join()
|
||||||
|
timer2.join()
|
||||||
|
|
||||||
def _callback_spy(self, *args, **kwargs):
|
def _callback_spy(self, *args, **kwargs):
|
||||||
self.callback_args.append((args[:], kwargs.copy()))
|
self.callback_args.append((args[:], kwargs.copy()))
|
||||||
|
|
|
@ -759,7 +759,9 @@ class BaseServerTestCase(unittest.TestCase):
|
||||||
self.evt = threading.Event()
|
self.evt = threading.Event()
|
||||||
# start server thread to handle requests
|
# start server thread to handle requests
|
||||||
serv_args = (self.evt, self.request_count, self.requestHandler)
|
serv_args = (self.evt, self.request_count, self.requestHandler)
|
||||||
threading.Thread(target=self.threadFunc, args=serv_args).start()
|
thread = threading.Thread(target=self.threadFunc, args=serv_args)
|
||||||
|
thread.start()
|
||||||
|
self.addCleanup(thread.join)
|
||||||
|
|
||||||
# wait for the server to be ready
|
# wait for the server to be ready
|
||||||
self.evt.wait()
|
self.evt.wait()
|
||||||
|
@ -1211,7 +1213,9 @@ class FailingServerTestCase(unittest.TestCase):
|
||||||
self.evt = threading.Event()
|
self.evt = threading.Event()
|
||||||
# start server thread to handle requests
|
# start server thread to handle requests
|
||||||
serv_args = (self.evt, 1)
|
serv_args = (self.evt, 1)
|
||||||
threading.Thread(target=http_server, args=serv_args).start()
|
thread = threading.Thread(target=http_server, args=serv_args)
|
||||||
|
thread.start()
|
||||||
|
self.addCleanup(thread.join)
|
||||||
|
|
||||||
# wait for the server to be ready
|
# wait for the server to be ready
|
||||||
self.evt.wait()
|
self.evt.wait()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue