3333#define MODULE_NAME_STR STR(MODULE_NAME)
3434
3535// Ignore reference count checks on PyPy
36- #if !defined( PYPY_VERSION )
36+ #ifndef PYPY_VERSION
3737# define CHECK_REFCNT
3838#endif
3939
@@ -148,7 +148,7 @@ test_py_is(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
148148}
149149
150150
151- #if !defined( PYPY_VERSION )
151+ #ifndef PYPY_VERSION
152152static void
153153test_frame_getvar (PyFrameObject * frame )
154154{
@@ -279,7 +279,7 @@ test_thread_state(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
279279 PyInterpreterState * interp = PyThreadState_GetInterpreter (tstate );
280280 assert (interp != _Py_NULL );
281281
282- #if !defined( PYPY_VERSION )
282+ #ifndef PYPY_VERSION
283283 // test PyThreadState_GetFrame()
284284 PyFrameObject * frame = PyThreadState_GetFrame (tstate );
285285 if (frame != _Py_NULL ) {
@@ -293,7 +293,7 @@ test_thread_state(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
293293 assert (id > 0 );
294294#endif
295295
296- #if !defined( PYPY_VERSION )
296+ #ifndef PYPY_VERSION
297297 // PyThreadState_EnterTracing(), PyThreadState_LeaveTracing()
298298 PyThreadState_EnterTracing (tstate );
299299 PyThreadState_LeaveTracing (tstate );
@@ -668,10 +668,90 @@ 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 * ref = Py_True ; // marker to check that value was set
713+ assert (PyWeakref_GetRef (weakref , & ref ) == 0 );
714+ assert (ref == obj );
715+ assert (Py_REFCNT (obj ) == (refcnt + 1 ));
716+ Py_DECREF (ref );
717+
718+ // delete the referenced object: clear the weakref
719+ Py_DECREF (obj );
720+ gc_collect ();
721+
722+ // test PyWeakref_GetRef(), reference is dead
723+ ref = Py_True ;
724+ assert (PyWeakref_GetRef (weakref , & ref ) == 0 );
725+ assert (ref == NULL );
726+
727+ // test PyWeakref_GetRef(), invalid type
728+ PyObject * invalid_weakref = Py_None ;
729+ assert (!PyErr_Occurred ());
730+ ref = Py_True ;
731+ assert (PyWeakref_GetRef (invalid_weakref , & ref ) == -1 );
732+ assert (PyErr_ExceptionMatches (PyExc_TypeError ));
733+ assert (ref == NULL );
734+ PyErr_Clear ();
735+
736+ #ifndef PYPY_VERSION
737+ // test PyWeakref_GetRef(NULL)
738+ ref = Py_True ;
739+ assert (PyWeakref_GetRef (NULL , & ref ) == -1 );
740+ assert (PyErr_ExceptionMatches (PyExc_SystemError ));
741+ assert (ref == NULL );
742+ PyErr_Clear ();
743+ #endif
744+
745+ Py_DECREF (weakref );
746+
747+ Py_RETURN_NONE ;
748+ }
749+
750+
671751static struct PyMethodDef methods [] = {
672752 {"test_object" , test_object , METH_NOARGS , _Py_NULL },
673753 {"test_py_is" , test_py_is , METH_NOARGS , _Py_NULL },
674- #if ! defined ( PYPY_VERSION )
754+ #ifndef PYPY_VERSION
675755 {"test_frame" , test_frame , METH_NOARGS , _Py_NULL },
676756#endif
677757 {"test_thread_state" , test_thread_state , METH_NOARGS , _Py_NULL },
@@ -682,11 +762,12 @@ static struct PyMethodDef methods[] = {
682762#if (PY_VERSION_HEX <= 0x030B00A1 || 0x030B00A7 <= PY_VERSION_HEX ) && !defined (PYPY_VERSION )
683763 {"test_float_pack" , test_float_pack , METH_NOARGS , _Py_NULL },
684764#endif
685- #if ! defined ( PYPY_VERSION )
765+ #ifndef PYPY_VERSION
686766 {"test_code" , test_code , METH_NOARGS , _Py_NULL },
687767#endif
688768 {"test_api_casts" , test_api_casts , METH_NOARGS , _Py_NULL },
689769 {"test_import" , test_import , METH_NOARGS , _Py_NULL },
770+ {"test_weakref" , test_weakref , METH_NOARGS , _Py_NULL },
690771 {_Py_NULL , _Py_NULL , 0 , _Py_NULL }
691772};
692773
0 commit comments