blob: b17a277b9cf10b9df5e6297ccf9b0b68160a85b7 [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 {
22 sprintf(buf, "%s: %s", test_name, msg);
23 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];
39 sprintf(buf, "%s #define == %d but sizeof(%s) == %d",
40 fatname, expected, typename, got);
41 PyErr_SetString(TestError, buf);
42 return (PyObject*)NULL;
43}
44
45static PyObject*
46test_config(PyObject *self, PyObject *args)
47{
48 if (!PyArg_ParseTuple(args, ":test_config"))
49 return NULL;
50
51#define CHECK_SIZEOF(FATNAME, TYPE) \
52 if (FATNAME != sizeof(TYPE)) \
53 return sizeof_error(#FATNAME, #TYPE, FATNAME, sizeof(TYPE))
54
Tim Peters208efe52001-06-26 22:40:47 +000055 CHECK_SIZEOF(SIZEOF_SHORT, short);
Tim Peters9ea17ac2001-02-02 05:57:15 +000056 CHECK_SIZEOF(SIZEOF_INT, int);
57 CHECK_SIZEOF(SIZEOF_LONG, long);
58 CHECK_SIZEOF(SIZEOF_VOID_P, void*);
59 CHECK_SIZEOF(SIZEOF_TIME_T, time_t);
60#ifdef HAVE_LONG_LONG
61 CHECK_SIZEOF(SIZEOF_LONG_LONG, LONG_LONG);
62#endif
63
64#undef CHECK_SIZEOF
65
66 Py_INCREF(Py_None);
67 return Py_None;
68}
69
Tim Peters5c4d5bf2001-02-12 22:13:26 +000070static PyObject*
71test_list_api(PyObject *self, PyObject *args)
72{
73 PyObject* list;
74 int i;
75 if (!PyArg_ParseTuple(args, ":test_list_api"))
76 return NULL;
77
78 /* SF bug 132008: PyList_Reverse segfaults */
79#define NLIST 30
80 list = PyList_New(NLIST);
81 if (list == (PyObject*)NULL)
82 return (PyObject*)NULL;
83 /* list = range(NLIST) */
84 for (i = 0; i < NLIST; ++i) {
85 PyObject* anint = PyInt_FromLong(i);
86 if (anint == (PyObject*)NULL) {
87 Py_DECREF(list);
88 return (PyObject*)NULL;
89 }
90 PyList_SET_ITEM(list, i, anint);
91 }
92 /* list.reverse(), via PyList_Reverse() */
93 i = PyList_Reverse(list); /* should not blow up! */
94 if (i != 0) {
95 Py_DECREF(list);
96 return (PyObject*)NULL;
97 }
98 /* Check that list == range(29, -1, -1) now */
99 for (i = 0; i < NLIST; ++i) {
100 PyObject* anint = PyList_GET_ITEM(list, i);
101 if (PyInt_AS_LONG(anint) != NLIST-1-i) {
102 PyErr_SetString(TestError,
103 "test_list_api: reverse screwed up");
104 Py_DECREF(list);
105 return (PyObject*)NULL;
106 }
107 }
108 Py_DECREF(list);
109#undef NLIST
110
111 Py_INCREF(Py_None);
112 return Py_None;
113}
114
Guido van Rossumeb0d9922001-04-13 17:08:15 +0000115static int
116test_dict_inner(int count)
117{
118 int pos = 0, iterations = 0, i;
119 PyObject *dict = PyDict_New();
120 PyObject *v, *k;
121
122 if (dict == NULL)
123 return -1;
124
125 for (i = 0; i < count; i++) {
126 v = PyInt_FromLong(i);
127 PyDict_SetItem(dict, v, v);
128 Py_DECREF(v);
129 }
130
131 while (PyDict_Next(dict, &pos, &k, &v)) {
132 PyObject *o;
133 iterations++;
134
135 i = PyInt_AS_LONG(v) + 1;
136 o = PyInt_FromLong(i);
137 if (o == NULL)
138 return -1;
139 if (PyDict_SetItem(dict, k, o) < 0) {
140 Py_DECREF(o);
141 return -1;
142 }
143 Py_DECREF(o);
144 }
145
146 Py_DECREF(dict);
147
148 if (iterations != count) {
149 PyErr_SetString(
150 TestError,
151 "test_dict_iteration: dict iteration went wrong ");
152 return -1;
153 } else {
154 return 0;
155 }
156}
157
158static PyObject*
159test_dict_iteration(PyObject* self, PyObject* args)
160{
161 int i;
162
163 if (!PyArg_ParseTuple(args, ":test_dict_iteration"))
164 return NULL;
Tim Peters91621db2001-06-12 20:10:01 +0000165
Guido van Rossumeb0d9922001-04-13 17:08:15 +0000166 for (i = 0; i < 200; i++) {
167 if (test_dict_inner(i) < 0) {
168 return NULL;
169 }
170 }
171
172 Py_INCREF(Py_None);
173 return Py_None;
174}
175
Tim Peters91621db2001-06-12 20:10:01 +0000176
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000177/* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG)
Tim Petersff70d3c2001-06-14 01:11:03 +0000178 PyLong_{As, From}{Unsigned,}LongLong().
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000179
180 Note that the meat of the test is contained in testcapi_long.h.
181 This is revolting, but delicate code duplication is worse: "almost
182 exactly the same" code is needed to test LONG_LONG, but the ubiquitous
183 dependence on type names makes it impossible to use a parameterized
184 function. A giant macro would be even worse than this. A C++ template
185 would be perfect.
186
187 The "report an error" functions are deliberately not part of the #include
188 file: if the test fails, you can set a breakpoint in the appropriate
189 error function directly, and crawl back from there in the debugger.
190*/
191
192#define UNBIND(X) Py_DECREF(X); (X) = NULL
193
194static PyObject *
195raise_test_long_error(const char* msg)
196{
197 return raiseTestError("test_long_api", msg);
198}
199
200#define TESTNAME test_long_api_inner
201#define TYPENAME long
202#define F_S_TO_PY PyLong_FromLong
203#define F_PY_TO_S PyLong_AsLong
204#define F_U_TO_PY PyLong_FromUnsignedLong
205#define F_PY_TO_U PyLong_AsUnsignedLong
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000206
207#include "testcapi_long.h"
208
209static PyObject *
210test_long_api(PyObject* self, PyObject* args)
211{
212 if (!PyArg_ParseTuple(args, ":test_long_api"))
213 return NULL;
214
Tim Peters83c9edc2001-06-16 08:10:13 +0000215 return TESTNAME(raise_test_long_error);
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000216}
217
218#undef TESTNAME
219#undef TYPENAME
220#undef F_S_TO_PY
221#undef F_PY_TO_S
222#undef F_U_TO_PY
223#undef F_PY_TO_U
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000224
225#ifdef HAVE_LONG_LONG
Tim Peters91621db2001-06-12 20:10:01 +0000226
227static PyObject *
Tim Petersd1a7da62001-06-13 00:35:57 +0000228raise_test_longlong_error(const char* msg)
229{
230 return raiseTestError("test_longlong_api", msg);
231}
232
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000233#define TESTNAME test_longlong_api_inner
234#define TYPENAME LONG_LONG
235#define F_S_TO_PY PyLong_FromLongLong
236#define F_PY_TO_S PyLong_AsLongLong
237#define F_U_TO_PY PyLong_FromUnsignedLongLong
238#define F_PY_TO_U PyLong_AsUnsignedLongLong
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000239
240#include "testcapi_long.h"
Tim Petersd1a7da62001-06-13 00:35:57 +0000241
242static PyObject *
Tim Peters91621db2001-06-12 20:10:01 +0000243test_longlong_api(PyObject* self, PyObject* args)
244{
Tim Peters91621db2001-06-12 20:10:01 +0000245 if (!PyArg_ParseTuple(args, ":test_longlong_api"))
246 return NULL;
247
Tim Peters83c9edc2001-06-16 08:10:13 +0000248 return TESTNAME(raise_test_longlong_error);
Tim Peters91621db2001-06-12 20:10:01 +0000249}
250
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000251#undef TESTNAME
252#undef TYPENAME
253#undef F_S_TO_PY
254#undef F_PY_TO_S
255#undef F_U_TO_PY
256#undef F_PY_TO_U
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000257
Tim Petersd38b1c72001-09-30 05:09:37 +0000258/* Test the L code for PyArg_ParseTuple. This should deliver a LONG_LONG
259 for both long and int arguments. The test may leak a little memory if
260 it fails.
261*/
262static PyObject *
263test_L_code(PyObject *self, PyObject *args)
264{
265 PyObject *tuple, *num;
266 LONG_LONG value;
267
268 if (!PyArg_ParseTuple(args, ":test_L_code"))
269 return NULL;
270
271 tuple = PyTuple_New(1);
272 if (tuple == NULL)
273 return NULL;
274
275 num = PyLong_FromLong(42);
276 if (num == NULL)
277 return NULL;
278
279 PyTuple_SET_ITEM(tuple, 0, num);
280
281 value = -1;
282 if (PyArg_ParseTuple(tuple, "L:test_L_code", &value) < 0)
283 return NULL;
284 if (value != 42)
285 return raiseTestError("test_L_code",
286 "L code returned wrong value for long 42");
287
288 Py_DECREF(num);
289 num = PyInt_FromLong(42);
290 if (num == NULL)
291 return NULL;
292
293 PyTuple_SET_ITEM(tuple, 0, num);
294
295 value = -1;
296 if (PyArg_ParseTuple(tuple, "L:test_L_code", &value) < 0)
297 return NULL;
298 if (value != 42)
299 return raiseTestError("test_L_code",
300 "L code returned wrong value for int 42");
301
302 Py_DECREF(tuple);
303 Py_INCREF(Py_None);
304 return Py_None;
305}
306
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000307#endif /* ifdef HAVE_LONG_LONG */
308
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000309static PyObject *
310raise_exception(PyObject *self, PyObject *args)
311{
312 PyObject *exc;
313 PyObject *exc_args, *v;
314 int num_args, i;
315
316 if (!PyArg_ParseTuple(args, "Oi:raise_exception",
317 &exc, &num_args))
318 return NULL;
319
320 exc_args = PyTuple_New(num_args);
321 if (exc_args == NULL)
322 return NULL;
323 for (i = 0; i < num_args; ++i) {
324 v = PyInt_FromLong(i);
325 if (v == NULL) {
326 Py_DECREF(exc_args);
327 return NULL;
328 }
329 PyTuple_SET_ITEM(exc_args, i, v);
330 }
331 PyErr_SetObject(exc, exc_args);
332 return NULL;
333}
Tim Peters91621db2001-06-12 20:10:01 +0000334
Tim Peters9ea17ac2001-02-02 05:57:15 +0000335static PyMethodDef TestMethods[] = {
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000336 {"raise_exception", raise_exception, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000337 {"test_config", test_config, METH_VARARGS},
338 {"test_list_api", test_list_api, METH_VARARGS},
339 {"test_dict_iteration", test_dict_iteration, METH_VARARGS},
Tim Peterse7c1f9b2001-06-14 00:55:41 +0000340 {"test_long_api", test_long_api, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000341#ifdef HAVE_LONG_LONG
342 {"test_longlong_api", test_longlong_api, METH_VARARGS},
Tim Petersd38b1c72001-09-30 05:09:37 +0000343 {"test_L_code", test_L_code, METH_VARARGS},
Tim Peters91621db2001-06-12 20:10:01 +0000344#endif
Tim Peters9ea17ac2001-02-02 05:57:15 +0000345 {NULL, NULL} /* sentinel */
346};
347
348DL_EXPORT(void)
Tim Petersd66595f2001-02-04 03:09:53 +0000349init_testcapi(void)
Tim Peters9ea17ac2001-02-02 05:57:15 +0000350{
351 PyObject *m, *d;
352
Tim Petersd66595f2001-02-04 03:09:53 +0000353 m = Py_InitModule("_testcapi", TestMethods);
Tim Peters9ea17ac2001-02-02 05:57:15 +0000354
Tim Petersd66595f2001-02-04 03:09:53 +0000355 TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Tim Peters9ea17ac2001-02-02 05:57:15 +0000356 d = PyModule_GetDict(m);
357 PyDict_SetItemString(d, "error", TestError);
358}