Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-trialdeletion
Changeset: r92283:f1659c93bbd0
Date: 2017-08-30 20:25 +0200
http://bitbucket.org/pypy/pypy/changeset/f1659c93bbd0/

Log:    Added simple tests for cycle detection

diff --git a/rpython/memory/gc/test/test_rawrefcount.py 
b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -4,7 +4,9 @@
 from rpython.memory.gc.test.test_direct import BaseDirectGCTest
 from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
 from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
-from pypy.module.cpyext.api import PyObject, PyTypeObject
+from pypy.module.cpyext.api import (PyObject, PyTypeObject, PyTypeObjectPtr,
+                                    PyObjectFields, cpython_struct)
+from pypy.module.cpyext.complexobject import PyComplexObject
 
 PYOBJ_HDR = IncrementalMiniMarkGC.PYOBJ_HDR
 PYOBJ_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_HDR_PTR
@@ -83,6 +85,49 @@
             return p1
         return p1, p1ref, r1, r1addr, check_alive
 
+    def _rawrefcount_cycle_obj(self):
+        from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc
+        from rpython.rtyper.lltypesystem import rffi
+        from rpython.rtyper.annlowlevel import llhelper
+        from rpython.rlib.rawrefcount import (REFCNT_CLR_PURPLE)
+        from rpython.rtyper.tool import rffi_platform
+
+        self.gc.rawrefcount_init(lambda: self.trigger.append(1))
+
+        # construct test type
+        TEST_P = lltype.Ptr(lltype.ForwardReference())
+        TEST_P.TO.become(lltype.Struct('test',
+                                       ('base', PyObject.TO),
+                                       ('next', TEST_P),
+                                       ('value', lltype.Signed)))
+
+        def test_tp_traverse(obj, visit, args):
+            from pypy.module.cpyext.api import generic_cpy_call
+            test = rffi.cast(TEST_P, obj)
+            vret = 0
+            if test.next is not None:
+                next = rffi.cast(PyObject, test.next)
+                vret = visit(next, args)
+                if vret != 0:
+                    return vret
+            return vret
+
+        TRAVERSE_FUNCTYPE = rffi.CCallback([PyObject, visitproc, rffi.VOIDP],
+                                           rffi.INT_real)
+        func_ptr = llhelper(TRAVERSE_FUNCTYPE, test_tp_traverse)
+        rffi_func_ptr = rffi.cast(traverseproc, func_ptr)
+        t1 = lltype.malloc(PyTypeObject, flavor='raw', immortal=True)
+        t1.c_tp_traverse = rffi_func_ptr
+
+        # initialize object
+        r1 = lltype.malloc(TEST_P.TO, flavor='raw', immortal=True)
+        r1.base.c_ob_refcnt = 1 | REFCNT_CLR_PURPLE
+        r1.base.c_ob_pypy_link = 0
+        r1.base.c_ob_type = t1
+        r1addr = llmemory.cast_ptr_to_adr(r1)
+
+        return r1, r1addr
+
     def test_rawrefcount_objects_basic(self, old=False):
         p1, p1ref, r1, r1addr, check_alive = (
             self._rawrefcount_pair(42, is_light=True, create_old=old))
@@ -292,9 +337,17 @@
         self._collect(major=True)
         check_alive(0)
 
-    def test_cycle(self):
-        p1, p1ref, r1, r1addr, check_alive = (
-            self._rawrefcount_pair(42, is_pyobj=True))
+    def test_cycle_self_reference_free(self):
+        r1, r1addr = self._rawrefcount_cycle_obj()
+        r1.next = r1
         self.gc.rawrefcount_buffer_pyobj(r1addr)
         self.gc.rrc_collect_cycles()
-        lltype.free(r1, flavor='raw')
+        assert r1.base.c_ob_refcnt == 0
+
+    def test_cycle_self_reference_not_free(self):
+        r1, r1addr = self._rawrefcount_cycle_obj()
+        r1.base.c_ob_refcnt += 1
+        r1.next = r1
+        self.gc.rawrefcount_buffer_pyobj(r1addr)
+        self.gc.rrc_collect_cycles()
+        assert r1.base.c_ob_refcnt == 2
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to