summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapimodule.c
diff options
context:
space:
mode:
authorJurica Bradarić <jbradaric@users.noreply.github.com>2023-05-12 09:26:07 (GMT)
committerGitHub <noreply@github.com>2023-05-12 09:26:07 (GMT)
commit19ee53d52e8adf267dfd588c2142967734a3b65a (patch)
treee7d963dcf359c4f447fa8d68c018c6cb2a066c6f /Modules/_testcapimodule.c
parentb2c1b4da1935639cb89fbbad0ce170a1182537bd (diff)
downloadcpython-19ee53d52e8adf267dfd588c2142967734a3b65a.zip
cpython-19ee53d52e8adf267dfd588c2142967734a3b65a.tar.gz
cpython-19ee53d52e8adf267dfd588c2142967734a3b65a.tar.bz2
gh-93649: Split gc- and allocation tests from _testcapimodule.c (GH-104403)
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r--Modules/_testcapimodule.c329
1 files changed, 3 insertions, 326 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 79ab7d3..c29d29c 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -155,68 +155,6 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored))
}
static PyObject*
-test_gc_control(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
- int orig_enabled = PyGC_IsEnabled();
- const char* msg = "ok";
- int old_state;
-
- old_state = PyGC_Enable();
- msg = "Enable(1)";
- if (old_state != orig_enabled) {
- goto failed;
- }
- msg = "IsEnabled(1)";
- if (!PyGC_IsEnabled()) {
- goto failed;
- }
-
- old_state = PyGC_Disable();
- msg = "disable(2)";
- if (!old_state) {
- goto failed;
- }
- msg = "IsEnabled(2)";
- if (PyGC_IsEnabled()) {
- goto failed;
- }
-
- old_state = PyGC_Enable();
- msg = "enable(3)";
- if (old_state) {
- goto failed;
- }
- msg = "IsEnabled(3)";
- if (!PyGC_IsEnabled()) {
- goto failed;
- }
-
- if (!orig_enabled) {
- old_state = PyGC_Disable();
- msg = "disable(4)";
- if (old_state) {
- goto failed;
- }
- msg = "IsEnabled(4)";
- if (PyGC_IsEnabled()) {
- goto failed;
- }
- }
-
- Py_RETURN_NONE;
-
-failed:
- /* Try to clean up if we can. */
- if (orig_enabled) {
- PyGC_Enable();
- } else {
- PyGC_Disable();
- }
- PyErr_Format(TestError, "GC control failed in %s", msg);
- return NULL;
-}
-
-static PyObject*
test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored))
{
PyObject* list;
@@ -1627,95 +1565,6 @@ restore_crossinterp_data(PyObject *self, PyObject *args)
return _PyCrossInterpreterData_NewObject(data);
}
-static void
-slot_tp_del(PyObject *self)
-{
- PyObject *del, *res;
-
- /* Temporarily resurrect the object. */
- assert(Py_REFCNT(self) == 0);
- Py_SET_REFCNT(self, 1);
-
- /* Save the current exception, if any. */
- PyObject *exc = PyErr_GetRaisedException();
-
- PyObject *tp_del = PyUnicode_InternFromString("__tp_del__");
- if (tp_del == NULL) {
- PyErr_WriteUnraisable(NULL);
- PyErr_SetRaisedException(exc);
- return;
- }
- /* Execute __del__ method, if any. */
- del = _PyType_Lookup(Py_TYPE(self), tp_del);
- Py_DECREF(tp_del);
- if (del != NULL) {
- res = PyObject_CallOneArg(del, self);
- if (res == NULL)
- PyErr_WriteUnraisable(del);
- else
- Py_DECREF(res);
- }
-
- /* Restore the saved exception. */
- PyErr_SetRaisedException(exc);
-
- /* Undo the temporary resurrection; can't use DECREF here, it would
- * cause a recursive call.
- */
- assert(Py_REFCNT(self) > 0);
- Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
- if (Py_REFCNT(self) == 0) {
- /* this is the normal path out */
- return;
- }
-
- /* __del__ resurrected it! Make it look like the original Py_DECREF
- * never happened.
- */
- {
- Py_ssize_t refcnt = Py_REFCNT(self);
- _Py_NewReferenceNoTotal(self);
- Py_SET_REFCNT(self, refcnt);
- }
- assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self));
-}
-
-static PyObject *
-with_tp_del(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- PyTypeObject *tp;
-
- if (!PyArg_ParseTuple(args, "O:with_tp_del", &obj))
- return NULL;
- tp = (PyTypeObject *) obj;
- if (!PyType_Check(obj) || !PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(PyExc_TypeError,
- "heap type expected, got %R", obj);
- return NULL;
- }
- tp->tp_del = slot_tp_del;
- return Py_NewRef(obj);
-}
-
-static PyObject *
-without_gc(PyObject *Py_UNUSED(self), PyObject *obj)
-{
- PyTypeObject *tp = (PyTypeObject*)obj;
- if (!PyType_Check(obj) || !PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
- return PyErr_Format(PyExc_TypeError, "heap type expected, got %R", obj);
- }
- if (PyType_IS_GC(tp)) {
- // Don't try this at home, kids:
- tp->tp_flags -= Py_TPFLAGS_HAVE_GC;
- tp->tp_free = PyObject_Del;
- tp->tp_traverse = NULL;
- tp->tp_clear = NULL;
- }
- assert(!PyType_IS_GC(tp));
- return Py_NewRef(obj);
-}
-
static PyMethodDef ml;
static PyObject *
@@ -3342,165 +3191,6 @@ function_set_kw_defaults(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-struct gc_visit_state_basic {
- PyObject *target;
- int found;
-};
-
-static int
-gc_visit_callback_basic(PyObject *obj, void *arg)
-{
- struct gc_visit_state_basic *state = (struct gc_visit_state_basic *)arg;
- if (obj == state->target) {
- state->found = 1;
- return 0;
- }
- return 1;
-}
-
-static PyObject *
-test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
- PyObject *Py_UNUSED(ignored))
-{
- PyObject *obj;
- struct gc_visit_state_basic state;
-
- obj = PyList_New(0);
- if (obj == NULL) {
- return NULL;
- }
- state.target = obj;
- state.found = 0;
-
- PyUnstable_GC_VisitObjects(gc_visit_callback_basic, &state);
- Py_DECREF(obj);
- if (!state.found) {
- PyErr_SetString(
- PyExc_AssertionError,
- "test_gc_visit_objects_basic: Didn't find live list");
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-static int
-gc_visit_callback_exit_early(PyObject *obj, void *arg)
- {
- int *visited_i = (int *)arg;
- (*visited_i)++;
- if (*visited_i == 2) {
- return 0;
- }
- return 1;
-}
-
-static PyObject *
-test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self),
- PyObject *Py_UNUSED(ignored))
-{
- int visited_i = 0;
- PyUnstable_GC_VisitObjects(gc_visit_callback_exit_early, &visited_i);
- if (visited_i != 2) {
- PyErr_SetString(
- PyExc_AssertionError,
- "test_gc_visit_objects_exit_early: did not exit when expected");
- }
- Py_RETURN_NONE;
-}
-
-typedef struct {
- PyObject_HEAD
-} ObjExtraData;
-
-static PyObject *
-obj_extra_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- size_t extra_size = sizeof(PyObject *);
- PyObject *obj = PyUnstable_Object_GC_NewWithExtraData(type, extra_size);
- if (obj == NULL) {
- return PyErr_NoMemory();
- }
- PyObject_GC_Track(obj);
- return obj;
-}
-
-static PyObject **
-obj_extra_data_get_extra_storage(PyObject *self)
-{
- return (PyObject **)((char *)self + Py_TYPE(self)->tp_basicsize);
-}
-
-static PyObject *
-obj_extra_data_get(PyObject *self, void *Py_UNUSED(ignored))
-{
- PyObject **extra_storage = obj_extra_data_get_extra_storage(self);
- PyObject *value = *extra_storage;
- if (!value) {
- Py_RETURN_NONE;
- }
- return Py_NewRef(value);
-}
-
-static int
-obj_extra_data_set(PyObject *self, PyObject *newval, void *Py_UNUSED(ignored))
-{
- PyObject **extra_storage = obj_extra_data_get_extra_storage(self);
- Py_CLEAR(*extra_storage);
- if (newval) {
- *extra_storage = Py_NewRef(newval);
- }
- return 0;
-}
-
-static PyGetSetDef obj_extra_data_getset[] = {
- {"extra", (getter)obj_extra_data_get, (setter)obj_extra_data_set, NULL},
- {NULL}
-};
-
-static int
-obj_extra_data_traverse(PyObject *self, visitproc visit, void *arg)
-{
- PyObject **extra_storage = obj_extra_data_get_extra_storage(self);
- PyObject *value = *extra_storage;
- Py_VISIT(value);
- return 0;
-}
-
-static int
-obj_extra_data_clear(PyObject *self)
-{
- PyObject **extra_storage = obj_extra_data_get_extra_storage(self);
- Py_CLEAR(*extra_storage);
- return 0;
-}
-
-static void
-obj_extra_data_dealloc(PyObject *self)
-{
- PyTypeObject *tp = Py_TYPE(self);
- PyObject_GC_UnTrack(self);
- obj_extra_data_clear(self);
- tp->tp_free(self);
- Py_DECREF(tp);
-}
-
-static PyType_Slot ObjExtraData_Slots[] = {
- {Py_tp_getset, obj_extra_data_getset},
- {Py_tp_dealloc, obj_extra_data_dealloc},
- {Py_tp_traverse, obj_extra_data_traverse},
- {Py_tp_clear, obj_extra_data_clear},
- {Py_tp_new, obj_extra_data_new},
- {Py_tp_free, PyObject_GC_Del},
- {0, NULL},
-};
-
-static PyType_Spec ObjExtraData_TypeSpec = {
- .name = "_testcapi.ObjExtraData",
- .basicsize = sizeof(ObjExtraData),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- .slots = ObjExtraData_Slots,
-};
-
struct atexit_data {
int called;
};
@@ -3538,7 +3228,6 @@ static PyMethodDef TestMethods[] = {
{"set_errno", set_errno, METH_VARARGS},
{"test_config", test_config, METH_NOARGS},
{"test_sizeof_c_types", test_sizeof_c_types, METH_NOARGS},
- {"test_gc_control", test_gc_control, METH_NOARGS},
{"test_list_api", test_list_api, METH_NOARGS},
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
{"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},
@@ -3590,7 +3279,6 @@ static PyMethodDef TestMethods[] = {
METH_VARARGS | METH_KEYWORDS},
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
- {"with_tp_del", with_tp_del, METH_VARARGS},
{"create_cfunction", create_cfunction, METH_NOARGS},
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS,
PyDoc_STR("set_error_class(error_class) -> None")},
@@ -3641,7 +3329,6 @@ static PyMethodDef TestMethods[] = {
{"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL},
{"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS},
{"pynumber_tobase", pynumber_tobase, METH_VARARGS},
- {"without_gc", without_gc, METH_O},
{"test_set_type_size", test_set_type_size, METH_NOARGS},
{"test_py_clear", test_py_clear, METH_NOARGS},
{"test_py_setref", test_py_setref, METH_NOARGS},
@@ -3675,8 +3362,6 @@ static PyMethodDef TestMethods[] = {
{"function_set_defaults", function_set_defaults, METH_VARARGS, NULL},
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
- {"test_gc_visit_objects_basic", test_gc_visit_objects_basic, METH_NOARGS, NULL},
- {"test_gc_visit_objects_exit_early", test_gc_visit_objects_exit_early, METH_NOARGS, NULL},
{"test_atexit", test_atexit, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
@@ -4223,17 +3908,6 @@ PyInit__testcapi(void)
Py_INCREF(&MethStatic_Type);
PyModule_AddObject(m, "MethStatic", (PyObject *)&MethStatic_Type);
- PyObject *ObjExtraData_Type = PyType_FromModuleAndSpec(
- m, &ObjExtraData_TypeSpec, NULL);
- if (ObjExtraData_Type == 0) {
- return NULL;
- }
- int ret = PyModule_AddType(m, (PyTypeObject*)ObjExtraData_Type);
- Py_DECREF(ObjExtraData_Type);
- if (ret < 0) {
- return NULL;
- }
-
PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX));
PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN));
PyModule_AddObject(m, "UCHAR_MAX", PyLong_FromLong(UCHAR_MAX));
@@ -4327,6 +4001,9 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_Immortal(m) < 0) {
return NULL;
}
+ if (_PyTestCapi_Init_GC(m) < 0) {
+ return NULL;
+ }
#ifndef LIMITED_API_AVAILABLE
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);