summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapimodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r--Modules/_testcapimodule.c452
1 files changed, 442 insertions, 10 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index cf4b0e1..d77d1db 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -12,6 +12,11 @@
#include "structmember.h"
#include "datetime.h"
#include "marshal.h"
+#include <signal.h>
+
+#ifdef MS_WINDOWS
+# include <winsock2.h> /* struct timeval */
+#endif
#ifdef WITH_THREAD
#include "pythread.h"
@@ -68,6 +73,10 @@ test_config(PyObject *self)
static PyObject*
test_sizeof_c_types(PyObject *self)
{
+#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
#define CHECK_SIZEOF(TYPE, EXPECTED) \
if (EXPECTED != sizeof(TYPE)) { \
PyErr_Format(TestError, \
@@ -125,6 +134,9 @@ test_sizeof_c_types(PyObject *self)
#undef IS_SIGNED
#undef CHECK_SIGNESS
#undef CHECK_SIZEOF
+#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
+#pragma GCC diagnostic pop
+#endif
}
@@ -1719,7 +1731,7 @@ test_long_numbits(PyObject *self)
{-0xffffL, 16, -1},
{0xfffffffL, 28, 1},
{-0xfffffffL, 28, -1}};
- int i;
+ size_t i;
for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
size_t nbits;
@@ -2468,7 +2480,7 @@ make_memoryview_from_NULL_pointer(PyObject *self)
return NULL;
return PyMemoryView_FromBuffer(&info);
}
-
+
static PyObject *
test_from_contiguous(PyObject* self, PyObject *noargs)
{
@@ -2519,6 +2531,58 @@ test_from_contiguous(PyObject* self, PyObject *noargs)
Py_RETURN_NONE;
}
+#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__)
+extern PyTypeObject _PyBytesIOBuffer_Type;
+
+static PyObject *
+test_pep3118_obsolete_write_locks(PyObject* self, PyObject *noargs)
+{
+ PyTypeObject *type = &_PyBytesIOBuffer_Type;
+ PyObject *b;
+ char *dummy[1];
+ int ret, match;
+
+ /* PyBuffer_FillInfo() */
+ ret = PyBuffer_FillInfo(NULL, NULL, dummy, 1, 0, PyBUF_SIMPLE);
+ match = PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_BufferError);
+ PyErr_Clear();
+ if (ret != -1 || match == 0)
+ goto error;
+
+ /* bytesiobuf_getbuffer() */
+ b = type->tp_alloc(type, 0);
+ if (b == NULL) {
+ return NULL;
+ }
+
+ ret = PyObject_GetBuffer(b, NULL, PyBUF_SIMPLE);
+ Py_DECREF(b);
+ match = PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_BufferError);
+ PyErr_Clear();
+ if (ret != -1 || match == 0)
+ goto error;
+
+ Py_RETURN_NONE;
+
+error:
+ PyErr_SetString(TestError,
+ "test_pep3118_obsolete_write_locks: failure");
+ return NULL;
+}
+#endif
+
+/* This tests functions that historically supported write locks. It is
+ wrong to call getbuffer() with view==NULL and a compliant getbufferproc
+ is entitled to segfault in that case. */
+static PyObject *
+getbuffer_with_null_view(PyObject* self, PyObject *obj)
+{
+ if (PyObject_GetBuffer(obj, NULL, PyBUF_SIMPLE) < 0)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
/* Test that the fatal error from not having a current thread doesn't
cause an infinite loop. Run via Lib/test/test_capi.py */
static PyObject *
@@ -2570,7 +2634,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
static int
check_time_rounding(int round)
{
- if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP) {
+ if (round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) {
PyErr_SetString(PyExc_ValueError, "invalid rounding");
return -1;
}
@@ -2703,6 +2767,21 @@ with_tp_del(PyObject *self, PyObject *args)
return obj;
}
+static PyMethodDef ml;
+
+static PyObject *
+create_cfunction(PyObject *self, PyObject *args)
+{
+ return PyCFunction_NewEx(&ml, self, NULL);
+}
+
+static PyMethodDef ml = {
+ "create_cfunction",
+ create_cfunction,
+ METH_NOARGS,
+ NULL
+};
+
static PyObject *
_test_incref(PyObject *ob)
{
@@ -2761,6 +2840,20 @@ test_pymem_alloc0(PyObject *self)
{
void *ptr;
+ ptr = PyMem_RawMalloc(0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_RawMalloc(0) returns NULL");
+ return NULL;
+ }
+ PyMem_RawFree(ptr);
+
+ ptr = PyMem_RawCalloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_RawCalloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyMem_RawFree(ptr);
+
ptr = PyMem_Malloc(0);
if (ptr == NULL) {
PyErr_SetString(PyExc_RuntimeError, "PyMem_Malloc(0) returns NULL");
@@ -2768,6 +2861,13 @@ test_pymem_alloc0(PyObject *self)
}
PyMem_Free(ptr);
+ ptr = PyMem_Calloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_Calloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyMem_Free(ptr);
+
ptr = PyObject_Malloc(0);
if (ptr == NULL) {
PyErr_SetString(PyExc_RuntimeError, "PyObject_Malloc(0) returns NULL");
@@ -2775,13 +2875,22 @@ test_pymem_alloc0(PyObject *self)
}
PyObject_Free(ptr);
+ ptr = PyObject_Calloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyObject_Calloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyObject_Free(ptr);
+
Py_RETURN_NONE;
}
typedef struct {
- PyMemAllocator alloc;
+ PyMemAllocatorEx alloc;
size_t malloc_size;
+ size_t calloc_nelem;
+ size_t calloc_elsize;
void *realloc_ptr;
size_t realloc_new_size;
void *free_ptr;
@@ -2794,6 +2903,14 @@ static void* hook_malloc (void* ctx, size_t size)
return hook->alloc.malloc(hook->alloc.ctx, size);
}
+static void* hook_calloc (void* ctx, size_t nelem, size_t elsize)
+{
+ alloc_hook_t *hook = (alloc_hook_t *)ctx;
+ hook->calloc_nelem = nelem;
+ hook->calloc_elsize = elsize;
+ return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize);
+}
+
static void* hook_realloc (void* ctx, void* ptr, size_t new_size)
{
alloc_hook_t *hook = (alloc_hook_t *)ctx;
@@ -2815,17 +2932,15 @@ test_setallocators(PyMemAllocatorDomain domain)
PyObject *res = NULL;
const char *error_msg;
alloc_hook_t hook;
- PyMemAllocator alloc;
- size_t size, size2;
+ PyMemAllocatorEx alloc;
+ size_t size, size2, nelem, elsize;
void *ptr, *ptr2;
- hook.malloc_size = 0;
- hook.realloc_ptr = NULL;
- hook.realloc_new_size = 0;
- hook.free_ptr = NULL;
+ memset(&hook, 0, sizeof(hook));
alloc.ctx = &hook;
alloc.malloc = &hook_malloc;
+ alloc.calloc = &hook_calloc;
alloc.realloc = &hook_realloc;
alloc.free = &hook_free;
PyMem_GetAllocator(domain, &hook.alloc);
@@ -2882,6 +2997,33 @@ test_setallocators(PyMemAllocatorDomain domain)
goto fail;
}
+ nelem = 2;
+ elsize = 5;
+ switch(domain)
+ {
+ case PYMEM_DOMAIN_RAW: ptr = PyMem_RawCalloc(nelem, elsize); break;
+ case PYMEM_DOMAIN_MEM: ptr = PyMem_Calloc(nelem, elsize); break;
+ case PYMEM_DOMAIN_OBJ: ptr = PyObject_Calloc(nelem, elsize); break;
+ default: ptr = NULL; break;
+ }
+
+ if (ptr == NULL) {
+ error_msg = "calloc failed";
+ goto fail;
+ }
+
+ if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) {
+ error_msg = "calloc invalid nelem or elsize";
+ goto fail;
+ }
+
+ switch(domain)
+ {
+ case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break;
+ case PYMEM_DOMAIN_MEM: PyMem_Free(ptr); break;
+ case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break;
+ }
+
Py_INCREF(Py_None);
res = Py_None;
goto finally;
@@ -2941,6 +3083,12 @@ PyDoc_STRVAR(docstring_with_signature,
"This docstring has a valid signature."
);
+PyDoc_STRVAR(docstring_with_signature_but_no_doc,
+"docstring_with_signature_but_no_doc($module, /, sig)\n"
+"--\n"
+"\n"
+);
+
PyDoc_STRVAR(docstring_with_signature_and_extra_newlines,
"docstring_with_signature_and_extra_newlines($module, /, parameter)\n"
"--\n"
@@ -3051,6 +3199,24 @@ exit:
}
#endif /* WITH_THREAD */
+static PyObject*
+test_raise_signal(PyObject* self, PyObject *args)
+{
+ int signum, err;
+
+ if (PyArg_ParseTuple(args, "i:raise_signal", &signum) < 0)
+ return NULL;
+
+ err = raise(signum);
+ if (err)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ if (PyErr_CheckSignals() < 0)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
/* marshal */
static PyObject*
@@ -3204,6 +3370,142 @@ pymarshal_read_object_from_file(PyObject* self, PyObject *args)
return Py_BuildValue("Nl", obj, pos);
}
+static PyObject*
+return_null_without_error(PyObject *self, PyObject *args)
+{
+ /* invalid call: return NULL without setting an error,
+ * _Py_CheckFunctionResult() must detect such bug at runtime. */
+ PyErr_Clear();
+ return NULL;
+}
+
+static PyObject*
+return_result_with_error(PyObject *self, PyObject *args)
+{
+ /* invalid call: return a result with an error set,
+ * _Py_CheckFunctionResult() must detect such bug at runtime. */
+ PyErr_SetNone(PyExc_ValueError);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+test_pytime_fromseconds(PyObject *self, PyObject *args)
+{
+ int seconds;
+ _PyTime_t ts;
+
+ if (!PyArg_ParseTuple(args, "i", &seconds))
+ return NULL;
+ ts = _PyTime_FromSeconds(seconds);
+ return _PyTime_AsNanosecondsObject(ts);
+}
+
+static PyObject *
+test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ _PyTime_t ts;
+
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
+ return NULL;
+ if (check_time_rounding(round) < 0)
+ return NULL;
+ if (_PyTime_FromSecondsObject(&ts, obj, round) == -1)
+ return NULL;
+ return _PyTime_AsNanosecondsObject(ts);
+}
+
+static PyObject *
+test_pytime_assecondsdouble(PyObject *self, PyObject *args)
+{
+ PY_LONG_LONG ns;
+ _PyTime_t ts;
+ double d;
+
+ if (!PyArg_ParseTuple(args, "L", &ns))
+ return NULL;
+ ts = _PyTime_FromNanoseconds(ns);
+ d = _PyTime_AsSecondsDouble(ts);
+ return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+test_PyTime_AsTimeval(PyObject *self, PyObject *args)
+{
+ PY_LONG_LONG ns;
+ int round;
+ _PyTime_t t;
+ struct timeval tv;
+ PyObject *seconds;
+
+ if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ return NULL;
+ if (check_time_rounding(round) < 0)
+ return NULL;
+ t = _PyTime_FromNanoseconds(ns);
+ if (_PyTime_AsTimeval(t, &tv, round) < 0)
+ return NULL;
+
+ seconds = PyLong_FromLong((PY_LONG_LONG)tv.tv_sec);
+ if (seconds == NULL)
+ return NULL;
+ return Py_BuildValue("Nl", seconds, tv.tv_usec);
+}
+
+#ifdef HAVE_CLOCK_GETTIME
+static PyObject *
+test_PyTime_AsTimespec(PyObject *self, PyObject *args)
+{
+ PY_LONG_LONG ns;
+ _PyTime_t t;
+ struct timespec ts;
+
+ if (!PyArg_ParseTuple(args, "L", &ns))
+ return NULL;
+ t = _PyTime_FromNanoseconds(ns);
+ if (_PyTime_AsTimespec(t, &ts) == -1)
+ return NULL;
+ return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
+}
+#endif
+
+static PyObject *
+test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
+{
+ PY_LONG_LONG ns;
+ int round;
+ _PyTime_t t, ms;
+
+ if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ return NULL;
+ if (check_time_rounding(round) < 0)
+ return NULL;
+ t = _PyTime_FromNanoseconds(ns);
+ ms = _PyTime_AsMilliseconds(t, round);
+ /* This conversion rely on the fact that _PyTime_t is a number of
+ nanoseconds */
+ return _PyTime_AsNanosecondsObject(ms);
+}
+
+static PyObject *
+test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
+{
+ PY_LONG_LONG ns;
+ int round;
+ _PyTime_t t, ms;
+
+ if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ return NULL;
+ if (check_time_rounding(round) < 0)
+ return NULL;
+ t = _PyTime_FromNanoseconds(ns);
+ ms = _PyTime_AsMicroseconds(t, round);
+ /* This conversion rely on the fact that _PyTime_t is a number of
+ nanoseconds */
+ return _PyTime_AsNanosecondsObject(ms);
+}
+
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
@@ -3236,6 +3538,10 @@ static PyMethodDef TestMethods[] = {
{"test_unicode_compare_with_ascii", (PyCFunction)test_unicode_compare_with_ascii, METH_NOARGS},
{"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
{"test_from_contiguous", (PyCFunction)test_from_contiguous, METH_NOARGS},
+#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__)
+ {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS},
+#endif
+ {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
{"getargs_tuple", getargs_tuple, METH_VARARGS},
{"getargs_keywords", (PyCFunction)getargs_keywords,
METH_VARARGS|METH_KEYWORDS},
@@ -3309,6 +3615,7 @@ static PyMethodDef TestMethods[] = {
{"pytime_object_to_timeval", test_pytime_object_to_timeval, METH_VARARGS},
{"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
{"with_tp_del", with_tp_del, METH_VARARGS},
+ {"create_cfunction", create_cfunction, METH_NOARGS},
{"test_pymem_alloc0",
(PyCFunction)test_pymem_alloc0, METH_NOARGS},
{"test_pymem_setrawallocators",
@@ -3334,12 +3641,17 @@ static PyMethodDef TestMethods[] = {
{"docstring_with_signature",
(PyCFunction)test_with_docstring, METH_NOARGS,
docstring_with_signature},
+ {"docstring_with_signature_but_no_doc",
+ (PyCFunction)test_with_docstring, METH_NOARGS,
+ docstring_with_signature_but_no_doc},
{"docstring_with_signature_and_extra_newlines",
(PyCFunction)test_with_docstring, METH_NOARGS,
docstring_with_signature_and_extra_newlines},
{"docstring_with_signature_with_defaults",
(PyCFunction)test_with_docstring, METH_NOARGS,
docstring_with_signature_with_defaults},
+ {"raise_signal",
+ (PyCFunction)test_raise_signal, METH_VARARGS},
#ifdef WITH_THREAD
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O,
PyDoc_STR("set_error_class(error_class) -> None")},
@@ -3356,6 +3668,19 @@ static PyMethodDef TestMethods[] = {
pymarshal_read_last_object_from_file, METH_VARARGS},
{"pymarshal_read_object_from_file",
pymarshal_read_object_from_file, METH_VARARGS},
+ {"return_null_without_error",
+ return_null_without_error, METH_NOARGS},
+ {"return_result_with_error",
+ return_result_with_error, METH_NOARGS},
+ {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS},
+ {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS},
+ {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
+ {"PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS},
+#ifdef HAVE_CLOCK_GETTIME
+ {"PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS},
+#endif
+ {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
+ {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
@@ -3515,6 +3840,109 @@ static PyTypeObject test_structmembersType = {
};
+typedef struct {
+ PyObject_HEAD
+} matmulObject;
+
+static PyObject *
+matmulType_matmul(PyObject *self, PyObject *other)
+{
+ return Py_BuildValue("(sOO)", "matmul", self, other);
+}
+
+static PyObject *
+matmulType_imatmul(PyObject *self, PyObject *other)
+{
+ return Py_BuildValue("(sOO)", "imatmul", self, other);
+}
+
+static void
+matmulType_dealloc(PyObject *self)
+{
+ Py_TYPE(self)->tp_free(self);
+}
+
+static PyNumberMethods matmulType_as_number = {
+ 0, /* nb_add */
+ 0, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_remainde r*/
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* tp_positive */
+ 0, /* tp_absolute */
+ 0, /* tp_bool */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ 0, /* nb_and */
+ 0, /* nb_xor */
+ 0, /* nb_or */
+ 0, /* nb_int */
+ 0, /* nb_reserved */
+ 0, /* nb_float */
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+ 0, /* nb_index */
+ matmulType_matmul, /* nb_matrix_multiply */
+ matmulType_imatmul /* nb_matrix_inplace_multiply */
+};
+
+static PyTypeObject matmulType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "matmulType",
+ sizeof(matmulObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ matmulType_dealloc, /* destructor tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ &matmulType_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ "C level type with matrix operations defined",
+ 0, /* traverseproc tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ PyType_GenericNew, /* tp_new */
+ PyObject_Del, /* tp_free */
+};
+
static struct PyModuleDef _testcapimodule = {
PyModuleDef_HEAD_INIT,
@@ -3544,6 +3972,10 @@ PyInit__testcapi(void)
/* don't use a name starting with "test", since we don't want
test_capi to automatically call this */
PyModule_AddObject(m, "_test_structmembersType", (PyObject *)&test_structmembersType);
+ if (PyType_Ready(&matmulType) < 0)
+ return NULL;
+ Py_INCREF(&matmulType);
+ PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType);
PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX));
PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN));