blob: 6f4a5b3a39445d0e7014a22d377eb7e9c4453633 [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
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +00004from __future__ import with_statement
Serhiy Storchakaef19fd22018-07-11 19:49:17 +03005import string
Martin v. Löwis6ce7ed22005-03-03 12:26:35 +00006import sys
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +00007import time
8import random
9import unittest
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030010from test import test_support as support
Victor Stinnerbe595d32010-04-27 23:01:29 +000011try:
Ezio Melottief1db542013-02-23 06:33:51 +020012 import thread
Victor Stinnerbe595d32010-04-27 23:01:29 +000013 import threading
14except ImportError:
Ezio Melottief1db542013-02-23 06:33:51 +020015 thread = None
Victor Stinnerbe595d32010-04-27 23:01:29 +000016 threading = None
Serhiy Storchaka76249ea2014-02-07 10:06:05 +020017# Skip this test if the _testcapi module isn't available.
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030018_testcapi = support.import_module('_testcapi')
Serhiy Storchaka76249ea2014-02-07 10:06:05 +020019
Serhiy Storchaka12cf60c2016-05-20 22:31:24 +030020class CAPITest(unittest.TestCase):
21
22 def test_buildvalue_N(self):
23 _testcapi.test_buildvalue_N()
24
Tim Peters9ea17ac2001-02-02 05:57:15 +000025
Victor Stinnerbe595d32010-04-27 23:01:29 +000026@unittest.skipUnless(threading, 'Threading required for this test.')
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000027class TestPendingCalls(unittest.TestCase):
28
29 def pendingcalls_submit(self, l, n):
30 def callback():
31 #this function can be interrupted by thread switching so let's
32 #use an atomic operation
33 l.append(None)
34
35 for i in range(n):
36 time.sleep(random.random()*0.02) #0.01 secs on average
37 #try submitting callback until successful.
38 #rely on regular interrupt to flush queue if we are
39 #unsuccessful.
40 while True:
41 if _testcapi._pending_threadfunc(callback):
42 break;
43
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000044 def pendingcalls_wait(self, l, n, context = None):
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000045 #now, stick around until l[0] has grown to 10
46 count = 0;
47 while len(l) != n:
48 #this busy loop is where we expect to be interrupted to
49 #run our callbacks. Note that callbacks are only run on the
50 #main thread
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030051 if False and support.verbose:
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000052 print "(%i)"%(len(l),),
53 for i in xrange(1000):
54 a = i*i
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000055 if context and not context.event.is_set():
56 continue
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000057 count += 1
Benjamin Peterson5c8da862009-06-30 22:57:08 +000058 self.assertTrue(count < 10000,
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000059 "timeout waiting for %i callbacks, got %i"%(n, len(l)))
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030060 if False and support.verbose:
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000061 print "(%i)"%(len(l),)
62
63 def test_pendingcalls_threaded(self):
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000064 #do every callback on a separate thread
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000065 n = 32 #total callbacks
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000066 threads = []
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000067 class foo(object):pass
68 context = foo()
69 context.l = []
70 context.n = 2 #submits per thread
Ezio Melottidde5b942010-02-03 05:37:26 +000071 context.nThreads = n // context.n
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000072 context.nFinished = 0
73 context.lock = threading.Lock()
74 context.event = threading.Event()
75
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030076 threads = [threading.Thread(target=self.pendingcalls_thread,
77 args=(context,))
78 for i in range(context.nThreads)]
79 with support.start_threads(threads):
80 self.pendingcalls_wait(context.l, n, context)
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000081
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000082 def pendingcalls_thread(self, context):
83 try:
84 self.pendingcalls_submit(context.l, context.n)
85 finally:
86 with context.lock:
87 context.nFinished += 1
88 nFinished = context.nFinished
Serhiy Storchakabd8c6292015-04-01 12:56:39 +030089 if False and support.verbose:
Kristján Valur Jónsson60e79ce2009-01-18 10:58:44 +000090 print "finished threads: ", nFinished
91 if nFinished == context.nThreads:
92 context.event.set()
93
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000094 def test_pendingcalls_non_threaded(self):
Ezio Melottic2077b02011-03-16 12:34:31 +020095 #again, just using the main thread, likely they will all be dispatched at
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +000096 #once. It is ok to ask for too many, because we loop until we find a slot.
97 #the loop can be interrupted to dispatch.
98 #there are only 32 dispatch slots, so we go for twice that!
99 l = []
100 n = 64
101 self.pendingcalls_submit(l, n)
102 self.pendingcalls_wait(l, n)
103
104
Serhiy Storchakaef19fd22018-07-11 19:49:17 +0300105# Bug #6012
106class Test6012(unittest.TestCase):
107 def test(self):
108 self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
109
110
Xtreak2bea7712018-07-26 21:50:34 +0530111class TestGetIndices(unittest.TestCase):
112
113 def test_get_indices(self):
114 self.assertEqual(_testcapi.get_indices(slice(10L, 20, 1), 100), (0, 10, 20, 1))
115 self.assertEqual(_testcapi.get_indices(slice(10.1, 20, 1), 100), None)
116 self.assertEqual(_testcapi.get_indices(slice(10, 20L, 1), 100), (0, 10, 20, 1))
117 self.assertEqual(_testcapi.get_indices(slice(10, 20.1, 1), 100), None)
118
119 self.assertEqual(_testcapi.get_indices(slice(10L, 20, 1L), 100), (0, 10, 20, 1))
120 self.assertEqual(_testcapi.get_indices(slice(10.1, 20, 1L), 100), None)
121 self.assertEqual(_testcapi.get_indices(slice(10, 20L, 1L), 100), (0, 10, 20, 1))
122 self.assertEqual(_testcapi.get_indices(slice(10, 20.1, 1L), 100), None)
123
124
Serhiy Storchakaef19fd22018-07-11 19:49:17 +0300125class SkipitemTest(unittest.TestCase):
126
127 def test_skipitem(self):
128 """
129 If this test failed, you probably added a new "format unit"
130 in Python/getargs.c, but neglected to update our poor friend
131 skipitem() in the same file. (If so, shame on you!)
132
133 With a few exceptions**, this function brute-force tests all
134 printable ASCII*** characters (32 to 126 inclusive) as format units,
135 checking to see that PyArg_ParseTupleAndKeywords() return consistent
136 errors both when the unit is attempted to be used and when it is
137 skipped. If the format unit doesn't exist, we'll get one of two
138 specific error messages (one for used, one for skipped); if it does
139 exist we *won't* get that error--we'll get either no error or some
140 other error. If we get the specific "does not exist" error for one
141 test and not for the other, there's a mismatch, and the test fails.
142
143 ** Some format units have special funny semantics and it would
144 be difficult to accommodate them here. Since these are all
145 well-established and properly skipped in skipitem() we can
146 get away with not testing them--this test is really intended
147 to catch *new* format units.
148
149 *** Python C source files must be ASCII. Therefore it's impossible
150 to have non-ASCII format units.
151
152 """
153 empty_tuple = ()
154 tuple_1 = (0,)
155 dict_b = {'b':1}
156 keywords = ["a", "b"]
157
158 for i in range(32, 127):
159 c = chr(i)
160
161 # skip parentheses, the error reporting is inconsistent about them
162 # skip 'e', it's always a two-character code
163 # skip '|', it doesn't represent arguments anyway
164 if c in '()e|':
165 continue
166
167 # test the format unit when not skipped
168 format = c + "i"
169 try:
170 _testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
171 format, keywords)
172 when_not_skipped = False
173 except TypeError as e:
174 s = "argument 1 (impossible<bad format char>)"
175 when_not_skipped = (str(e) == s)
176 except RuntimeError:
177 when_not_skipped = False
178
179 # test the format unit when skipped
180 optional_format = "|" + format
181 try:
182 _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
183 optional_format, keywords)
184 when_skipped = False
185 except RuntimeError as e:
186 s = "impossible<bad format char>: '{}'".format(format)
187 when_skipped = (str(e) == s)
188
189 message = ("test_skipitem_parity: "
190 "detected mismatch between convertsimple and skipitem "
191 "for format unit '{}' ({}), not skipped {}, skipped {}".format(
192 c, i, when_skipped, when_not_skipped))
193 self.assertIs(when_skipped, when_not_skipped, message)
194
195 def test_skipitem_with_suffix(self):
196 parse = _testcapi.parse_tuple_and_keywords
197 empty_tuple = ()
198 tuple_1 = (0,)
199 dict_b = {'b':1}
200 keywords = ["a", "b"]
201
202 supported = ('s#', 's*', 'z#', 'z*', 'u#', 't#', 'w#', 'w*')
203 for c in string.ascii_letters:
204 for c2 in '#*':
205 f = c + c2
206 optional_format = "|" + f + "i"
207 if f in supported:
208 parse(empty_tuple, dict_b, optional_format, keywords)
209 else:
210 with self.assertRaisesRegexp((RuntimeError, TypeError),
211 'impossible<bad format char>'):
212 parse(empty_tuple, dict_b, optional_format, keywords)
213
214 for c in map(chr, range(32, 128)):
215 f = 'e' + c
216 optional_format = "|" + f + "i"
217 if c in 'st':
218 parse(empty_tuple, dict_b, optional_format, keywords)
219 else:
220 with self.assertRaisesRegexp(RuntimeError,
221 'impossible<bad format char>'):
222 parse(empty_tuple, dict_b, optional_format, keywords)
223
224 def test_parse_tuple_and_keywords(self):
225 # Test handling errors in the parse_tuple_and_keywords helper itself
226 self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
227 (), {}, 42, [])
228 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
229 (), {}, '', 42)
230 self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
231 (), {}, '', [''] * 42)
232 self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
233 (), {}, '', [42])
234
235 def test_bad_use(self):
236 # Test handling invalid format and keywords in
237 # PyArg_ParseTupleAndKeywords()
238 self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
239 (1,), {}, '||O', ['a'])
240 self.assertRaises(RuntimeError, _testcapi.parse_tuple_and_keywords,
241 (1,), {}, '|O', ['a', 'b'])
242 self.assertRaises(RuntimeError, _testcapi.parse_tuple_and_keywords,
243 (1,), {}, '|OO', ['a'])
244
245
Ezio Melottief1db542013-02-23 06:33:51 +0200246@unittest.skipUnless(threading and thread, 'Threading required for this test.')
Ezio Melotti2fddfd82013-02-23 05:45:37 +0200247class TestThreadState(unittest.TestCase):
Tim Peters59b96c12006-03-21 03:58:41 +0000248
Serhiy Storchakabd8c6292015-04-01 12:56:39 +0300249 @support.reap_threads
Ezio Melotti2fddfd82013-02-23 05:45:37 +0200250 def test_thread_state(self):
251 # some extra thread-state tests driven via _testcapi
252 def target():
253 idents = []
254
255 def callback():
256 idents.append(thread.get_ident())
257
258 _testcapi._test_thread_state(callback)
259 a = b = callback
260 time.sleep(1)
261 # Check our main thread is in the list exactly 3 times.
262 self.assertEqual(idents.count(thread.get_ident()), 3,
263 "Couldn't find main thread correctly in the list")
264
265 target()
266 t = threading.Thread(target=target)
267 t.start()
268 t.join()
269
270
271def test_main():
Tim Peters59b96c12006-03-21 03:58:41 +0000272 for name in dir(_testcapi):
273 if name.startswith('test_'):
274 test = getattr(_testcapi, name)
Serhiy Storchakabd8c6292015-04-01 12:56:39 +0300275 if support.verbose:
Tim Peters59b96c12006-03-21 03:58:41 +0000276 print "internal", name
277 try:
278 test()
279 except _testcapi.error:
Serhiy Storchakabd8c6292015-04-01 12:56:39 +0300280 raise support.TestFailed, sys.exc_info()[1]
Tim Peters59b96c12006-03-21 03:58:41 +0000281
Serhiy Storchakaef19fd22018-07-11 19:49:17 +0300282 support.run_unittest(CAPITest, TestPendingCalls, SkipitemTest,
Xtreak2bea7712018-07-26 21:50:34 +0530283 TestThreadState, TestGetIndices)
Kristján Valur Jónsson0e2d8c32009-01-09 21:35:16 +0000284
Tim Peters59b96c12006-03-21 03:58:41 +0000285if __name__ == "__main__":
286 test_main()