@@ -668,6 +668,78 @@ test_import(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
668668}
669669
670670
671+ static void
672+ gc_collect (void )
673+ {
674+ #if defined(PYPY_VERSION )
675+ PyObject * mod = PyImport_ImportModule ("gc" );
676+ assert (mod != NULL );
677+
678+ PyObject * res = PyObject_CallMethod (mod , "collect" , NULL );
679+ Py_DECREF (mod );
680+ assert (res != NULL );
681+ Py_DECREF (res );
682+ #else
683+ PyGC_Collect ();
684+ #endif
685+ }
686+
687+
688+ static PyObject *
689+ test_weakref (PyObject * Py_UNUSED (module ), PyObject * Py_UNUSED (args ))
690+ {
691+ // Create a new heap type, create an instance of this type, and delete the
692+ // type. This object supports weak references.
693+ PyObject * new_type = PyObject_CallFunction ((PyObject * )& PyType_Type ,
694+ "s(){}" , "TypeName" );
695+ if (new_type == NULL ) {
696+ return NULL ;
697+ }
698+ PyObject * obj = PyObject_CallNoArgs (new_type );
699+ Py_DECREF (new_type );
700+ if (obj == NULL ) {
701+ return NULL ;
702+ }
703+ Py_ssize_t refcnt = Py_REFCNT (obj );
704+
705+ // create a weak reference
706+ PyObject * weakref = PyWeakref_NewRef (obj , NULL );
707+ if (weakref == NULL ) {
708+ return NULL ;
709+ }
710+
711+ // test PyWeakref_GetRef(), reference is alive
712+ PyObject * ref1 ;
713+ assert (PyWeakref_GetRef (weakref , & ref1 ) == 0 );
714+ assert (ref1 == obj );
715+ assert (Py_REFCNT (obj ) == (refcnt + 1 ));
716+ Py_DECREF (ref1 );
717+
718+ // delete the referenced object
719+ assert (Py_REFCNT (obj ) == 1 );
720+ Py_DECREF (obj );
721+ gc_collect ();
722+
723+ // test PyWeakref_GetRef(), reference is dead
724+ PyObject * ref2 = Py_True ; // marker to check that value was set
725+ assert (PyWeakref_GetRef (weakref , & ref2 ) == 0 );
726+ assert (ref2 == NULL );
727+
728+ // test PyWeakref_GetRef(), invalid type
729+ PyObject * invalid_weakref = Py_None ;
730+ assert (!PyErr_Occurred ());
731+ PyObject * ref3 = Py_True ; // marker to check that value was set
732+ assert (PyWeakref_GetRef (invalid_weakref , & ref3 ) == -1 );
733+ assert (PyErr_ExceptionMatches (PyExc_TypeError ));
734+ assert (ref3 == NULL );
735+ PyErr_Clear ();
736+
737+ Py_DECREF (weakref );
738+
739+ Py_RETURN_NONE ;
740+ }
741+
742+
671743static struct PyMethodDef methods [] = {
672744 {"test_object" , test_object , METH_NOARGS , _Py_NULL },
673745 {"test_py_is" , test_py_is , METH_NOARGS , _Py_NULL },
@@ -687,6 +759,7 @@ static struct PyMethodDef methods[] = {
687759#endif
688760 {"test_api_casts" , test_api_casts , METH_NOARGS , _Py_NULL },
689761 {"test_import" , test_import , METH_NOARGS , _Py_NULL },
762+ {"test_weakref" , test_weakref , METH_NOARGS , _Py_NULL },
690763 {_Py_NULL , _Py_NULL , 0 , _Py_NULL }
691764};
692765
0 commit comments