| /* |
| * C Extension module to test Python interpreter C APIs. |
| * |
| * The 'test_*' functions exported by this module are run as part of the |
| * standard Python regression test, via Lib/test/test_capi.py. |
| */ |
| |
| #include "Python.h" |
| |
| static PyObject *TestError; /* set to exception object in init */ |
| |
| /* Test #defines from config.h (particularly the SIZEOF_* defines). |
| |
| The ones derived from autoconf on the UNIX-like OSes can be relied |
| upon (in the absence of sloppy cross-compiling), but the Windows |
| platforms have these hardcoded. Better safe than sorry. |
| */ |
| static PyObject* |
| sizeof_error(const char* fatname, const char* typename, |
| int expected, int got) |
| { |
| char buf[1024]; |
| sprintf(buf, "%s #define == %d but sizeof(%s) == %d", |
| fatname, expected, typename, got); |
| PyErr_SetString(TestError, buf); |
| return (PyObject*)NULL; |
| } |
| |
| static PyObject* |
| test_config(PyObject *self, PyObject *args) |
| { |
| if (!PyArg_ParseTuple(args, ":test_config")) |
| return NULL; |
| |
| #define CHECK_SIZEOF(FATNAME, TYPE) \ |
| if (FATNAME != sizeof(TYPE)) \ |
| return sizeof_error(#FATNAME, #TYPE, FATNAME, sizeof(TYPE)) |
| |
| CHECK_SIZEOF(SIZEOF_INT, int); |
| CHECK_SIZEOF(SIZEOF_LONG, long); |
| CHECK_SIZEOF(SIZEOF_VOID_P, void*); |
| CHECK_SIZEOF(SIZEOF_TIME_T, time_t); |
| #ifdef HAVE_LONG_LONG |
| CHECK_SIZEOF(SIZEOF_LONG_LONG, LONG_LONG); |
| #endif |
| |
| #undef CHECK_SIZEOF |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| |
| static PyObject* |
| test_list_api(PyObject *self, PyObject *args) |
| { |
| PyObject* list; |
| int i; |
| if (!PyArg_ParseTuple(args, ":test_list_api")) |
| return NULL; |
| |
| /* SF bug 132008: PyList_Reverse segfaults */ |
| #define NLIST 30 |
| list = PyList_New(NLIST); |
| if (list == (PyObject*)NULL) |
| return (PyObject*)NULL; |
| /* list = range(NLIST) */ |
| for (i = 0; i < NLIST; ++i) { |
| PyObject* anint = PyInt_FromLong(i); |
| if (anint == (PyObject*)NULL) { |
| Py_DECREF(list); |
| return (PyObject*)NULL; |
| } |
| PyList_SET_ITEM(list, i, anint); |
| } |
| /* list.reverse(), via PyList_Reverse() */ |
| i = PyList_Reverse(list); /* should not blow up! */ |
| if (i != 0) { |
| Py_DECREF(list); |
| return (PyObject*)NULL; |
| } |
| /* Check that list == range(29, -1, -1) now */ |
| for (i = 0; i < NLIST; ++i) { |
| PyObject* anint = PyList_GET_ITEM(list, i); |
| if (PyInt_AS_LONG(anint) != NLIST-1-i) { |
| PyErr_SetString(TestError, |
| "test_list_api: reverse screwed up"); |
| Py_DECREF(list); |
| return (PyObject*)NULL; |
| } |
| } |
| Py_DECREF(list); |
| #undef NLIST |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| |
| static int |
| test_dict_inner(int count) |
| { |
| int pos = 0, iterations = 0, i; |
| PyObject *dict = PyDict_New(); |
| PyObject *v, *k; |
| |
| if (dict == NULL) |
| return -1; |
| |
| for (i = 0; i < count; i++) { |
| v = PyInt_FromLong(i); |
| PyDict_SetItem(dict, v, v); |
| Py_DECREF(v); |
| } |
| |
| while (PyDict_Next(dict, &pos, &k, &v)) { |
| PyObject *o; |
| iterations++; |
| |
| i = PyInt_AS_LONG(v) + 1; |
| o = PyInt_FromLong(i); |
| if (o == NULL) |
| return -1; |
| if (PyDict_SetItem(dict, k, o) < 0) { |
| Py_DECREF(o); |
| return -1; |
| } |
| Py_DECREF(o); |
| } |
| |
| Py_DECREF(dict); |
| |
| if (iterations != count) { |
| PyErr_SetString( |
| TestError, |
| "test_dict_iteration: dict iteration went wrong "); |
| return -1; |
| } else { |
| return 0; |
| } |
| } |
| |
| static PyObject* |
| test_dict_iteration(PyObject* self, PyObject* args) |
| { |
| int i; |
| |
| if (!PyArg_ParseTuple(args, ":test_dict_iteration")) |
| return NULL; |
| |
| for (i = 0; i < 200; i++) { |
| if (test_dict_inner(i) < 0) { |
| return NULL; |
| } |
| } |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| |
| static PyMethodDef TestMethods[] = { |
| {"test_config", test_config, METH_VARARGS}, |
| {"test_list_api", test_list_api, METH_VARARGS}, |
| {"test_dict_iteration", test_dict_iteration, METH_VARARGS}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| DL_EXPORT(void) |
| init_testcapi(void) |
| { |
| PyObject *m, *d; |
| |
| m = Py_InitModule("_testcapi", TestMethods); |
| |
| TestError = PyErr_NewException("_testcapi.error", NULL, NULL); |
| d = PyModule_GetDict(m); |
| PyDict_SetItemString(d, "error", TestError); |
| } |