blob: 0f5fa7c5d17ec80cd23b36a780af13630925faa8 [file] [log] [blame]
Tim Peters9ea17ac2001-02-02 05:57:15 +00001/*
2 * C Extension module to test Python interpreter C APIs.
3 *
4 * The 'test_*' functions exported by this module are run as part of the
5 * standard Python regression test, via Lib/test/test_capi.py.
6 */
7
8#include "Python.h"
9
10static PyObject *TestError; /* set to exception object in init */
11
Tim Peters91621db2001-06-12 20:10:01 +000012/* Raise TestError with test_name + ": " + msg, and return NULL. */
13
14static PyObject *
15raiseTestError(const char* test_name, const char* msg)
16{
17 char buf[2048];
18
19 if (strlen(test_name) + strlen(msg) > sizeof(buf) - 50)
20 PyErr_SetString(TestError, "internal error msg too large");
21 else {
Tim Peters885d4572001-11-28 20:27:42 +000022 PyOS_snprintf(buf, sizeof(buf), "%s: %s", test_name, msg);
Tim Peters91621db2001-06-12 20:10:01 +000023 PyErr_SetString(TestError, buf);
24 }
25 return NULL;
26}
27
Martin v. Löwis4f1cd8b2001-07-26 13:41:06 +000028/* Test #defines from pyconfig.h (particularly the SIZEOF_* defines).
Tim Peters9ea17ac2001-02-02 05:57:15 +000029
30 The ones derived from autoconf on the UNIX-like OSes can be relied
31 upon (in the absence of sloppy cross-compiling), but the Windows
32 platforms have these hardcoded. Better safe than sorry.
33*/
34static PyObject*
35sizeof_error(const char* fatname, const char* typename,
36 int expected, int got)
37{
38 char buf[1024];
Tim Peters885d4572001-11-28 20:27:42 +000039 PyOS_snprintf(buf, sizeof(buf),
40 "%.200s #define == %d but sizeof(%.200s) == %d",
Tim Peters9ea17ac2001-02-02 05:57:15 +000041 fatname, expected, typename, got);
42 PyErr_SetString(TestError, buf);
43 return (PyObject*)NULL;
44}
45
46static PyObject*
47test_config(PyObject *self, PyObject *args)
48{
49 if (!PyArg_ParseTuple(args, ":test_config"))
50 return NULL;
51
52#define CHECK_SIZEOF(FATNAME, TYPE) \
53 if (FATNAME != sizeof(TYPE)) \
54 return sizeof_error(#FATNAME, #TYPE, FATNAME, sizeof(TYPE))
55
Tim Peters208efe52001-06-26 22:40:47 +000056 CHECK_SIZEOF(SIZEOF_SHORT, short);
Tim Peters9ea17ac2001-02-02 05:57:15 +000057 CHECK_SIZEOF(SIZEOF_INT, int);
58 CHECK_SIZEOF(SIZEOF_LONG, long);
59 CHECK_SIZEOF(SIZEOF_VOID_P, void*);
60 CHECK_SIZEOF(SIZEOF_TIME_T, time_t);
61#ifdef HAVE_LONG_LONG
62 CHECK_SIZEOF(SIZEOF_LONG_LONG, LONG_LONG);
63#endif
64
65#undef CHECK_SIZEOF
66
67 Py_INCREF(Py_None);
68 return Py_None;
69}
70
Tim Peters5c4d5bf2001-02-12 22:13:26 +000071static PyObject*
72test_list_api(PyObject *self, PyObject *args)
73{
74 PyObject* list;
75 int i;
76 if (!PyArg_ParseTuple(args, ":test_list_api"))
77 return NULL;
78
79 /* SF bug 132008: PyList_Reverse segfaults */
80#define NLIST 30
81 list = PyList_New(NLIST);
82 if (list == (PyObject*)NULL)
83 return (PyObject*)NULL;
84 /* list = range(NLIST) */
85 for (i = 0; i < NLIST; ++i) {
86 PyObject* anint = PyInt_FromLong(i);
87 if (anint == (PyObject*)NULL) {
88 Py_DECREF(list);
89 return (PyObject*)NULL;
90 }
91 PyList_SET_ITEM(list, i, anint);
92 }
93 /* list.reverse(), via PyList_Reverse() */
94 i = PyList_Reverse(list); /* should not blow up! */
95 if (i != 0) {
96 Py_DECREF(list);
97 return (PyObject*)NULL;
98 }
99 /* Check that list == range(29, -1, -1) now */
100 for (i = 0; i < NLIST; ++i) {
101 PyObject* anint = PyList_GET_ITEM(list, i);
102 if (PyInt_AS_LONG(anint) != NLIST-1-i) {
103 PyErr_SetString(TestError,
104 "test_list_api: reverse screwed up");
105 Py_DECREF(list);
106 return (PyObject*)NULL;
107 }
108 }
109 Py_DECREF(list);
110#undef NLIST
111
112 Py_INCREF(Py_None);
113 return Py_None;
114}
115
Guido van Rossumeb0d9922001-04-13 17:08:15 +0000116static int
117test_dict_inner(int count)
118{
119 int pos = 0, iterations = 0, i;
120 PyObject *dict = PyDict_New();
121 PyObject *v, *k;
122
123 if (dict == NULL)
124 return -1;
125
126 for (i = 0; i < count; i++) {
127 v = PyInt_FromLong(i);
128 PyDict_SetItem(dict, v, v);
129 Py_DECREF(v);
130 }
131
132 while (PyDict_Next(dict, &pos, &k, &v)) {
133 PyObject *o;
134 iterations++;
135
136 i = PyInt_AS_LONG(v) + 1;
137 o = PyInt_FromLong(i);
138 if (o == NULL)
139 return -1;
140 if (PyDict_SetItem(dict, k, o) < 0) {
141 Py_DECREF(o);
142 return -1;
143 }
144 Py_DECREF(o);
145 }
146
147 Py_DECREF(dict);
148
149 if (iterations != count) {
150 PyErr_SetString(
151 TestError,
152 "test_dict_iteration: dict iteration went wrong ");
153 return -1;
154 } else {
155 return 0;
156 }
157}
158
159static PyObject*
160test_dict_iteration(PyObject* self, PyObject* args)
161{
162 int i;
163
164 if (!PyArg_ParseTuple(args, ":test_dict_iteration"))
165 return NULL;
Tim Peters91621db2001-06-12 20:10:01 +0000166
Guido van Rossumeb0d9922001-04-13 17:08:15 +0000167 for (i = 0; i < 200; i++) {
168 if (test_dict_inner(i) < 0) {
169 return NULL;
170 }
171 }
172
173 Py_INCREF(Py_None);
174 return Py_None;
175}
176
Tim Peters91621db2001-06-12 20:10:01 +0000177
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000178/* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG)
Tim Petersff70d3c2001-06-14 01:11:03 +0000179 PyLong_{As, From}{Unsigned,}LongLong().
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000180
181 Note that the meat of the test is contained in testcapi_long.h.
182 This is revolting, but delicate code duplication is worse: "almost
183 exactly the same" code is needed to test LONG_LONG, but the ubiquitous
184 dependence on type names makes it impossible to use a parameterized
185 function. A giant macro would be even worse than this. A C++ template
186 would be perfect.
187
188 The "report an error" functions are deliberately not part of the #include
189 file: if the test fails, you can set a breakpoint in the appropriate
190 error function directly, and crawl back from there in the debugger.
191*/
192
193#define UNBIND(X) Py_DECREF(X); (X) = NULL
194
195static PyObject *
196raise_test_long_error(const char* msg)
197{
198 return raiseTestError("test_long_api", msg);
199}
200
201#define TESTNAME test_long_api_inner
202#define TYPENAME long
203#define F_S_TO_PY PyLong_FromLong
204#define F_PY_TO_S PyLong_AsLong
205#define F_U_TO_PY PyLong_FromUnsignedLong
206#define F_PY_TO_U PyLong_AsUnsignedLong
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000207
208#include "testcapi_long.h"
209
210static PyObject *
211test_long_api(PyObject* self, PyObject* args)
212{
213 if (!PyArg_ParseTuple(args, ":test_long_api"))
214 return NULL;
215
Tim Peters83c9edc2001-06-16 08:10:13 +0000216 return TESTNAME(raise_test_long_error);
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000217}
218
219#undef TESTNAME
220#undef TYPENAME
221#undef F_S_TO_PY
222#undef F_PY_TO_S
223#undef F_U_TO_PY
224#undef F_PY_TO_U
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000225
226#ifdef HAVE_LONG_LONG
Tim Peters91621db2001-06-12 20:10:01 +0000227
228static PyObject *
Tim Petersd1a7da62001-06-13 00:35:57 +0000229raise_test_longlong_error(const char* msg)
230{
231 return raiseTestError("test_longlong_api", msg);
232}
233
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000234#define TESTNAME test_longlong_api_inner
235#define TYPENAME LONG_LONG
236#define F_S_TO_PY PyLong_FromLongLong
237#define F_PY_TO_S PyLong_AsLongLong
238#define F_U_TO_PY PyLong_FromUnsignedLongLong
239#define F_PY_TO_U PyLong_AsUnsignedLongLong
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000240
241#include "testcapi_long.h"
Tim Petersd1a7da62001-06-13 00:35:57 +0000242
243static PyObject *
Tim Peters91621db2001-06-12 20:10:01 +0000244test_longlong_api(PyObject* self, PyObject* args)
245{
Tim Peters91621db2001-06-12 20:10:01 +0000246 if (!PyArg_ParseTuple(args, ":test_longlong_api"))
247 return NULL;
248
Tim Peters83c9edc2001-06-16 08:10:13 +0000249 return TESTNAME(raise_test_longlong_error);
Tim Peters91621db2001-06-12 20:10:01 +0000250}
251
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000252#undef TESTNAME
253#undef TYPENAME
254#undef F_S_TO_PY
255#undef F_PY_TO_S
256#undef F_U_TO_PY
257#undef F_PY_TO_U
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000258
Tim Petersd38b1c72001-09-30 05:09:37 +0000259/* Test the L code for PyArg_ParseTuple. This should deliver a LONG_LONG
260 for both long and int arguments. The test may leak a little memory if
261 it fails.
262*/
263static PyObject *
264test_L_code(PyObject *self, PyObject *args)
265{
266 PyObject *tuple, *num;
267 LONG_LONG value;
268
269 if (!PyArg_ParseTuple(args, ":test_L_code"))
270 return NULL;
271
272 tuple = PyTuple_New(1);
273 if (tuple == NULL)
274 return NULL;
275
276 num = PyLong_FromLong(42);
277 if (num == NULL)
278 return NULL;
279
280 PyTuple_SET_ITEM(tuple, 0, num);
281
282 value = -1;
283 if (PyArg_ParseTuple(tuple, "L:test_L_code", &value) < 0)
284 return NULL;
285 if (value != 42)
286 return raiseTestError("test_L_code",
287 "L code returned wrong value for long 42");
288
289 Py_DECREF(num);
290 num = PyInt_FromLong(42);
291 if (num == NULL)
292 return NULL;
293
294 PyTuple_SET_ITEM(tuple, 0, num);
295
296 value = -1;
297 if (PyArg_ParseTuple(tuple, "L:test_L_code", &value) < 0)
298 return NULL;
299 if (value != 42)
300 return raiseTestError("test_L_code",
301 "L code returned wrong value for int 42");
302
303 Py_DECREF(tuple);
304 Py_INCREF(Py_None);
305 return Py_None;
306}
307
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000308#endif /* ifdef HAVE_LONG_LONG */
309
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000310static PyObject *
311raise_exception(PyObject *self, PyObject *args)
312{
313 PyObject *exc;
314 PyObject *exc_args, *v;
315 int num_args, i;
316
317 if (!PyArg_ParseTuple(args, "Oi:raise_exception",
318 &exc, &num_args))
319 return NULL;
320
321 exc_args = PyTuple_New(num_args);
322 if (exc_args == NULL)
323 return NULL;
324 for (i = 0; i < num_args; ++i) {
325 v = PyInt_FromLong(i);
326 if (v == NULL) {
327 Py_DECREF(exc_args);
328 return NULL;
329 }
330 PyTuple_SET_ITEM(exc_args, i, v);
331 }
332 PyErr_SetObject(exc, exc_args);
333 return NULL;
334}
Tim Peters91621db2001-06-12 20:10:01 +0000335
Tim Peters9ea17ac2001-02-02 05:57:15 +0000336static PyMethodDef TestMethods[] = {
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000337 {"raise_exception", raise_exception, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000338 {"test_config", test_config, METH_VARARGS},
339 {"test_list_api", test_list_api, METH_VARARGS},
340 {"test_dict_iteration", test_dict_iteration, METH_VARARGS},
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000341 {"test_long_api", test_long_api, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000342#ifdef HAVE_LONG_LONG
343 {"test_longlong_api", test_longlong_api, METH_VARARGS},
Tim Petersd38b1c72001-09-30 05:09:37 +0000344 {"test_L_code", test_L_code, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000345#endif
Tim Peters9ea17ac2001-02-02 05:57:15 +0000346 {NULL, NULL} /* sentinel */
347};
348
349DL_EXPORT(void)
Tim Petersd66595f2001-02-04 03:09:53 +0000350init_testcapi(void)
Tim Peters9ea17ac2001-02-02 05:57:15 +0000351{
352 PyObject *m, *d;
353
Tim Petersd66595f2001-02-04 03:09:53 +0000354 m = Py_InitModule("_testcapi", TestMethods);
Tim Peters9ea17ac2001-02-02 05:57:15 +0000355
Tim Petersd66595f2001-02-04 03:09:53 +0000356 TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Tim Peters9ea17ac2001-02-02 05:57:15 +0000357 d = PyModule_GetDict(m);
358 PyDict_SetItemString(d, "error", TestError);
359}