def testStoreBridge(self):
        allocator = HGlobalAllocator()
        mapper = PythonMapper(allocator)
        deallocTypes = CreateTypes(mapper)
        # need to use same allocator as mapper, otherwise it gets upset on shutdown
        ptr = allocator.Alloc(Marshal.SizeOf(PyObject))

        try:

            def do():
                # see NOTE in interestingptrmaptest
                obj = object()
                ref = WeakReference(obj)
                CPyMarshal.WriteIntField(ptr, PyObject, "ob_refcnt", 1)
                CPyMarshal.WritePtrField(ptr, PyObject, "ob_type",
                                         mapper.PyBaseObject_Type)
                mapper.StoreBridge(ptr, obj)

                self.assertEquals(mapper.Retrieve(ptr), obj,
                                  "object not stored")
                self.assertEquals(mapper.Store(obj), ptr,
                                  "object not reverse-mapped")

                mapper.Weaken(obj)
                CPyMarshal.WriteIntField(ptr, PyObject, "ob_refcnt", 1)

                mapper.IncRef(ptr)
                del obj
                return ref

            ref = do()
            gcwait()
            self.assertEquals(ref.IsAlive, True,
                              "was not strengthened by IncRef")

            mapper.DecRef(ptr)
            gcwait()
            self.assertEquals(ref.IsAlive, False, "was not weakened by DecRef")

        finally:
            # need to dealloc ptr ourselves, it doesn't happen automatically
            # except for objects with Dispatchers
            mapper.IC_PyBaseObject_Dealloc(ptr)
            mapper.Dispose()
            deallocTypes()
    def testReleaseGILChecksBridgePtrs(self):
        frees = []
        allocator = GetAllocatingTestAllocator([], frees)
        mapper = PythonMapper(allocator)
        deallocTypes = CreateTypes(mapper)

        # force no throttling of cleanup
        mapper.GCThreshold = 0

        def do1():
            obj = object()
            ref = WeakReference(obj)
            # need to use same allocator as mapper, otherwise it gets upset on shutdown
            ptr = allocator.Alloc(Marshal.SizeOf(PyObject))
            CPyMarshal.WriteIntField(ptr, PyObject, "ob_refcnt", 2)
            CPyMarshal.WritePtrField(ptr, PyObject, "ob_type",
                                     mapper.PyBaseObject_Type)
            mapper.StoreBridge(ptr, obj)

            # refcount > 1 means ref should have been strengthened
            del obj
            return ref, ptr

        ref, ptr = do1()
        gcwait()
        self.assertEquals(ref.IsAlive, True,
                          "was reaped unexpectedly (refcount was 2)")

        CPyMarshal.WriteIntField(ptr, PyObject, "ob_refcnt", 1)
        mapper.EnsureGIL()
        mapper.ReleaseGIL()

        # refcount < 2 should have been weakened
        gcwait()
        self.assertRaises(NullReferenceException, mapper.Retrieve, ptr)

        # need to dealloc ptr ourselves, it doesn't hapen automatically
        # except for objects with Dispatchers
        mapper.IC_PyBaseObject_Dealloc(ptr)
        mapper.Dispose()
        deallocTypes()
    def testStrengthenWeakenUnmanagedInstance(self):
        frees = []
        allocator = GetAllocatingTestAllocator([], frees)
        mapper = PythonMapper(allocator)
        deallocTypes = CreateTypes(mapper)

        # need to use same allocator as mapper, otherwise it gets upset on shutdown
        ptr = allocator.Alloc(Marshal.SizeOf(PyObject))

        try:

            def do1():
                # see NOTE in interestingptrmaptest
                obj = object()
                ref = WeakReference(obj)
                CPyMarshal.WriteIntField(ptr, PyObject, "ob_refcnt", 1)
                CPyMarshal.WritePtrField(ptr, PyObject, "ob_type",
                                         mapper.PyBaseObject_Type)
                mapper.StoreBridge(ptr, obj)
                del obj
                return ref

            ref = do1()
            gcwait()
            self.assertEquals(ref.IsAlive, True, "was not strongly referenced")

            def do2():
                obj = ref.Target
                mapper.Weaken(obj)
                del obj

            do2()
            gcwait()
            self.assertRaises(NullReferenceException, mapper.Retrieve, ptr)

        finally:
            # need to dealloc ptr ourselves, it doesn't hapen automatically
            # except for objects with Dispatchers
            mapper.IC_PyBaseObject_Dealloc(ptr)
            mapper.Dispose()
            deallocTypes()