blob: a86f86bd5f6fb4eed1c78ea64f130e85099cdcf6 [file] [log] [blame]
Christian Heimesdd15f6c2008-03-16 00:07:10 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Georg Brandl2067bfd2008-05-25 13:05:15 +00005import _thread as thread
Guido van Rossumcc544171994-04-14 20:28:41 +00006import time
7
Antoine Pitrou959f3e52009-11-09 16:52:46 +00008from test import lock_tests
Guido van Rossumcc544171994-04-14 20:28:41 +00009
Christian Heimesdd15f6c2008-03-16 00:07:10 +000010NUMTASKS = 10
11NUMTRIPS = 3
Guido van Rossumd3b68421994-05-23 12:17:36 +000012
Christian Heimesb186d002008-03-18 15:15:01 +000013_print_mutex = thread.allocate_lock()
14
Christian Heimesdd15f6c2008-03-16 00:07:10 +000015def verbose_print(arg):
16 """Helper function for printing out debugging output."""
Benjamin Petersonee8712c2008-05-20 21:35:26 +000017 if support.verbose:
Christian Heimesb186d002008-03-18 15:15:01 +000018 with _print_mutex:
19 print(arg)
Guido van Rossumcc544171994-04-14 20:28:41 +000020
Christian Heimesdd15f6c2008-03-16 00:07:10 +000021class BasicThreadTest(unittest.TestCase):
Guido van Rossumcc544171994-04-14 20:28:41 +000022
Christian Heimesdd15f6c2008-03-16 00:07:10 +000023 def setUp(self):
24 self.done_mutex = thread.allocate_lock()
25 self.done_mutex.acquire()
26 self.running_mutex = thread.allocate_lock()
27 self.random_mutex = thread.allocate_lock()
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000028 self.created = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +000029 self.running = 0
30 self.next_ident = 0
Guido van Rossumcc544171994-04-14 20:28:41 +000031
Guido van Rossumd3b68421994-05-23 12:17:36 +000032
Christian Heimesdd15f6c2008-03-16 00:07:10 +000033class ThreadRunningTests(BasicThreadTest):
34
35 def newtask(self):
36 with self.running_mutex:
37 self.next_ident += 1
38 verbose_print("creating task %s" % self.next_ident)
39 thread.start_new_thread(self.task, (self.next_ident,))
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000040 self.created += 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +000041 self.running += 1
42
43 def task(self, ident):
44 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +000045 delay = random.random() / 10000.0
46 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +000047 time.sleep(delay)
48 verbose_print("task %s done" % ident)
49 with self.running_mutex:
50 self.running -= 1
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000051 if self.created == NUMTASKS and self.running == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +000052 self.done_mutex.release()
53
54 def test_starting_threads(self):
55 # Basic test for thread creation.
56 for i in range(NUMTASKS):
57 self.newtask()
58 verbose_print("waiting for tasks to complete...")
59 self.done_mutex.acquire()
60 verbose_print("all tasks done")
61
62 def test_stack_size(self):
63 # Various stack size tests.
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000064 self.assertEqual(thread.stack_size(), 0, "intial stack size is not 0")
Christian Heimesdd15f6c2008-03-16 00:07:10 +000065
66 thread.stack_size(0)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000067 self.assertEqual(thread.stack_size(), 0, "stack_size not reset to default")
Christian Heimesdd15f6c2008-03-16 00:07:10 +000068
69 if os.name not in ("nt", "os2", "posix"):
70 return
71
72 tss_supported = True
73 try:
74 thread.stack_size(4096)
75 except ValueError:
76 verbose_print("caught expected ValueError setting "
77 "stack_size(4096)")
78 except thread.error:
79 tss_supported = False
80 verbose_print("platform does not support changing thread stack "
81 "size")
82
83 if tss_supported:
84 fail_msg = "stack_size(%d) failed - should succeed"
85 for tss in (262144, 0x100000, 0):
86 thread.stack_size(tss)
Ezio Melotti19f2aeb2010-11-21 01:30:29 +000087 self.assertEqual(thread.stack_size(), tss, fail_msg % tss)
Christian Heimesdd15f6c2008-03-16 00:07:10 +000088 verbose_print("successfully set stack_size(%d)" % tss)
89
90 for tss in (262144, 0x100000):
91 verbose_print("trying stack_size = (%d)" % tss)
92 self.next_ident = 0
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000093 self.created = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +000094 for i in range(NUMTASKS):
95 self.newtask()
96
97 verbose_print("waiting for all tasks to complete")
98 self.done_mutex.acquire()
99 verbose_print("all tasks done")
100
101 thread.stack_size(0)
102
103
104class Barrier:
105 def __init__(self, num_threads):
106 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000107 self.waiting = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000108 self.checkin_mutex = thread.allocate_lock()
109 self.checkout_mutex = thread.allocate_lock()
110 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000111
Fred Drake004d5e62000-10-23 17:22:08 +0000112 def enter(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000113 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000114 self.waiting = self.waiting + 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000115 if self.waiting == self.num_threads:
116 self.waiting = self.num_threads - 1
117 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000118 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000119 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000120
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000121 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000122 self.waiting = self.waiting - 1
123 if self.waiting == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000124 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000125 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000126 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000127
Guido van Rossumd3b68421994-05-23 12:17:36 +0000128
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000129class BarrierTest(BasicThreadTest):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000130
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000131 def test_barrier(self):
132 self.bar = Barrier(NUMTASKS)
133 self.running = NUMTASKS
134 for i in range(NUMTASKS):
135 thread.start_new_thread(self.task2, (i,))
136 verbose_print("waiting for tasks to end")
137 self.done_mutex.acquire()
138 verbose_print("tasks done")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000139
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000140 def task2(self, ident):
141 for i in range(NUMTRIPS):
142 if ident == 0:
143 # give it a good chance to enter the next
144 # barrier before the others are all out
145 # of the current one
Christian Heimesb186d002008-03-18 15:15:01 +0000146 delay = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000147 else:
148 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +0000149 delay = random.random() / 10000.0
150 verbose_print("task %s will run for %sus" %
151 (ident, round(delay * 1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000152 time.sleep(delay)
153 verbose_print("task %s entering %s" % (ident, i))
154 self.bar.enter()
155 verbose_print("task %s leaving barrier" % ident)
156 with self.running_mutex:
157 self.running -= 1
158 # Must release mutex before releasing done, else the main thread can
159 # exit and set mutex to None as part of global teardown; then
160 # mutex.release() raises AttributeError.
161 finished = self.running == 0
162 if finished:
163 self.done_mutex.release()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000164
Antoine Pitrou959f3e52009-11-09 16:52:46 +0000165class LockTests(lock_tests.LockTests):
166 locktype = thread.allocate_lock
167
168
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000169def test_main():
Antoine Pitrou959f3e52009-11-09 16:52:46 +0000170 support.run_unittest(ThreadRunningTests, BarrierTest, LockTests)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000171
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000172if __name__ == "__main__":
173 test_main()