Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Enhance tests
  • Loading branch information
vstinner committed Jun 20, 2023
commit 4589377993d50d86cc72a47be62d223b958b9da4
4 changes: 0 additions & 4 deletions Lib/test/test_weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,10 +967,6 @@ def __del__(self): pass
del x
support.gc_collect()

@support.cpython_only
def test_capi(self):
import _testcapi
_testcapi.check_weakref_capi(C)

class SubclassableWeakrefTestCase(TestBase):

Expand Down
41 changes: 26 additions & 15 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3373,17 +3373,23 @@ check_pyimport_addmodule(PyObject *self, PyObject *args)


static PyObject *
check_weakref_capi(PyObject *self, PyObject *factory)
test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
// obj = factory()
PyObject *obj = PyObject_CallNoArgs(factory);
// Create a new heap type, create an instance of this type, and delete the
// type. This object supports weak references.
PyObject *new_type = PyObject_CallFunction((PyObject*)&PyType_Type,
"s(){}", "TypeName");
if (new_type == NULL) {
return NULL;
}
PyObject *obj = PyObject_CallNoArgs(new_type);
Py_DECREF(new_type);
if (obj == NULL) {
return NULL;
}
Py_ssize_t refcnt = Py_REFCNT(obj);
assert(refcnt == 1);

// test PyWeakref_NewRef()
// test PyWeakref_NewRef(), reference is alive
PyObject *weakref = PyWeakref_NewRef(obj, NULL);
if (weakref == NULL) {
Py_DECREF(obj);
Expand All @@ -3394,28 +3400,30 @@ check_weakref_capi(PyObject *self, PyObject *factory)
assert(PyWeakref_CheckRefExact(weakref));
assert(Py_REFCNT(obj) == refcnt);

// test PyWeakref_GetRef()
// test PyWeakref_GetRef(), reference is alive
PyObject *ref1;
assert(PyWeakref_GetRef(weakref, &ref1) == 0);
assert(ref1 == obj);
assert(Py_REFCNT(obj) == (refcnt + 1));
Py_DECREF(ref1);

// test PyWeakref_GetObject()
// test PyWeakref_GetObject(), reference is alive
PyObject *ref2 = PyWeakref_GetObject(weakref);
assert(ref2 == obj);
assert(Py_REFCNT(obj) == refcnt);

// test PyWeakref_GET_OBJECT()
// test PyWeakref_GET_OBJECT(), reference is alive
PyObject *ref3 = PyWeakref_GET_OBJECT(weakref);
assert(ref3 == obj);
assert(Py_REFCNT(obj) == refcnt);

// delete the object
assert(refcnt == 1);
// delete the referenced object
assert(Py_REFCNT(obj) == 1);
Py_DECREF(obj);

// test PyWeakref_GET_OBJECT(), reference is dead
assert(PyWeakref_GET_OBJECT(weakref) == Py_None);
PyObject *ref4;

// test PyWeakref_GetRef(), reference is dead
PyObject *ref4 = Py_True; // marker to check that value was set
assert(PyWeakref_GetRef(weakref, &ref4) == 0);
assert(ref4 == NULL);

Expand All @@ -3425,12 +3433,15 @@ check_weakref_capi(PyObject *self, PyObject *factory)
assert(!PyWeakref_CheckRefExact(invalid_weakref));
assert(!PyWeakref_CheckRefExact(invalid_weakref));

// test PyWeakref_GetRef(), invalid type
assert(!PyErr_Occurred());
PyObject *ref5 = factory; // marker to check that value was set
PyObject *ref5 = Py_True; // marker to check that value was set
assert(PyWeakref_GetRef(invalid_weakref, &ref5) == -1);
assert(PyErr_ExceptionMatches(PyExc_TypeError));
PyErr_Clear();
assert(ref5 == NULL);

// test PyWeakref_GetObject(), invalid type
assert(PyWeakref_GetObject(invalid_weakref) == NULL);
assert(PyErr_ExceptionMatches(PyExc_SystemError));
PyErr_Clear();
Expand Down Expand Up @@ -3583,7 +3594,7 @@ static PyMethodDef TestMethods[] = {
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
{"test_atexit", test_atexit, METH_NOARGS},
{"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
{"check_weakref_capi", check_weakref_capi, METH_O},
{"test_weakref_capi", test_weakref_capi, METH_NOARGS},
{NULL, NULL} /* sentinel */
};

Expand Down