@@ -3372,6 +3372,84 @@ check_pyimport_addmodule(PyObject *self, PyObject *args)
3372
3372
}
3373
3373
3374
3374
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
+
3375
3453
static PyMethodDef TestMethods [] = {
3376
3454
{"set_errno" , set_errno , METH_VARARGS },
3377
3455
{"test_config" , test_config , METH_NOARGS },
@@ -3516,6 +3594,7 @@ static PyMethodDef TestMethods[] = {
3516
3594
{"function_set_kw_defaults" , function_set_kw_defaults , METH_VARARGS , NULL },
3517
3595
{"test_atexit" , test_atexit , METH_NOARGS },
3518
3596
{"check_pyimport_addmodule" , check_pyimport_addmodule , METH_VARARGS },
3597
+ {"test_weakref_capi" , test_weakref_capi , METH_NOARGS },
3519
3598
{NULL , NULL } /* sentinel */
3520
3599
};
3521
3600
0 commit comments