1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Run the _testcapi module tests (tests for the Python/C API): by defn, 2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# these are all functions _testcapi exports whose name begins with 'test_'. 3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom __future__ import with_statement 5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport sys 6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport time 7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport random 8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport unittest 9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom test import test_support 10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeptry: 11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep import thread 12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep import threading 13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepexcept ImportError: 14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep thread = None 15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep threading = None 16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport _testcapi 17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep@unittest.skipUnless(threading, 'Threading required for this test.') 19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass TestPendingCalls(unittest.TestCase): 20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pendingcalls_submit(self, l, n): 22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def callback(): 23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #this function can be interrupted by thread switching so let's 24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #use an atomic operation 25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep l.append(None) 26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for i in range(n): 28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep time.sleep(random.random()*0.02) #0.01 secs on average 29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #try submitting callback until successful. 30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #rely on regular interrupt to flush queue if we are 31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #unsuccessful. 32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep while True: 33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if _testcapi._pending_threadfunc(callback): 34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep break; 35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pendingcalls_wait(self, l, n, context = None): 37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #now, stick around until l[0] has grown to 10 38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep count = 0; 39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep while len(l) != n: 40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #this busy loop is where we expect to be interrupted to 41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #run our callbacks. Note that callbacks are only run on the 42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #main thread 43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if False and test_support.verbose: 44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "(%i)"%(len(l),), 45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for i in xrange(1000): 46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep a = i*i 47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if context and not context.event.is_set(): 48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep continue 49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep count += 1 50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.assertTrue(count < 10000, 51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "timeout waiting for %i callbacks, got %i"%(n, len(l))) 52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if False and test_support.verbose: 53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "(%i)"%(len(l),) 54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def test_pendingcalls_threaded(self): 56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #do every callback on a separate thread 57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep n = 32 #total callbacks 58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep threads = [] 59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep class foo(object):pass 60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context = foo() 61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.l = [] 62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.n = 2 #submits per thread 63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.nThreads = n // context.n 64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.nFinished = 0 65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.lock = threading.Lock() 66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.event = threading.Event() 67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for i in range(context.nThreads): 69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t = threading.Thread(target=self.pendingcalls_thread, args = (context,)) 70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t.start() 71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep threads.append(t) 72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.pendingcalls_wait(context.l, n, context) 74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for t in threads: 76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t.join() 77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pendingcalls_thread(self, context): 79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.pendingcalls_submit(context.l, context.n) 81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep finally: 82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep with context.lock: 83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.nFinished += 1 84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep nFinished = context.nFinished 85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if False and test_support.verbose: 86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "finished threads: ", nFinished 87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if nFinished == context.nThreads: 88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context.event.set() 89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def test_pendingcalls_non_threaded(self): 91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #again, just using the main thread, likely they will all be dispatched at 92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #once. It is ok to ask for too many, because we loop until we find a slot. 93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #the loop can be interrupted to dispatch. 94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep #there are only 32 dispatch slots, so we go for twice that! 95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep l = [] 96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep n = 64 97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.pendingcalls_submit(l, n) 98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.pendingcalls_wait(l, n) 99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep@unittest.skipUnless(threading and thread, 'Threading required for this test.') 102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass TestThreadState(unittest.TestCase): 103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep @test_support.reap_threads 105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def test_thread_state(self): 106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # some extra thread-state tests driven via _testcapi 107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def target(): 108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep idents = [] 109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def callback(): 111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep idents.append(thread.get_ident()) 112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _testcapi._test_thread_state(callback) 114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep a = b = callback 115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep time.sleep(1) 116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # Check our main thread is in the list exactly 3 times. 117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.assertEqual(idents.count(thread.get_ident()), 3, 118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "Couldn't find main thread correctly in the list") 119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep target() 121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t = threading.Thread(target=target) 122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t.start() 123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t.join() 124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef test_main(): 127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for name in dir(_testcapi): 128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if name.startswith('test_'): 129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep test = getattr(_testcapi, name) 130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if test_support.verbose: 131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "internal", name 132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep test() 134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except _testcapi.error: 135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise test_support.TestFailed, sys.exc_info()[1] 136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep test_support.run_unittest(TestPendingCalls, TestThreadState) 138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepif __name__ == "__main__": 140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep test_main() 141