@@ -3372,6 +3372,84 @@ check_pyimport_addmodule(PyObject *self, PyObject *args)
33723372}
33733373
33743374
3375+ static PyObject *
3376+ test_weakref_capi (PyObject * Py_UNUSED (module ), PyObject * Py_UNUSED (args ))
3377+ {
3378+ // Create a new heap type, create an instance of this type, and delete the
3379+ // type. This object supports weak references.
3380+ PyObject * new_type = PyObject_CallFunction ((PyObject * )& PyType_Type ,
3381+ "s(){}" , "TypeName" );
3382+ if (new_type == NULL ) {
3383+ return NULL ;
3384+ }
3385+ PyObject * obj = PyObject_CallNoArgs (new_type );
3386+ Py_DECREF (new_type );
3387+ if (obj == NULL ) {
3388+ return NULL ;
3389+ }
3390+ Py_ssize_t refcnt = Py_REFCNT (obj );
3391+
3392+ // test PyWeakref_NewRef(), reference is alive
3393+ PyObject * weakref = PyWeakref_NewRef (obj , NULL );
3394+ if (weakref == NULL ) {
3395+ Py_DECREF (obj );
3396+ return NULL ;
3397+ }
3398+ assert (PyWeakref_Check (weakref ));
3399+ assert (PyWeakref_CheckRefExact (weakref ));
3400+ assert (PyWeakref_CheckRefExact (weakref ));
3401+ assert (Py_REFCNT (obj ) == refcnt );
3402+
3403+ // test PyWeakref_GetRef(), reference is alive
3404+ PyObject * ref1 ;
3405+ assert (PyWeakref_GetRef (weakref , & ref1 ) == 0 );
3406+ assert (ref1 == obj );
3407+ assert (Py_REFCNT (obj ) == (refcnt + 1 ));
3408+ Py_DECREF (ref1 );
3409+
3410+ // test PyWeakref_GetObject(), reference is alive
3411+ PyObject * ref2 = PyWeakref_GetObject (weakref );
3412+ assert (ref2 == obj );
3413+
3414+ // test PyWeakref_GET_OBJECT(), reference is alive
3415+ PyObject * ref3 = PyWeakref_GET_OBJECT (weakref );
3416+ assert (ref3 == obj );
3417+
3418+ // delete the referenced object
3419+ assert (Py_REFCNT (obj ) == 1 );
3420+ Py_DECREF (obj );
3421+
3422+ // test PyWeakref_GET_OBJECT(), reference is dead
3423+ assert (PyWeakref_GET_OBJECT (weakref ) == Py_None );
3424+
3425+ // test PyWeakref_GetRef(), reference is dead
3426+ PyObject * ref4 = Py_True ; // marker to check that value was set
3427+ assert (PyWeakref_GetRef (weakref , & ref4 ) == 0 );
3428+ assert (ref4 == NULL );
3429+
3430+ // None is not a weak reference object
3431+ PyObject * invalid_weakref = Py_None ;
3432+ assert (!PyWeakref_Check (invalid_weakref ));
3433+ assert (!PyWeakref_CheckRefExact (invalid_weakref ));
3434+ assert (!PyWeakref_CheckRefExact (invalid_weakref ));
3435+
3436+ // test PyWeakref_GetRef(), invalid type
3437+ assert (!PyErr_Occurred ());
3438+ PyObject * ref5 = Py_True ; // marker to check that value was set
3439+ assert (PyWeakref_GetRef (invalid_weakref , & ref5 ) == -1 );
3440+ assert (PyErr_ExceptionMatches (PyExc_TypeError ));
3441+ PyErr_Clear ();
3442+ assert (ref5 == NULL );
3443+
3444+ // test PyWeakref_GetObject(), invalid type
3445+ assert (PyWeakref_GetObject (invalid_weakref ) == NULL );
3446+ assert (PyErr_ExceptionMatches (PyExc_SystemError ));
3447+ PyErr_Clear ();
3448+
3449+ Py_RETURN_NONE ;
3450+ }
3451+
3452+
33753453static PyMethodDef TestMethods [] = {
33763454 {"set_errno" , set_errno , METH_VARARGS },
33773455 {"test_config" , test_config , METH_NOARGS },
@@ -3516,6 +3594,7 @@ static PyMethodDef TestMethods[] = {
35163594 {"function_set_kw_defaults" , function_set_kw_defaults , METH_VARARGS , NULL },
35173595 {"test_atexit" , test_atexit , METH_NOARGS },
35183596 {"check_pyimport_addmodule" , check_pyimport_addmodule , METH_VARARGS },
3597+ {"test_weakref_capi" , test_weakref_capi , METH_NOARGS },
35193598 {NULL , NULL } /* sentinel */
35203599};
35213600
0 commit comments