blob: bb2570a8e094389109621276403af3e6b9a665a2 [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
Nick Coghlan39f0bb52017-11-28 08:11:51 +10004from collections import OrderedDict
Antoine Pitrou8e605772011-04-25 21:21:07 +02005import os
Antoine Pitrou2f828f22012-01-18 00:21:11 +01006import pickle
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +00007import random
Victor Stinnerb3adb1a2016-03-14 17:40:09 +01008import re
Serhiy Storchaka504373c2018-07-11 17:41:43 +03009import string
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000010import subprocess
Martin v. Löwis6ce7ed22005-03-03 12:26:35 +000011import sys
Victor Stinner34be8072016-03-14 12:04:26 +010012import sysconfig
Victor Stinnerefde1462015-03-21 15:04:43 +010013import textwrap
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020014import threading
Benjamin Petersona54c9092009-01-13 02:11:23 +000015import time
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000016import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +000017from test import support
Larry Hastingsfcafe432013-11-23 17:35:48 -080018from test.support import MISSING_C_DOCSTRINGS
xdegaye85f64302017-07-01 14:14:45 +020019from test.support.script_helper import assert_python_failure, assert_python_ok
Victor Stinner45df8202010-04-28 22:31:17 +000020try:
Stefan Krahfd24f9e2012-08-20 11:04:24 +020021 import _posixsubprocess
22except ImportError:
23 _posixsubprocess = None
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020024
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020025# Skip this test if the _testcapi module isn't available.
26_testcapi = support.import_module('_testcapi')
Tim Peters9ea17ac2001-02-02 05:57:15 +000027
Victor Stinnerefde1462015-03-21 15:04:43 +010028# Were we compiled --with-pydebug or with #define Py_DEBUG?
29Py_DEBUG = hasattr(sys, 'gettotalrefcount')
30
Benjamin Petersona54c9092009-01-13 02:11:23 +000031
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000032def testfunction(self):
33 """some doc"""
34 return self
35
36class InstanceMethod:
37 id = _testcapi.instancemethod(id)
38 testfunction = _testcapi.instancemethod(testfunction)
39
40class CAPITest(unittest.TestCase):
41
42 def test_instancemethod(self):
43 inst = InstanceMethod()
44 self.assertEqual(id(inst), inst.id())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000045 self.assertTrue(inst.testfunction() is inst)
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000046 self.assertEqual(inst.testfunction.__doc__, testfunction.__doc__)
47 self.assertEqual(InstanceMethod.testfunction.__doc__, testfunction.__doc__)
48
49 InstanceMethod.testfunction.attribute = "test"
50 self.assertEqual(testfunction.attribute, "test")
51 self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test")
52
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000053 def test_no_FatalError_infinite_loop(self):
Antoine Pitrou77e904e2013-10-08 23:04:32 +020054 with support.SuppressCrashReport():
Ezio Melotti25a40452013-03-05 20:26:17 +020055 p = subprocess.Popen([sys.executable, "-c",
Ezio Melottie1857d92013-03-05 20:31:34 +020056 'import _testcapi;'
57 '_testcapi.crash_no_current_thread()'],
58 stdout=subprocess.PIPE,
59 stderr=subprocess.PIPE)
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000060 (out, err) = p.communicate()
61 self.assertEqual(out, b'')
62 # This used to cause an infinite loop.
Vinay Sajip73954042012-05-06 11:34:50 +010063 self.assertTrue(err.rstrip().startswith(
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000064 b'Fatal Python error:'
Vinay Sajip73954042012-05-06 11:34:50 +010065 b' PyThreadState_Get: no current thread'))
Jeffrey Yasskin8e0bdfd2010-05-13 18:31:05 +000066
Antoine Pitrou915605c2011-02-24 20:53:48 +000067 def test_memoryview_from_NULL_pointer(self):
68 self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer)
Benjamin Peterson9b6df6a2008-10-16 23:56:29 +000069
Martin v. Löwisaa2efcb2012-04-19 14:33:43 +020070 def test_exc_info(self):
71 raised_exception = ValueError("5")
72 new_exc = TypeError("TEST")
73 try:
74 raise raised_exception
75 except ValueError as e:
76 tb = e.__traceback__
77 orig_sys_exc_info = sys.exc_info()
78 orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None)
79 new_sys_exc_info = sys.exc_info()
80 new_exc_info = _testcapi.set_exc_info(*orig_exc_info)
81 reset_sys_exc_info = sys.exc_info()
82
83 self.assertEqual(orig_exc_info[1], e)
84
85 self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb))
86 self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info)
87 self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info)
88 self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None))
89 self.assertSequenceEqual(new_sys_exc_info, new_exc_info)
90 else:
91 self.assertTrue(False)
92
Stefan Krahfd24f9e2012-08-20 11:04:24 +020093 @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
94 def test_seq_bytes_to_charp_array(self):
95 # Issue #15732: crash in _PySequence_BytesToCharpArray()
96 class Z(object):
97 def __len__(self):
98 return 1
99 self.assertRaises(TypeError, _posixsubprocess.fork_exec,
Serhiy Storchaka66bffd12017-04-19 21:12:46 +0300100 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 +0200101 # Issue #15736: overflow in _PySequence_BytesToCharpArray()
102 class Z(object):
103 def __len__(self):
104 return sys.maxsize
105 def __getitem__(self, i):
106 return b'x'
107 self.assertRaises(MemoryError, _posixsubprocess.fork_exec,
Serhiy Storchaka66bffd12017-04-19 21:12:46 +0300108 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 +0200109
Stefan Krahdb579d72012-08-20 14:36:47 +0200110 @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
111 def test_subprocess_fork_exec(self):
112 class Z(object):
113 def __len__(self):
114 return 1
115
116 # Issue #15738: crash in subprocess_fork_exec()
117 self.assertRaises(TypeError, _posixsubprocess.fork_exec,
Serhiy Storchaka66bffd12017-04-19 21:12:46 +0300118 Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17)
Stefan Krahdb579d72012-08-20 14:36:47 +0200119
Larry Hastingsfcafe432013-11-23 17:35:48 -0800120 @unittest.skipIf(MISSING_C_DOCSTRINGS,
121 "Signature information for builtins requires docstrings")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800122 def test_docstring_signature_parsing(self):
123
124 self.assertEqual(_testcapi.no_docstring.__doc__, None)
125 self.assertEqual(_testcapi.no_docstring.__text_signature__, None)
126
Zachary Ware8ef887c2015-04-13 18:22:35 -0500127 self.assertEqual(_testcapi.docstring_empty.__doc__, None)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800128 self.assertEqual(_testcapi.docstring_empty.__text_signature__, None)
129
130 self.assertEqual(_testcapi.docstring_no_signature.__doc__,
131 "This docstring has no signature.")
132 self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None)
133
134 self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800135 "docstring_with_invalid_signature($module, /, boo)\n"
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800136 "\n"
137 "This docstring has an invalid signature."
138 )
139 self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None)
140
Larry Hastings2623c8c2014-02-08 22:15:29 -0800141 self.assertEqual(_testcapi.docstring_with_invalid_signature2.__doc__,
142 "docstring_with_invalid_signature2($module, /, boo)\n"
143 "\n"
144 "--\n"
145 "\n"
146 "This docstring also has an invalid signature."
147 )
148 self.assertEqual(_testcapi.docstring_with_invalid_signature2.__text_signature__, None)
149
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800150 self.assertEqual(_testcapi.docstring_with_signature.__doc__,
151 "This docstring has a valid signature.")
Larry Hastings2623c8c2014-02-08 22:15:29 -0800152 self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800153
Zachary Ware8ef887c2015-04-13 18:22:35 -0500154 self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__doc__, None)
155 self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__text_signature__,
156 "($module, /, sig)")
157
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800158 self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800159 "\nThis docstring has a valid signature and some extra newlines.")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800160 self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__,
Larry Hastings2623c8c2014-02-08 22:15:29 -0800161 "($module, /, parameter)")
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800162
Benjamin Petersond51374e2014-04-09 23:55:56 -0400163 def test_c_type_with_matrix_multiplication(self):
164 M = _testcapi.matmulType
165 m1 = M()
166 m2 = M()
167 self.assertEqual(m1 @ m2, ("matmul", m1, m2))
168 self.assertEqual(m1 @ 42, ("matmul", m1, 42))
169 self.assertEqual(42 @ m1, ("matmul", 42, m1))
170 o = m1
171 o @= m2
172 self.assertEqual(o, ("imatmul", m1, m2))
173 o = m1
174 o @= 42
175 self.assertEqual(o, ("imatmul", m1, 42))
176 o = 42
177 o @= m1
178 self.assertEqual(o, ("matmul", 42, m1))
179
Victor Stinnerefde1462015-03-21 15:04:43 +0100180 def test_return_null_without_error(self):
181 # Issue #23571: A function must not return NULL without setting an
182 # error
183 if Py_DEBUG:
184 code = textwrap.dedent("""
185 import _testcapi
186 from test import support
187
188 with support.SuppressCrashReport():
189 _testcapi.return_null_without_error()
190 """)
191 rc, out, err = assert_python_failure('-c', code)
Victor Stinner381a9bc2015-03-24 14:01:32 +0100192 self.assertRegex(err.replace(b'\r', b''),
Victor Stinner944fbcc2015-03-24 16:28:52 +0100193 br'Fatal Python error: a function returned NULL '
194 br'without setting an error\n'
Victor Stinner381a9bc2015-03-24 14:01:32 +0100195 br'SystemError: <built-in function '
196 br'return_null_without_error> returned NULL '
197 br'without setting an error\n'
198 br'\n'
199 br'Current thread.*:\n'
200 br' File .*", line 6 in <module>')
Victor Stinnerefde1462015-03-21 15:04:43 +0100201 else:
202 with self.assertRaises(SystemError) as cm:
203 _testcapi.return_null_without_error()
204 self.assertRegex(str(cm.exception),
205 'return_null_without_error.* '
206 'returned NULL without setting an error')
207
208 def test_return_result_with_error(self):
209 # Issue #23571: A function must not return a result with an error set
210 if Py_DEBUG:
211 code = textwrap.dedent("""
212 import _testcapi
213 from test import support
214
215 with support.SuppressCrashReport():
216 _testcapi.return_result_with_error()
217 """)
218 rc, out, err = assert_python_failure('-c', code)
Victor Stinner381a9bc2015-03-24 14:01:32 +0100219 self.assertRegex(err.replace(b'\r', b''),
Victor Stinner944fbcc2015-03-24 16:28:52 +0100220 br'Fatal Python error: a function returned a '
221 br'result with an error set\n'
Victor Stinner381a9bc2015-03-24 14:01:32 +0100222 br'ValueError\n'
223 br'\n'
Serhiy Storchaka467ab192016-10-21 17:09:17 +0300224 br'The above exception was the direct cause '
225 br'of the following exception:\n'
Victor Stinner381a9bc2015-03-24 14:01:32 +0100226 br'\n'
227 br'SystemError: <built-in '
228 br'function return_result_with_error> '
229 br'returned a result with an error set\n'
230 br'\n'
231 br'Current thread.*:\n'
232 br' File .*, line 6 in <module>')
Victor Stinnerefde1462015-03-21 15:04:43 +0100233 else:
234 with self.assertRaises(SystemError) as cm:
235 _testcapi.return_result_with_error()
236 self.assertRegex(str(cm.exception),
237 'return_result_with_error.* '
238 'returned a result with an error set')
239
Serhiy Storchaka13e602e2016-05-20 22:31:14 +0300240 def test_buildvalue_N(self):
241 _testcapi.test_buildvalue_N()
242
xdegaye85f64302017-07-01 14:14:45 +0200243 def test_set_nomemory(self):
244 code = """if 1:
245 import _testcapi
246
247 class C(): pass
248
249 # The first loop tests both functions and that remove_mem_hooks()
250 # can be called twice in a row. The second loop checks a call to
251 # set_nomemory() after a call to remove_mem_hooks(). The third
252 # loop checks the start and stop arguments of set_nomemory().
253 for outer_cnt in range(1, 4):
254 start = 10 * outer_cnt
255 for j in range(100):
256 if j == 0:
257 if outer_cnt != 3:
258 _testcapi.set_nomemory(start)
259 else:
260 _testcapi.set_nomemory(start, start + 1)
261 try:
262 C()
263 except MemoryError as e:
264 if outer_cnt != 3:
265 _testcapi.remove_mem_hooks()
266 print('MemoryError', outer_cnt, j)
267 _testcapi.remove_mem_hooks()
268 break
269 """
270 rc, out, err = assert_python_ok('-c', code)
271 self.assertIn(b'MemoryError 1 10', out)
272 self.assertIn(b'MemoryError 2 20', out)
273 self.assertIn(b'MemoryError 3 30', out)
274
Oren Milman0ccc0f62017-10-08 11:17:46 +0300275 def test_mapping_keys_values_items(self):
276 class Mapping1(dict):
277 def keys(self):
278 return list(super().keys())
279 def values(self):
280 return list(super().values())
281 def items(self):
282 return list(super().items())
283 class Mapping2(dict):
284 def keys(self):
285 return tuple(super().keys())
286 def values(self):
287 return tuple(super().values())
288 def items(self):
289 return tuple(super().items())
290 dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
291
292 for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(),
293 dict_obj, OrderedDict(dict_obj),
294 Mapping1(dict_obj), Mapping2(dict_obj)]:
295 self.assertListEqual(_testcapi.get_mapping_keys(mapping),
296 list(mapping.keys()))
297 self.assertListEqual(_testcapi.get_mapping_values(mapping),
298 list(mapping.values()))
299 self.assertListEqual(_testcapi.get_mapping_items(mapping),
300 list(mapping.items()))
301
302 def test_mapping_keys_values_items_bad_arg(self):
303 self.assertRaises(AttributeError, _testcapi.get_mapping_keys, None)
304 self.assertRaises(AttributeError, _testcapi.get_mapping_values, None)
305 self.assertRaises(AttributeError, _testcapi.get_mapping_items, None)
306
307 class BadMapping:
308 def keys(self):
309 return None
310 def values(self):
311 return None
312 def items(self):
313 return None
314 bad_mapping = BadMapping()
315 self.assertRaises(TypeError, _testcapi.get_mapping_keys, bad_mapping)
316 self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping)
317 self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping)
318
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800319
Benjamin Petersona54c9092009-01-13 02:11:23 +0000320class TestPendingCalls(unittest.TestCase):
321
322 def pendingcalls_submit(self, l, n):
323 def callback():
324 #this function can be interrupted by thread switching so let's
325 #use an atomic operation
326 l.append(None)
327
328 for i in range(n):
329 time.sleep(random.random()*0.02) #0.01 secs on average
330 #try submitting callback until successful.
331 #rely on regular interrupt to flush queue if we are
332 #unsuccessful.
333 while True:
334 if _testcapi._pending_threadfunc(callback):
335 break;
336
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000337 def pendingcalls_wait(self, l, n, context = None):
Benjamin Petersona54c9092009-01-13 02:11:23 +0000338 #now, stick around until l[0] has grown to 10
339 count = 0;
340 while len(l) != n:
341 #this busy loop is where we expect to be interrupted to
342 #run our callbacks. Note that callbacks are only run on the
343 #main thread
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000344 if False and support.verbose:
Benjamin Petersona54c9092009-01-13 02:11:23 +0000345 print("(%i)"%(len(l),),)
346 for i in range(1000):
347 a = i*i
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000348 if context and not context.event.is_set():
349 continue
Benjamin Petersona54c9092009-01-13 02:11:23 +0000350 count += 1
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000351 self.assertTrue(count < 10000,
Benjamin Petersona54c9092009-01-13 02:11:23 +0000352 "timeout waiting for %i callbacks, got %i"%(n, len(l)))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000353 if False and support.verbose:
Benjamin Petersona54c9092009-01-13 02:11:23 +0000354 print("(%i)"%(len(l),))
355
356 def test_pendingcalls_threaded(self):
Benjamin Petersona54c9092009-01-13 02:11:23 +0000357
358 #do every callback on a separate thread
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000359 n = 32 #total callbacks
Benjamin Petersona54c9092009-01-13 02:11:23 +0000360 threads = []
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000361 class foo(object):pass
362 context = foo()
363 context.l = []
364 context.n = 2 #submits per thread
365 context.nThreads = n // context.n
366 context.nFinished = 0
367 context.lock = threading.Lock()
368 context.event = threading.Event()
369
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300370 threads = [threading.Thread(target=self.pendingcalls_thread,
371 args=(context,))
372 for i in range(context.nThreads)]
373 with support.start_threads(threads):
374 self.pendingcalls_wait(context.l, n, context)
Benjamin Petersona54c9092009-01-13 02:11:23 +0000375
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000376 def pendingcalls_thread(self, context):
377 try:
378 self.pendingcalls_submit(context.l, context.n)
379 finally:
380 with context.lock:
381 context.nFinished += 1
382 nFinished = context.nFinished
383 if False and support.verbose:
384 print("finished threads: ", nFinished)
385 if nFinished == context.nThreads:
386 context.event.set()
387
Benjamin Petersona54c9092009-01-13 02:11:23 +0000388 def test_pendingcalls_non_threaded(self):
Ezio Melotti13925002011-03-16 11:05:33 +0200389 #again, just using the main thread, likely they will all be dispatched at
Benjamin Petersona54c9092009-01-13 02:11:23 +0000390 #once. It is ok to ask for too many, because we loop until we find a slot.
391 #the loop can be interrupted to dispatch.
392 #there are only 32 dispatch slots, so we go for twice that!
393 l = []
394 n = 64
395 self.pendingcalls_submit(l, n)
396 self.pendingcalls_wait(l, n)
397
Antoine Pitrou7a2572c2013-08-01 20:43:26 +0200398
399class SubinterpreterTest(unittest.TestCase):
400
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100401 def test_subinterps(self):
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100402 import builtins
403 r, w = os.pipe()
404 code = """if 1:
405 import sys, builtins, pickle
406 with open({:d}, "wb") as f:
407 pickle.dump(id(sys.modules), f)
408 pickle.dump(id(builtins), f)
409 """.format(w)
410 with open(r, "rb") as f:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100411 ret = support.run_in_subinterp(code)
Antoine Pitrou2f828f22012-01-18 00:21:11 +0100412 self.assertEqual(ret, 0)
413 self.assertNotEqual(pickle.load(f), id(sys.modules))
414 self.assertNotEqual(pickle.load(f), id(builtins))
415
Antoine Pitrou7a2572c2013-08-01 20:43:26 +0200416
Martin v. Löwisc15bdef2009-05-29 14:47:46 +0000417# Bug #6012
418class Test6012(unittest.TestCase):
419 def test(self):
420 self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
Benjamin Petersona54c9092009-01-13 02:11:23 +0000421
Antoine Pitrou8e605772011-04-25 21:21:07 +0200422
Larry Hastings8f904da2012-06-22 03:56:29 -0700423class SkipitemTest(unittest.TestCase):
424
425 def test_skipitem(self):
426 """
427 If this test failed, you probably added a new "format unit"
428 in Python/getargs.c, but neglected to update our poor friend
429 skipitem() in the same file. (If so, shame on you!)
430
Larry Hastings48ed3602012-06-22 12:58:36 -0700431 With a few exceptions**, this function brute-force tests all
432 printable ASCII*** characters (32 to 126 inclusive) as format units,
433 checking to see that PyArg_ParseTupleAndKeywords() return consistent
434 errors both when the unit is attempted to be used and when it is
435 skipped. If the format unit doesn't exist, we'll get one of two
436 specific error messages (one for used, one for skipped); if it does
437 exist we *won't* get that error--we'll get either no error or some
438 other error. If we get the specific "does not exist" error for one
439 test and not for the other, there's a mismatch, and the test fails.
Larry Hastings8f904da2012-06-22 03:56:29 -0700440
Larry Hastings48ed3602012-06-22 12:58:36 -0700441 ** Some format units have special funny semantics and it would
Martin Panter46f50722016-05-26 05:35:26 +0000442 be difficult to accommodate them here. Since these are all
Larry Hastings48ed3602012-06-22 12:58:36 -0700443 well-established and properly skipped in skipitem() we can
444 get away with not testing them--this test is really intended
445 to catch *new* format units.
446
447 *** Python C source files must be ASCII. Therefore it's impossible
448 to have non-ASCII format units.
449
Larry Hastings8f904da2012-06-22 03:56:29 -0700450 """
451 empty_tuple = ()
452 tuple_1 = (0,)
453 dict_b = {'b':1}
454 keywords = ["a", "b"]
455
Larry Hastings48ed3602012-06-22 12:58:36 -0700456 for i in range(32, 127):
Larry Hastings8f904da2012-06-22 03:56:29 -0700457 c = chr(i)
458
Larry Hastings8f904da2012-06-22 03:56:29 -0700459 # skip parentheses, the error reporting is inconsistent about them
460 # skip 'e', it's always a two-character code
461 # skip '|' and '$', they don't represent arguments anyway
Larry Hastings48ed3602012-06-22 12:58:36 -0700462 if c in '()e|$':
Larry Hastings8f904da2012-06-22 03:56:29 -0700463 continue
464
465 # test the format unit when not skipped
466 format = c + "i"
467 try:
Larry Hastings8f904da2012-06-22 03:56:29 -0700468 _testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300469 format, keywords)
Larry Hastings8f904da2012-06-22 03:56:29 -0700470 when_not_skipped = False
Serhiy Storchaka4cd63ef2016-02-08 01:22:47 +0200471 except SystemError as e:
Serhiy Storchakac4b813d2016-02-08 01:06:11 +0200472 s = "argument 1 (impossible<bad format char>)"
Larry Hastings8f904da2012-06-22 03:56:29 -0700473 when_not_skipped = (str(e) == s)
Serhiy Storchakaa9725f82016-02-11 12:41:40 +0200474 except TypeError:
Larry Hastings8f904da2012-06-22 03:56:29 -0700475 when_not_skipped = False
476
477 # test the format unit when skipped
478 optional_format = "|" + format
479 try:
480 _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300481 optional_format, keywords)
Larry Hastings8f904da2012-06-22 03:56:29 -0700482 when_skipped = False
Serhiy Storchakaa9725f82016-02-11 12:41:40 +0200483 except SystemError as e:
Larry Hastings8f904da2012-06-22 03:56:29 -0700484 s = "impossible<bad format char>: '{}'".format(format)
485 when_skipped = (str(e) == s)
486
487 message = ("test_skipitem_parity: "
488 "detected mismatch between convertsimple and skipitem "
489 "for format unit '{}' ({}), not skipped {}, skipped {}".format(
490 c, i, when_skipped, when_not_skipped))
491 self.assertIs(when_skipped, when_not_skipped, message)
Antoine Pitrou8e605772011-04-25 21:21:07 +0200492
Serhiy Storchaka504373c2018-07-11 17:41:43 +0300493 def test_skipitem_with_suffix(self):
494 parse = _testcapi.parse_tuple_and_keywords
495 empty_tuple = ()
496 tuple_1 = (0,)
497 dict_b = {'b':1}
498 keywords = ["a", "b"]
499
500 supported = ('s#', 's*', 'z#', 'z*', 'u#', 'Z#', 'y#', 'y*', 'w#', 'w*')
501 for c in string.ascii_letters:
502 for c2 in '#*':
503 f = c + c2
504 with self.subTest(format=f):
505 optional_format = "|" + f + "i"
506 if f in supported:
507 parse(empty_tuple, dict_b, optional_format, keywords)
508 else:
509 with self.assertRaisesRegex(SystemError,
510 'impossible<bad format char>'):
511 parse(empty_tuple, dict_b, optional_format, keywords)
512
513 for c in map(chr, range(32, 128)):
514 f = 'e' + c
515 optional_format = "|" + f + "i"
516 with self.subTest(format=f):
517 if c in 'st':
518 parse(empty_tuple, dict_b, optional_format, keywords)
519 else:
520 with self.assertRaisesRegex(SystemError,
521 'impossible<bad format char>'):
522 parse(empty_tuple, dict_b, optional_format, keywords)
523
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200524 def test_parse_tuple_and_keywords(self):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300525 # Test handling errors in the parse_tuple_and_keywords helper itself
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200526 self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
527 (), {}, 42, [])
528 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300529 (), {}, '', 42)
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200530 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300531 (), {}, '', [''] * 42)
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200532 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300533 (), {}, '', [42])
534
535 def test_bad_use(self):
536 # Test handling invalid format and keywords in
537 # PyArg_ParseTupleAndKeywords()
538 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
539 (1,), {}, '||O', ['a'])
540 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
541 (1, 2), {}, '|O|O', ['a', 'b'])
542 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
543 (), {'a': 1}, '$$O', ['a'])
544 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
545 (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b'])
546 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
547 (), {'a': 1}, '$|O', ['a'])
548 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
549 (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b'])
550 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
551 (1,), {}, '|O', ['a', 'b'])
552 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
553 (1,), {}, '|OO', ['a'])
554 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
555 (), {}, '|$O', [''])
556 self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
557 (), {}, '|OO', ['a', ''])
Jesus Cea6e1d2b62012-10-04 16:06:30 +0200558
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300559 def test_positional_only(self):
560 parse = _testcapi.parse_tuple_and_keywords
561
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300562 parse((1, 2, 3), {}, 'OOO', ['', '', 'a'])
563 parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a'])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300564 with self.assertRaisesRegex(TypeError,
Michael Seifert64c8f702017-04-09 09:47:12 +0200565 r'function takes at least 2 positional arguments \(1 given\)'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300566 parse((1,), {'a': 3}, 'OOO', ['', '', 'a'])
567 parse((1,), {}, 'O|OO', ['', '', 'a'])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300568 with self.assertRaisesRegex(TypeError,
Michael Seifert64c8f702017-04-09 09:47:12 +0200569 r'function takes at least 1 positional arguments \(0 given\)'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300570 parse((), {}, 'O|OO', ['', '', 'a'])
571 parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a'])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300572 with self.assertRaisesRegex(TypeError,
Michael Seifert64c8f702017-04-09 09:47:12 +0200573 r'function takes exactly 2 positional arguments \(1 given\)'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300574 parse((1,), {'a': 3}, 'OO$O', ['', '', 'a'])
575 parse((1,), {}, 'O|O$O', ['', '', 'a'])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300576 with self.assertRaisesRegex(TypeError,
Michael Seifert64c8f702017-04-09 09:47:12 +0200577 r'function takes at least 1 positional arguments \(0 given\)'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300578 parse((), {}, 'O|O$O', ['', '', 'a'])
R David Murray44b548d2016-09-08 13:59:53 -0400579 with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300580 parse((1,), {}, 'O|$OO', ['', '', 'a'])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300581 with self.assertRaisesRegex(SystemError, 'Empty keyword'):
Serhiy Storchaka5f161fd2017-05-04 00:03:23 +0300582 parse((1,), {}, 'O|OO', ['', 'a', ''])
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300583
Victor Stinner34be8072016-03-14 12:04:26 +0100584
Ezio Melotti29267c82013-02-23 05:52:46 +0200585class TestThreadState(unittest.TestCase):
586
587 @support.reap_threads
588 def test_thread_state(self):
589 # some extra thread-state tests driven via _testcapi
590 def target():
591 idents = []
592
593 def callback():
Ezio Melotti35246bd2013-02-23 05:58:38 +0200594 idents.append(threading.get_ident())
Ezio Melotti29267c82013-02-23 05:52:46 +0200595
596 _testcapi._test_thread_state(callback)
597 a = b = callback
598 time.sleep(1)
599 # Check our main thread is in the list exactly 3 times.
Ezio Melotti35246bd2013-02-23 05:58:38 +0200600 self.assertEqual(idents.count(threading.get_ident()), 3,
Ezio Melotti29267c82013-02-23 05:52:46 +0200601 "Couldn't find main thread correctly in the list")
602
603 target()
604 t = threading.Thread(target=target)
605 t.start()
606 t.join()
607
Victor Stinner34be8072016-03-14 12:04:26 +0100608
Zachary Warec12f09e2013-11-11 22:47:04 -0600609class Test_testcapi(unittest.TestCase):
610 def test__testcapi(self):
Victor Stinnere1a470b2017-10-31 08:40:59 -0700611 if support.verbose:
612 print()
Zachary Warec12f09e2013-11-11 22:47:04 -0600613 for name in dir(_testcapi):
Victor Stinnere1a470b2017-10-31 08:40:59 -0700614 if not name.startswith('test_'):
615 continue
616 with self.subTest("internal", name=name):
617 if support.verbose:
618 print(f" {name}", flush=True)
619 test = getattr(_testcapi, name)
620 test()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000621
Victor Stinner34be8072016-03-14 12:04:26 +0100622
Victor Stinnerc4aec362016-03-14 22:26:53 +0100623class PyMemDebugTests(unittest.TestCase):
624 PYTHONMALLOC = 'debug'
Victor Stinnera1bc28a2016-03-14 17:10:36 +0100625 # '0x04c06e0' or '04C06E0'
Victor Stinner08572f62016-03-14 21:55:43 +0100626 PTR_REGEX = r'(?:0x)?[0-9a-fA-F]+'
Victor Stinner34be8072016-03-14 12:04:26 +0100627
628 def check(self, code):
629 with support.SuppressCrashReport():
Victor Stinnerc4aec362016-03-14 22:26:53 +0100630 out = assert_python_failure('-c', code,
631 PYTHONMALLOC=self.PYTHONMALLOC)
Victor Stinner34be8072016-03-14 12:04:26 +0100632 stderr = out.err
633 return stderr.decode('ascii', 'replace')
634
635 def test_buffer_overflow(self):
636 out = self.check('import _testcapi; _testcapi.pymem_buffer_overflow()')
Victor Stinnera1bc28a2016-03-14 17:10:36 +0100637 regex = (r"Debug memory block at address p={ptr}: API 'm'\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100638 r" 16 bytes originally requested\n"
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100639 r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
640 r" The [0-9] pad bytes at tail={ptr} are not all FORBIDDENBYTE \(0x[0-9a-f]{{2}}\):\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100641 r" at tail\+0: 0x78 \*\*\* OUCH\n"
642 r" at tail\+1: 0xfb\n"
643 r" at tail\+2: 0xfb\n"
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100644 r" .*\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100645 r" The block was made by call #[0-9]+ to debug malloc/realloc.\n"
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100646 r" Data at p: cb cb cb .*\n"
Victor Stinner6453e9e2016-03-15 23:36:28 +0100647 r"\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100648 r"Fatal Python error: bad trailing pad byte")
Victor Stinnera1bc28a2016-03-14 17:10:36 +0100649 regex = regex.format(ptr=self.PTR_REGEX)
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100650 regex = re.compile(regex, flags=re.DOTALL)
Victor Stinner34be8072016-03-14 12:04:26 +0100651 self.assertRegex(out, regex)
652
653 def test_api_misuse(self):
654 out = self.check('import _testcapi; _testcapi.pymem_api_misuse()')
Victor Stinnera1bc28a2016-03-14 17:10:36 +0100655 regex = (r"Debug memory block at address p={ptr}: API 'm'\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100656 r" 16 bytes originally requested\n"
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100657 r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
658 r" The [0-9] pad bytes at tail={ptr} are FORBIDDENBYTE, as expected.\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100659 r" The block was made by call #[0-9]+ to debug malloc/realloc.\n"
Victor Stinnerb3adb1a2016-03-14 17:40:09 +0100660 r" Data at p: cb cb cb .*\n"
Victor Stinner6453e9e2016-03-15 23:36:28 +0100661 r"\n"
Victor Stinner34be8072016-03-14 12:04:26 +0100662 r"Fatal Python error: bad ID: Allocated using API 'm', verified using API 'r'\n")
Victor Stinnera1bc28a2016-03-14 17:10:36 +0100663 regex = regex.format(ptr=self.PTR_REGEX)
Victor Stinner34be8072016-03-14 12:04:26 +0100664 self.assertRegex(out, regex)
665
Victor Stinnerad524372016-03-16 12:12:53 +0100666 def check_malloc_without_gil(self, code):
Victor Stinnerc4aec362016-03-14 22:26:53 +0100667 out = self.check(code)
668 expected = ('Fatal Python error: Python memory allocator called '
669 'without holding the GIL')
670 self.assertIn(expected, out)
Victor Stinner34be8072016-03-14 12:04:26 +0100671
Victor Stinnerad524372016-03-16 12:12:53 +0100672 def test_pymem_malloc_without_gil(self):
673 # Debug hooks must raise an error if PyMem_Malloc() is called
674 # without holding the GIL
675 code = 'import _testcapi; _testcapi.pymem_malloc_without_gil()'
676 self.check_malloc_without_gil(code)
677
678 def test_pyobject_malloc_without_gil(self):
679 # Debug hooks must raise an error if PyObject_Malloc() is called
680 # without holding the GIL
681 code = 'import _testcapi; _testcapi.pyobject_malloc_without_gil()'
682 self.check_malloc_without_gil(code)
683
Victor Stinnerc4aec362016-03-14 22:26:53 +0100684
685class PyMemMallocDebugTests(PyMemDebugTests):
686 PYTHONMALLOC = 'malloc_debug'
Victor Stinner34be8072016-03-14 12:04:26 +0100687
688
Victor Stinner5d39e042017-11-29 17:20:38 +0100689@unittest.skipUnless(support.with_pymalloc(), 'need pymalloc')
Victor Stinnerc4aec362016-03-14 22:26:53 +0100690class PyMemPymallocDebugTests(PyMemDebugTests):
691 PYTHONMALLOC = 'pymalloc_debug'
Victor Stinner34be8072016-03-14 12:04:26 +0100692
693
694@unittest.skipUnless(Py_DEBUG, 'need Py_DEBUG')
Victor Stinnerc4aec362016-03-14 22:26:53 +0100695class PyMemDefaultTests(PyMemDebugTests):
696 # test default allocator of Python compiled in debug mode
697 PYTHONMALLOC = ''
Victor Stinner34be8072016-03-14 12:04:26 +0100698
699
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000700if __name__ == "__main__":
Zachary Warec12f09e2013-11-11 22:47:04 -0600701 unittest.main()