blob: ba7c38db27cf908f9b3820743d5129889a8d72e2 [file] [log] [blame]
Tim Petersd66595f2001-02-04 03:09:53 +00001# Run the _testcapi module tests (tests for the Python/C API): by defn,
Guido van Rossum361c5352001-04-13 17:03:04 +00002# these are all functions _testcapi exports whose name begins with 'test_'.
Tim Peters9ea17ac2001-02-02 05:57:15 +00003
Antoine Pitrou8e605772011-04-25 21:21:07 +02004import os
Antoine Pitrou2f828f22012-01-18 00:21:11 +01005import pickle
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +00006import random
7import subprocess
Martin v. Löwis6ce7ed22005-03-03 12:26:35 +00008import sys
Benjamin Petersona54c9092009-01-13 02:11:23 +00009import time
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000010import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +000011from test import support
Larry Hastingsfcafe432013-11-23 17:35:48 -080012from test.support import MISSING_C_DOCSTRINGS
Victor Stinner45df8202010-04-28 22:31:17 +000013try:
Stefan Krahfd24f9e2012-08-20 11:04:24 +020014 import _posixsubprocess
15except ImportError:
16 _posixsubprocess = None
17try:
Victor Stinner45df8202010-04-28 22:31:17 +000018 import threading
19except ImportError:
20 threading = None
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020021# Skip this test if the _testcapi module isn't available.
22_testcapi = support.import_module('_testcapi')
Tim Peters9ea17ac2001-02-02 05:57:15 +000023
Benjamin Petersona54c9092009-01-13 02:11:23 +000024
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000025def testfunction(self):
26 """some doc"""
27 return self
28
29class InstanceMethod:
30 id = _testcapi.instancemethod(id)
31 testfunction = _testcapi.instancemethod(testfunction)
32
33class CAPITest(unittest.TestCase):
34
35 def test_instancemethod(self):
36 inst = InstanceMethod()
37 self.assertEqual(id(inst), inst.id())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000038 self.assertTrue(inst.testfunction() is inst)
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000039 self.assertEqual(inst.testfunction.__doc__, testfunction.__doc__)
40 self.assertEqual(InstanceMethod.testfunction.__doc__, testfunction.__doc__)
41
42 InstanceMethod.testfunction.attribute = "test"
43 self.assertEqual(testfunction.attribute, "test")
44 self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test")
45
Stefan Krah0ca46242010-06-09 08:56:28 +000046 @unittest.skipUnless(threading, 'Threading required for this test.')
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000047 def test_no_FatalError_infinite_loop(self):
Antoine Pitrou77e904e2013-10-08 23:04:32 +020048 with support.SuppressCrashReport():
Ezio Melotti25a40452013-03-05 20:26:17 +020049 p = subprocess.Popen([sys.executable, "-c",
Ezio Melottie1857d92013-03-05 20:31:34 +020050 'import _testcapi;'
51 '_testcapi.crash_no_current_thread()'],
52 stdout=subprocess.PIPE,
53 stderr=subprocess.PIPE)
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000054 (out, err) = p.communicate()
55 self.assertEqual(out, b'')
56 # This used to cause an infinite loop.
Vinay Sajip73954042012-05-06 11:34:50 +010057 self.assertTrue(err.rstrip().startswith(
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000058 b'Fatal Python error:'
Vinay Sajip73954042012-05-06 11:34:50 +010059 b' PyThreadState_Get: no current thread'))
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000060
Antoine Pitrou915605c2011-02-24 20:53:48 +000061 def test_memoryview_from_NULL_pointer(self):
62 self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer)
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000063
Martin v. Löwisaa2efcb2012-04-19 14:33:43 +020064 def test_exc_info(self):
65 raised_exception = ValueError("5")
66 new_exc = TypeError("TEST")
67 try:
68 raise raised_exception
69 except ValueError as e:
70 tb = e.__traceback__
71 orig_sys_exc_info = sys.exc_info()
72 orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None)
73 new_sys_exc_info = sys.exc_info()
74 new_exc_info = _testcapi.set_exc_info(*orig_exc_info)
75 reset_sys_exc_info = sys.exc_info()
76
77 self.assertEqual(orig_exc_info[1], e)
78
79 self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb))
80 self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info)
81 self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info)
82 self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None))
83 self.assertSequenceEqual(new_sys_exc_info, new_exc_info)
84 else:
85 self.assertTrue(False)
86
Stefan Krahfd24f9e2012-08-20 11:04:24 +020087 @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
88 def test_seq_bytes_to_charp_array(self):
89 # Issue #15732: crash in _PySequence_BytesToCharpArray()
90 class Z(object):
91 def __len__(self):
92 return 1
93 self.assertRaises(TypeError, _posixsubprocess.fork_exec,
94 1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
Stefan Krah7cacd2e2012-08-21 08:16:09 +020095 # Issue #15736: overflow in _PySequence_BytesToCharpArray()
96 class Z(object):
97 def __len__(self):
98 return sys.maxsize
99 def __getitem__(self, i):
100 return b'x'
101 self.assertRaises(MemoryError, _posixsubprocess.fork_exec,
102 1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
Stefan Krahfd24f9e2012-08-20 11:04:24 +0200103
Stefan Krahdb579d72012-08-20 14:36:47 +0200104 @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
105 def test_subprocess_fork_exec(self):
106 class Z(object):
107 def __len__(self):
108 return 1
109
110 # Issue #15738: crash in subprocess_fork_exec()
111 self.assertRaises(TypeError, _posixsubprocess.fork_exec,
112 Z(),[b'1'],3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
113
Larry Hastingsfcafe432013-11-23 17:35:48 -0800114 @unittest.skipIf(MISSING_C_DOCSTRINGS,
115 "Signature information for builtins requires docstrings")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800116 def test_docstring_signature_parsing(self):
117
118 self.assertEqual(_testcapi.no_docstring.__doc__, None)
119 self.assertEqual(_testcapi.no_docstring.__text_signature__, None)
120
121 self.assertEqual(_testcapi.docstring_empty.__doc__, "")
122 self.assertEqual(_testcapi.docstring_empty.__text_signature__, None)
123
124 self.assertEqual(_testcapi.docstring_no_signature.__doc__,
125 "This docstring has no signature.")
126 self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None)
127
128 self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800129 "docstring_with_invalid_signature($module, /, boo)\n"
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800130 "\n"
131 "This docstring has an invalid signature."
132 )
133 self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None)
134
Larry Hastings2623c8c2014-02-08 22:15:29 -0800135 self.assertEqual(_testcapi.docstring_with_invalid_signature2.__doc__,
136 "docstring_with_invalid_signature2($module, /, boo)\n"
137 "\n"
138 "--\n"
139 "\n"
140 "This docstring also has an invalid signature."
141 )
142 self.assertEqual(_testcapi.docstring_with_invalid_signature2.__text_signature__, None)
143
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800144 self.assertEqual(_testcapi.docstring_with_signature.__doc__,
145 "This docstring has a valid signature.")
Larry Hastings2623c8c2014-02-08 22:15:29 -0800146 self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800147
148 self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800149 "\nThis docstring has a valid signature and some extra newlines.")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800150 self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800151 "($module, /, parameter)")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800152
153
Victor Stinner45df8202010-04-28 22:31:17 +0000154@unittest.skipUnless(threading, 'Threading required for this test.')
Benjamin Petersona54c9092009-01-13 02:11:23 +0000155class TestPendingCalls(unittest.TestCase):
156
157 def pendingcalls_submit(self, l, n):
158 def callback():
159 #this function can be interrupted by thread switching so let's
160 #use an atomic operation
161 l.append(None)
162
163 for i in range(n):
164 time.sleep(random.random()*0.02) #0.01 secs on average
165 #try submitting callback until successful.
166 #rely on regular interrupt to flush queue if we are
167 #unsuccessful.
168 while True:
169 if _testcapi._pending_threadfunc(callback):
170 break;
171
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000172 def pendingcalls_wait(self, l, n, context = None):
Benjamin Petersona54c9092009-01-13 02:11:23 +0000173 #now, stick around until l[0] has grown to 10
174 count = 0;
175 while len(l) != n:
176 #this busy loop is where we expect to be interrupted to
177 #run our callbacks. Note that callbacks are only run on the
178 #main thread
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000179 if False and support.verbose:
Benjamin Petersona54c9092009-01-13 02:11:23 +0000180 print("(%i)"%(len(l),),)
181 for i in range(1000):
182 a = i*i
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000183 if context and not context.event.is_set():
184 continue
Benjamin Petersona54c9092009-01-13 02:11:23 +0000185 count += 1
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000186 self.assertTrue(count < 10000,
Benjamin Petersona54c9092009-01-13 02:11:23 +0000187 "timeout waiting for %i callbacks, got %i"%(n, len(l)))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000188 if False and support.verbose:
Benjamin Petersona54c9092009-01-13 02:11:23 +0000189 print("(%i)"%(len(l),))
190
191 def test_pendingcalls_threaded(self):
Benjamin Petersona54c9092009-01-13 02:11:23 +0000192
193 #do every callback on a separate thread
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000194 n = 32 #total callbacks
Benjamin Petersona54c9092009-01-13 02:11:23 +0000195 threads = []
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000196 class foo(object):pass
197 context = foo()
198 context.l = []
199 context.n = 2 #submits per thread
200 context.nThreads = n // context.n
201 context.nFinished = 0
202 context.lock = threading.Lock()
203 context.event = threading.Event()
204
205 for i in range(context.nThreads):
206 t = threading.Thread(target=self.pendingcalls_thread, args = (context,))
Benjamin Petersona54c9092009-01-13 02:11:23 +0000207 t.start()
208 threads.append(t)
209
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000210 self.pendingcalls_wait(context.l, n, context)
Benjamin Petersona54c9092009-01-13 02:11:23 +0000211
212 for t in threads:
213 t.join()
214
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000215 def pendingcalls_thread(self, context):
216 try:
217 self.pendingcalls_submit(context.l, context.n)
218 finally:
219 with context.lock:
220 context.nFinished += 1
221 nFinished = context.nFinished
222 if False and support.verbose:
223 print("finished threads: ", nFinished)
224 if nFinished == context.nThreads:
225 context.event.set()
226
Benjamin Petersona54c9092009-01-13 02:11:23 +0000227 def test_pendingcalls_non_threaded(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200228 #again, just using the main thread, likely they will all be dispatched at
Benjamin Petersona54c9092009-01-13 02:11:23 +0000229 #once. It is ok to ask for too many, because we loop until we find a slot.
230 #the loop can be interrupted to dispatch.
231 #there are only 32 dispatch slots, so we go for twice that!
232 l = []
233 n = 64
234 self.pendingcalls_submit(l, n)
235 self.pendingcalls_wait(l, n)
236
Antoine Pitrou7a2572c2013-08-01 20:43:26 +0200237
238class SubinterpreterTest(unittest.TestCase):
239
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100240 def test_subinterps(self):
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100241 import builtins
242 r, w = os.pipe()
243 code = """if 1:
244 import sys, builtins, pickle
245 with open({:d}, "wb") as f:
246 pickle.dump(id(sys.modules), f)
247 pickle.dump(id(builtins), f)
248 """.format(w)
249 with open(r, "rb") as f:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100250 ret = support.run_in_subinterp(code)
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100251 self.assertEqual(ret, 0)
252 self.assertNotEqual(pickle.load(f), id(sys.modules))
253 self.assertNotEqual(pickle.load(f), id(builtins))
254
Antoine Pitrou7a2572c2013-08-01 20:43:26 +0200255
Martin v. Löwisc15bdef2009-05-29 14:47:46 +0000256# Bug #6012
257class Test6012(unittest.TestCase):
258 def test(self):
259 self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
Benjamin Petersona54c9092009-01-13 02:11:23 +0000260
Antoine Pitrou8e605772011-04-25 21:21:07 +0200261
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000262class EmbeddingTests(unittest.TestCase):
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000263 def setUp(self):
Antoine Pitrou8e605772011-04-25 21:21:07 +0200264 basepath = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
Nick Coghlan4e641df2013-11-03 16:54:46 +1000265 exename = "_testembed"
266 if sys.platform.startswith("win"):
267 ext = ("_d" if "_d" in sys.executable else "") + ".exe"
268 exename += ext
269 exepath = os.path.dirname(sys.executable)
270 else:
271 exepath = os.path.join(basepath, "Modules")
272 self.test_exe = exe = os.path.join(exepath, exename)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000273 if not os.path.exists(exe):
274 self.skipTest("%r doesn't exist" % exe)
Antoine Pitrou8e605772011-04-25 21:21:07 +0200275 # This is needed otherwise we get a fatal error:
276 # "Py_Initialize: Unable to get the locale encoding
277 # LookupError: no codec search functions registered: can't find encoding"
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000278 self.oldcwd = os.getcwd()
Antoine Pitrou8e605772011-04-25 21:21:07 +0200279 os.chdir(basepath)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000280
281 def tearDown(self):
282 os.chdir(self.oldcwd)
283
284 def run_embedded_interpreter(self, *args):
285 """Runs a test in the embedded interpreter"""
286 cmd = [self.test_exe]
287 cmd.extend(args)
288 p = subprocess.Popen(cmd,
289 stdout=subprocess.PIPE,
290 stderr=subprocess.PIPE)
291 (out, err) = p.communicate()
292 self.assertEqual(p.returncode, 0,
293 "bad returncode %d, stderr is %r" %
294 (p.returncode, err))
295 return out.decode("latin1"), err.decode("latin1")
296
297 def test_subinterps(self):
298 # This is just a "don't crash" test
299 out, err = self.run_embedded_interpreter()
300 if support.verbose:
301 print()
302 print(out)
303 print(err)
304
Nick Coghlan4e641df2013-11-03 16:54:46 +1000305 @staticmethod
306 def _get_default_pipe_encoding():
307 rp, wp = os.pipe()
308 try:
309 with os.fdopen(wp, 'w') as w:
310 default_pipe_encoding = w.encoding
311 finally:
312 os.close(rp)
313 return default_pipe_encoding
314
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000315 def test_forced_io_encoding(self):
316 # Checks forced configuration of embedded interpreter IO streams
317 out, err = self.run_embedded_interpreter("forced_io_encoding")
318 if support.verbose:
319 print()
320 print(out)
321 print(err)
Nick Coghlan4e641df2013-11-03 16:54:46 +1000322 expected_stdin_encoding = sys.__stdin__.encoding
323 expected_pipe_encoding = self._get_default_pipe_encoding()
324 expected_output = os.linesep.join([
325 "--- Use defaults ---",
326 "Expected encoding: default",
327 "Expected errors: default",
328 "stdin: {0}:strict",
329 "stdout: {1}:strict",
330 "stderr: {1}:backslashreplace",
331 "--- Set errors only ---",
332 "Expected encoding: default",
333 "Expected errors: surrogateescape",
334 "stdin: {0}:surrogateescape",
335 "stdout: {1}:surrogateescape",
336 "stderr: {1}:backslashreplace",
337 "--- Set encoding only ---",
338 "Expected encoding: latin-1",
339 "Expected errors: default",
340 "stdin: latin-1:strict",
341 "stdout: latin-1:strict",
342 "stderr: latin-1:backslashreplace",
343 "--- Set encoding and errors ---",
344 "Expected encoding: latin-1",
345 "Expected errors: surrogateescape",
346 "stdin: latin-1:surrogateescape",
347 "stdout: latin-1:surrogateescape",
348 "stderr: latin-1:backslashreplace"]).format(expected_stdin_encoding,
349 expected_pipe_encoding)
Nick Coghlan3321fb82013-10-18 23:59:58 +1000350 # This is useful if we ever trip over odd platform behaviour
Nick Coghlan6508dc52013-10-18 01:44:22 +1000351 self.maxDiff = None
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000352 self.assertEqual(out.strip(), expected_output)
Antoine Pitrou8e605772011-04-25 21:21:07 +0200353
Larry Hastings8f904da2012-06-22 03:56:29 -0700354class SkipitemTest(unittest.TestCase):
355
356 def test_skipitem(self):
357 """
358 If this test failed, you probably added a new "format unit"
359 in Python/getargs.c, but neglected to update our poor friend
360 skipitem() in the same file. (If so, shame on you!)
361
Larry Hastings48ed3602012-06-22 12:58:36 -0700362 With a few exceptions**, this function brute-force tests all
363 printable ASCII*** characters (32 to 126 inclusive) as format units,
364 checking to see that PyArg_ParseTupleAndKeywords() return consistent
365 errors both when the unit is attempted to be used and when it is
366 skipped. If the format unit doesn't exist, we'll get one of two
367 specific error messages (one for used, one for skipped); if it does
368 exist we *won't* get that error--we'll get either no error or some
369 other error. If we get the specific "does not exist" error for one
370 test and not for the other, there's a mismatch, and the test fails.
Larry Hastings8f904da2012-06-22 03:56:29 -0700371
Larry Hastings48ed3602012-06-22 12:58:36 -0700372 ** Some format units have special funny semantics and it would
373 be difficult to accomodate them here. Since these are all
374 well-established and properly skipped in skipitem() we can
375 get away with not testing them--this test is really intended
376 to catch *new* format units.
377
378 *** Python C source files must be ASCII. Therefore it's impossible
379 to have non-ASCII format units.
380
Larry Hastings8f904da2012-06-22 03:56:29 -0700381 """
382 empty_tuple = ()
383 tuple_1 = (0,)
384 dict_b = {'b':1}
385 keywords = ["a", "b"]
386
Larry Hastings48ed3602012-06-22 12:58:36 -0700387 for i in range(32, 127):
Larry Hastings8f904da2012-06-22 03:56:29 -0700388 c = chr(i)
389
Larry Hastings8f904da2012-06-22 03:56:29 -0700390 # skip parentheses, the error reporting is inconsistent about them
391 # skip 'e', it's always a two-character code
392 # skip '|' and '$', they don't represent arguments anyway
Larry Hastings48ed3602012-06-22 12:58:36 -0700393 if c in '()e|$':
Larry Hastings8f904da2012-06-22 03:56:29 -0700394 continue
395
396 # test the format unit when not skipped
397 format = c + "i"
398 try:
399 # (note: the format string must be bytes!)
400 _testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
401 format.encode("ascii"), keywords)
402 when_not_skipped = False
403 except TypeError as e:
404 s = "argument 1 must be impossible<bad format char>, not int"
405 when_not_skipped = (str(e) == s)
406 except RuntimeError as e:
407 when_not_skipped = False
408
409 # test the format unit when skipped
410 optional_format = "|" + format
411 try:
412 _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
413 optional_format.encode("ascii"), keywords)
414 when_skipped = False
415 except RuntimeError as e:
416 s = "impossible<bad format char>: '{}'".format(format)
417 when_skipped = (str(e) == s)
418
419 message = ("test_skipitem_parity: "
420 "detected mismatch between convertsimple and skipitem "
421 "for format unit '{}' ({}), not skipped {}, skipped {}".format(
422 c, i, when_skipped, when_not_skipped))
423 self.assertIs(when_skipped, when_not_skipped, message)
Antoine Pitrou8e605772011-04-25 21:21:07 +0200424
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200425 def test_parse_tuple_and_keywords(self):
426 # parse_tuple_and_keywords error handling tests
427 self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
428 (), {}, 42, [])
429 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
430 (), {}, b'', 42)
431 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
432 (), {}, b'', [''] * 42)
433 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
434 (), {}, b'', [42])
435
Ezio Melotti29267c82013-02-23 05:52:46 +0200436@unittest.skipUnless(threading, 'Threading required for this test.')
437class TestThreadState(unittest.TestCase):
438
439 @support.reap_threads
440 def test_thread_state(self):
441 # some extra thread-state tests driven via _testcapi
442 def target():
443 idents = []
444
445 def callback():
Ezio Melotti35246bd2013-02-23 05:58:38 +0200446 idents.append(threading.get_ident())
Ezio Melotti29267c82013-02-23 05:52:46 +0200447
448 _testcapi._test_thread_state(callback)
449 a = b = callback
450 time.sleep(1)
451 # Check our main thread is in the list exactly 3 times.
Ezio Melotti35246bd2013-02-23 05:58:38 +0200452 self.assertEqual(idents.count(threading.get_ident()), 3,
Ezio Melotti29267c82013-02-23 05:52:46 +0200453 "Couldn't find main thread correctly in the list")
454
455 target()
456 t = threading.Thread(target=target)
457 t.start()
458 t.join()
459
Zachary Warec12f09e2013-11-11 22:47:04 -0600460class Test_testcapi(unittest.TestCase):
461 def test__testcapi(self):
462 for name in dir(_testcapi):
463 if name.startswith('test_'):
Zachary Waredfcd6942013-11-11 22:59:23 -0600464 with self.subTest("internal", name=name):
465 test = getattr(_testcapi, name)
466 test()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000467
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000468if __name__ == "__main__":
Zachary Warec12f09e2013-11-11 22:47:04 -0600469 unittest.main()