Skip to content

Commit 9dda0c9

Browse files
committed
[merge from 3.5] Issue11551 - Increase the test coverage of _dummy_thread module to 100%.
Initial patch contributed by Denver Coneybeare.
2 parents 7f9eb6e + 82733fa commit 9dda0c9

File tree

1 file changed

+115
-41
lines changed

1 file changed

+115
-41
lines changed

Lib/test/test_dummy_thread.py

Lines changed: 115 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
"""Generic thread tests.
2-
3-
Meant to be used by dummy_thread and thread. To allow for different modules
4-
to be used, test_main() can be called with the module to use as the thread
5-
implementation as its sole argument.
6-
7-
"""
81
import _dummy_thread as _thread
92
import time
103
import queue
114
import random
125
import unittest
136
from test import support
7+
from unittest import mock
8+
9+
DELAY = 0
1410

15-
DELAY = 0 # Set > 0 when testing a module other than _dummy_thread, such as
16-
# the '_thread' module.
1711

1812
class LockTests(unittest.TestCase):
1913
"""Test lock objects."""
@@ -34,6 +28,12 @@ def test_release(self):
3428
self.assertFalse(self.lock.locked(),
3529
"Lock object did not release properly.")
3630

31+
def test_LockType_context_manager(self):
32+
with _thread.LockType():
33+
pass
34+
self.assertFalse(self.lock.locked(),
35+
"Acquired Lock was not released")
36+
3737
def test_improper_release(self):
3838
#Make sure release of an unlocked thread raises RuntimeError
3939
self.assertRaises(RuntimeError, self.lock.release)
@@ -83,39 +83,72 @@ def delay_unlock(to_unlock, delay):
8383
self.assertGreaterEqual(end_time - start_time, DELAY,
8484
"Blocking by unconditional acquiring failed.")
8585

86+
@mock.patch('time.sleep')
87+
def test_acquire_timeout(self, mock_sleep):
88+
"""Test invoking acquire() with a positive timeout when the lock is
89+
already acquired. Ensure that time.sleep() is invoked with the given
90+
timeout and that False is returned."""
91+
92+
self.lock.acquire()
93+
retval = self.lock.acquire(waitflag=0, timeout=1)
94+
self.assertTrue(mock_sleep.called)
95+
mock_sleep.assert_called_once_with(1)
96+
self.assertEqual(retval, False)
97+
98+
def test_lock_representation(self):
99+
self.lock.acquire()
100+
self.assertIn("locked", repr(self.lock))
101+
self.lock.release()
102+
self.assertIn("unlocked", repr(self.lock))
103+
104+
86105
class MiscTests(unittest.TestCase):
87106
"""Miscellaneous tests."""
88107

89108
def test_exit(self):
90-
#Make sure _thread.exit() raises SystemExit
91109
self.assertRaises(SystemExit, _thread.exit)
92110

93111
def test_ident(self):
94-
#Test sanity of _thread.get_ident()
95112
self.assertIsInstance(_thread.get_ident(), int,
96113
"_thread.get_ident() returned a non-integer")
97114
self.assertNotEqual(_thread.get_ident(), 0,
98115
"_thread.get_ident() returned 0")
99116

100117
def test_LockType(self):
101-
#Make sure _thread.LockType is the same type as _thread.allocate_locke()
102118
self.assertIsInstance(_thread.allocate_lock(), _thread.LockType,
103119
"_thread.LockType is not an instance of what "
104120
"is returned by _thread.allocate_lock()")
105121

122+
def test_set_sentinel(self):
123+
self.assertIsInstance(_thread._set_sentinel(), _thread.LockType,
124+
"_thread._set_sentinel() did not return a "
125+
"LockType instance.")
126+
106127
def test_interrupt_main(self):
107128
#Calling start_new_thread with a function that executes interrupt_main
108129
# should raise KeyboardInterrupt upon completion.
109130
def call_interrupt():
110131
_thread.interrupt_main()
111-
self.assertRaises(KeyboardInterrupt, _thread.start_new_thread,
112-
call_interrupt, tuple())
132+
133+
self.assertRaises(KeyboardInterrupt,
134+
_thread.start_new_thread,
135+
call_interrupt,
136+
tuple())
113137

114138
def test_interrupt_in_main(self):
115-
# Make sure that if interrupt_main is called in main threat that
116-
# KeyboardInterrupt is raised instantly.
117139
self.assertRaises(KeyboardInterrupt, _thread.interrupt_main)
118140

141+
def test_stack_size_None(self):
142+
retval = _thread.stack_size(None)
143+
self.assertEqual(retval, 0)
144+
145+
def test_stack_size_not_None(self):
146+
with self.assertRaises(_thread.error) as cm:
147+
_thread.stack_size("")
148+
self.assertEqual(cm.exception.args[0],
149+
"setting thread stack size not supported")
150+
151+
119152
class ThreadTests(unittest.TestCase):
120153
"""Test thread creation."""
121154

@@ -129,31 +162,43 @@ def arg_tester(queue, arg1=False, arg2=False):
129162
_thread.start_new_thread(arg_tester, (testing_queue, True, True))
130163
result = testing_queue.get()
131164
self.assertTrue(result[0] and result[1],
132-
"Argument passing for thread creation using tuple failed")
133-
_thread.start_new_thread(arg_tester, tuple(), {'queue':testing_queue,
134-
'arg1':True, 'arg2':True})
165+
"Argument passing for thread creation "
166+
"using tuple failed")
167+
168+
_thread.start_new_thread(
169+
arg_tester,
170+
tuple(),
171+
{'queue':testing_queue, 'arg1':True, 'arg2':True})
172+
135173
result = testing_queue.get()
136174
self.assertTrue(result[0] and result[1],
137-
"Argument passing for thread creation using kwargs failed")
138-
_thread.start_new_thread(arg_tester, (testing_queue, True), {'arg2':True})
175+
"Argument passing for thread creation "
176+
"using kwargs failed")
177+
178+
_thread.start_new_thread(
179+
arg_tester,
180+
(testing_queue, True),
181+
{'arg2':True})
182+
139183
result = testing_queue.get()
140184
self.assertTrue(result[0] and result[1],
141185
"Argument passing for thread creation using both tuple"
142186
" and kwargs failed")
143187

144-
def test_multi_creation(self):
145-
#Make sure multiple threads can be created.
188+
def test_multi_thread_creation(self):
146189
def queue_mark(queue, delay):
147-
"""Wait for ``delay`` seconds and then put something into ``queue``"""
148190
time.sleep(delay)
149191
queue.put(_thread.get_ident())
150192

151193
thread_count = 5
152194
testing_queue = queue.Queue(thread_count)
195+
153196
if support.verbose:
154197
print()
155-
print("*** Testing multiple thread creation "\
156-
"(will take approx. %s to %s sec.) ***" % (DELAY, thread_count))
198+
print("*** Testing multiple thread creation "
199+
"(will take approx. %s to %s sec.) ***" % (
200+
DELAY, thread_count))
201+
157202
for count in range(thread_count):
158203
if DELAY:
159204
local_delay = round(random.random(), 1)
@@ -165,18 +210,47 @@ def queue_mark(queue, delay):
165210
if support.verbose:
166211
print('done')
167212
self.assertEqual(testing_queue.qsize(), thread_count,
168-
"Not all %s threads executed properly after %s sec." %
169-
(thread_count, DELAY))
170-
171-
def test_main(imported_module=None):
172-
global _thread, DELAY
173-
if imported_module:
174-
_thread = imported_module
175-
DELAY = 2
176-
if support.verbose:
177-
print()
178-
print("*** Using %s as _thread module ***" % _thread)
179-
support.run_unittest(LockTests, MiscTests, ThreadTests)
180-
181-
if __name__ == '__main__':
182-
test_main()
213+
"Not all %s threads executed properly "
214+
"after %s sec." % (thread_count, DELAY))
215+
216+
def test_args_not_tuple(self):
217+
"""
218+
Test invoking start_new_thread() with a non-tuple value for "args".
219+
Expect TypeError with a meaningful error message to be raised.
220+
"""
221+
with self.assertRaises(TypeError) as cm:
222+
_thread.start_new_thread(mock.Mock(), [])
223+
self.assertEqual(cm.exception.args[0], "2nd arg must be a tuple")
224+
225+
def test_kwargs_not_dict(self):
226+
"""
227+
Test invoking start_new_thread() with a non-dict value for "kwargs".
228+
Expect TypeError with a meaningful error message to be raised.
229+
"""
230+
with self.assertRaises(TypeError) as cm:
231+
_thread.start_new_thread(mock.Mock(), tuple(), kwargs=[])
232+
self.assertEqual(cm.exception.args[0], "3rd arg must be a dict")
233+
234+
def test_SystemExit(self):
235+
"""
236+
Test invoking start_new_thread() with a function that raises
237+
SystemExit.
238+
The exception should be discarded.
239+
"""
240+
func = mock.Mock(side_effect=SystemExit())
241+
try:
242+
_thread.start_new_thread(func, tuple())
243+
except SystemExit:
244+
self.fail("start_new_thread raised SystemExit.")
245+
246+
@mock.patch('traceback.print_exc')
247+
def test_RaiseException(self, mock_print_exc):
248+
"""
249+
Test invoking start_new_thread() with a function that raises exception.
250+
251+
The exception should be discarded and the traceback should be printed
252+
via traceback.print_exc()
253+
"""
254+
func = mock.Mock(side_effect=Exception)
255+
_thread.start_new_thread(func, tuple())
256+
self.assertTrue(mock_print_exc.called)

0 commit comments

Comments
 (0)