blob: 4d2c06ef109489592da255db5c307f4b04f7584e [file] [log] [blame]
Brett Cannon66865d22008-03-13 20:27:00 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Brett Cannon66865d22008-03-13 20:27:00 +00004from test import test_support
Guido van Rossumcc544171994-04-14 20:28:41 +00005import thread
6import time
Gregory P. Smithc21d0cb2010-03-01 04:40:36 +00007import sys
Guido van Rossumcc544171994-04-14 20:28:41 +00008
Antoine Pitrouc747d3a2009-11-09 16:47:50 +00009from test import lock_tests
Guido van Rossumcc544171994-04-14 20:28:41 +000010
Brett Cannon66865d22008-03-13 20:27:00 +000011NUMTASKS = 10
12NUMTRIPS = 3
Guido van Rossumd3b68421994-05-23 12:17:36 +000013
Guido van Rossumcc544171994-04-14 20:28:41 +000014
Jeffrey Yasskina1458532008-03-18 04:56:06 +000015_print_mutex = thread.allocate_lock()
16
Brett Cannon66865d22008-03-13 20:27:00 +000017def verbose_print(arg):
18 """Helper function for printing out debugging output."""
19 if test_support.verbose:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000020 with _print_mutex:
21 print arg
Guido van Rossumcc544171994-04-14 20:28:41 +000022
Guido van Rossumcc544171994-04-14 20:28:41 +000023
Brett Cannon66865d22008-03-13 20:27:00 +000024class BasicThreadTest(unittest.TestCase):
Guido van Rossumd3b68421994-05-23 12:17:36 +000025
Brett Cannon66865d22008-03-13 20:27:00 +000026 def setUp(self):
27 self.done_mutex = thread.allocate_lock()
28 self.done_mutex.acquire()
29 self.running_mutex = thread.allocate_lock()
30 self.random_mutex = thread.allocate_lock()
Antoine Pitrouf75774b2009-10-27 12:32:18 +000031 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000032 self.running = 0
33 self.next_ident = 0
34
35
36class ThreadRunningTests(BasicThreadTest):
37
38 def newtask(self):
39 with self.running_mutex:
40 self.next_ident += 1
41 verbose_print("creating task %s" % self.next_ident)
42 thread.start_new_thread(self.task, (self.next_ident,))
Antoine Pitrouf75774b2009-10-27 12:32:18 +000043 self.created += 1
Brett Cannon66865d22008-03-13 20:27:00 +000044 self.running += 1
45
46 def task(self, ident):
47 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000048 delay = random.random() / 10000.0
49 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +000050 time.sleep(delay)
51 verbose_print("task %s done" % ident)
52 with self.running_mutex:
53 self.running -= 1
Antoine Pitrouf75774b2009-10-27 12:32:18 +000054 if self.created == NUMTASKS and self.running == 0:
Brett Cannon66865d22008-03-13 20:27:00 +000055 self.done_mutex.release()
56
57 def test_starting_threads(self):
58 # Basic test for thread creation.
59 for i in range(NUMTASKS):
60 self.newtask()
61 verbose_print("waiting for tasks to complete...")
62 self.done_mutex.acquire()
63 verbose_print("all tasks done")
64
65 def test_stack_size(self):
66 # Various stack size tests.
67 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
68
69 thread.stack_size(0)
70 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
71
72 if os.name not in ("nt", "os2", "posix"):
73 return
74
75 tss_supported = True
76 try:
77 thread.stack_size(4096)
78 except ValueError:
79 verbose_print("caught expected ValueError setting "
80 "stack_size(4096)")
81 except thread.error:
82 tss_supported = False
83 verbose_print("platform does not support changing thread stack "
84 "size")
85
86 if tss_supported:
87 fail_msg = "stack_size(%d) failed - should succeed"
88 for tss in (262144, 0x100000, 0):
89 thread.stack_size(tss)
90 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
91 verbose_print("successfully set stack_size(%d)" % tss)
92
93 for tss in (262144, 0x100000):
94 verbose_print("trying stack_size = (%d)" % tss)
95 self.next_ident = 0
Antoine Pitrouf75774b2009-10-27 12:32:18 +000096 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000097 for i in range(NUMTASKS):
98 self.newtask()
99
100 verbose_print("waiting for all tasks to complete")
101 self.done_mutex.acquire()
102 verbose_print("all tasks done")
103
104 thread.stack_size(0)
105
106
107class Barrier:
108 def __init__(self, num_threads):
109 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000110 self.waiting = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000111 self.checkin_mutex = thread.allocate_lock()
112 self.checkout_mutex = thread.allocate_lock()
113 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000114
Fred Drake004d5e62000-10-23 17:22:08 +0000115 def enter(self):
Brett Cannon66865d22008-03-13 20:27:00 +0000116 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000117 self.waiting = self.waiting + 1
Brett Cannon66865d22008-03-13 20:27:00 +0000118 if self.waiting == self.num_threads:
119 self.waiting = self.num_threads - 1
120 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000121 return
Brett Cannon66865d22008-03-13 20:27:00 +0000122 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000123
Brett Cannon66865d22008-03-13 20:27:00 +0000124 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000125 self.waiting = self.waiting - 1
126 if self.waiting == 0:
Brett Cannon66865d22008-03-13 20:27:00 +0000127 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000128 return
Brett Cannon66865d22008-03-13 20:27:00 +0000129 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000130
Guido van Rossumd3b68421994-05-23 12:17:36 +0000131
Brett Cannon66865d22008-03-13 20:27:00 +0000132class BarrierTest(BasicThreadTest):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000133
Brett Cannon66865d22008-03-13 20:27:00 +0000134 def test_barrier(self):
135 self.bar = Barrier(NUMTASKS)
136 self.running = NUMTASKS
137 for i in range(NUMTASKS):
138 thread.start_new_thread(self.task2, (i,))
139 verbose_print("waiting for tasks to end")
140 self.done_mutex.acquire()
141 verbose_print("tasks done")
Andrew MacIntyre92913322006-06-13 15:04:24 +0000142
Brett Cannon66865d22008-03-13 20:27:00 +0000143 def task2(self, ident):
144 for i in range(NUMTRIPS):
145 if ident == 0:
146 # give it a good chance to enter the next
147 # barrier before the others are all out
148 # of the current one
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000149 delay = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000150 else:
151 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000152 delay = random.random() / 10000.0
153 verbose_print("task %s will run for %sus" %
154 (ident, round(delay * 1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +0000155 time.sleep(delay)
156 verbose_print("task %s entering %s" % (ident, i))
157 self.bar.enter()
158 verbose_print("task %s leaving barrier" % ident)
159 with self.running_mutex:
160 self.running -= 1
161 # Must release mutex before releasing done, else the main thread can
162 # exit and set mutex to None as part of global teardown; then
163 # mutex.release() raises AttributeError.
164 finished = self.running == 0
165 if finished:
166 self.done_mutex.release()
Andrew MacIntyre92913322006-06-13 15:04:24 +0000167
Andrew MacIntyre92913322006-06-13 15:04:24 +0000168
Antoine Pitrouc747d3a2009-11-09 16:47:50 +0000169class LockTests(lock_tests.LockTests):
170 locktype = thread.allocate_lock
171
172
Gregory P. Smithc21d0cb2010-03-01 04:40:36 +0000173class TestForkInThread(unittest.TestCase):
174 def setUp(self):
175 self.read_fd, self.write_fd = os.pipe()
176
Gregory P. Smith6e064bd2010-03-01 06:03:44 +0000177 def _test_forkinthread(self):
Gregory P. Smithc21d0cb2010-03-01 04:40:36 +0000178 def thread1():
179 try:
180 pid = os.fork() # fork in a thread
181 except RuntimeError:
182 sys.exit(0) # exit the child
183
184 if pid == 0: # child
185 os.close(self.read_fd)
186 os.write(self.write_fd, "OK")
187 sys.exit(0)
188 else: # parent
189 os.close(self.write_fd)
190
191 thread.start_new_thread(thread1, ())
192 self.assertEqual(os.read(self.read_fd, 2), "OK",
193 "Unable to fork() in thread")
194
Gregory P. Smith31980982010-03-04 18:26:53 +0000195 if not sys.platform.startswith('win'):
Gregory P. Smith6e064bd2010-03-01 06:03:44 +0000196 test_forkinthread = _test_forkinthread
197
Gregory P. Smithc21d0cb2010-03-01 04:40:36 +0000198 def tearDown(self):
199 try:
200 os.close(self.read_fd)
201 except OSError:
202 pass
203
204 try:
205 os.close(self.write_fd)
206 except OSError:
207 pass
208
209
Brett Cannon66865d22008-03-13 20:27:00 +0000210def test_main():
Gregory P. Smithc21d0cb2010-03-01 04:40:36 +0000211 test_support.run_unittest(ThreadRunningTests, BarrierTest, LockTests,
212 TestForkInThread)
Andrew MacIntyre92913322006-06-13 15:04:24 +0000213
Brett Cannon66865d22008-03-13 20:27:00 +0000214if __name__ == "__main__":
215 test_main()