diff options
author | Jurica Bradarić <jbradaric@users.noreply.github.com> | 2023-05-12 09:26:07 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-12 09:26:07 (GMT) |
commit | 19ee53d52e8adf267dfd588c2142967734a3b65a (patch) | |
tree | e7d963dcf359c4f447fa8d68c018c6cb2a066c6f /Modules/_testcapimodule.c | |
parent | b2c1b4da1935639cb89fbbad0ce170a1182537bd (diff) | |
download | cpython-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.c | 329 |
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); |