def testDeleteList(self): deallocs = [] mapper = PythonMapper(GetAllocatingTestAllocator([], deallocs)) deallocTypes = CreateTypes(mapper) item1 = object() item2 = object() itemPtr1 = mapper.Store(item1) itemPtr2 = mapper.Store(item2) listPtr = mapper.PyList_New(0) mapper.PyList_Append(listPtr, itemPtr1) mapper.PyList_Append(listPtr, itemPtr2) mapper.DecRef(itemPtr1) mapper.DecRef(itemPtr2) self.assertEquals(len(deallocs), 1, "should have deallocated original data block only at this point") dataStore = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") mapper.DecRef(listPtr) listDeallocs = deallocs[1:] self.assertEquals(len(listDeallocs), 4, "should dealloc list object; data store; both items") expectedDeallocs = [listPtr, dataStore, itemPtr1, itemPtr2] self.assertEquals(set(listDeallocs), set(expectedDeallocs), "deallocated wrong stuff") mapper.Dispose() deallocTypes()
def testRefCountIncRefDecRef(self): frees = [] allocator = GetAllocatingTestAllocator([], frees) mapper = PythonMapper(allocator) deallocTypes = CreateTypes(mapper) obj1 = object() ptr = mapper.Store(obj1) self.assertEquals(mapper.HasPtr(ptr), True) mapper.IncRef(ptr) self.assertEquals(mapper.RefCount(ptr), 2, "unexpected refcount") self.assertEquals(mapper.HasPtr(ptr), True) del frees[:] mapper.DecRef(ptr) self.assertEquals(mapper.RefCount(ptr), 1, "unexpected refcount") self.assertEquals(mapper.HasPtr(ptr), True) self.assertEquals(frees, [], "unexpected deallocations") mapper.DecRef(ptr) self.assertEquals(mapper.HasPtr(ptr), False) self.assertEquals(frees, [ptr], "unexpected deallocations") self.assertRaises(KeyError, lambda: mapper.PyObject_Free(ptr)) mapper.Dispose() deallocTypes()
def testStoreSameObjectIncRefsOriginal(self): frees = [] allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, frees)) deallocTypes = CreateTypes(mapper) del allocs[:] obj1 = object() result1 = mapper.Store(obj1) result2 = mapper.Store(obj1) self.assertEquals(allocs, [(result1, Marshal.SizeOf(PyObject))], "unexpected result") self.assertEquals(result1, result2, "did not return same ptr") self.assertEquals(mapper.RefCount(result1), 2, "did not incref") mapper.DecRef(result1) del frees[:] mapper.DecRef(result1) self.assertEquals(frees, [result1], "did not free memory") result3 = mapper.Store(obj1) self.assertEquals( allocs, [(result1, Marshal.SizeOf(PyObject)), (result3, Marshal.SizeOf(PyObject))], "unexpected result -- failed to clear reverse mapping?") mapper.Dispose() deallocTypes()
def testNullPointers(self): allocator = GetDoNothingTestAllocator([]) mapper = PythonMapper(allocator) self.assertEquals(mapper.HasPtr(IntPtr.Zero), False) self.assertRaisesClr(CannotInterpretException, lambda: mapper.IncRef(IntPtr.Zero)) self.assertRaisesClr(CannotInterpretException, lambda: mapper.DecRef(IntPtr.Zero)) self.assertRaisesClr(CannotInterpretException, lambda: mapper.Retrieve(IntPtr.Zero)) self.assertRaisesClr(CannotInterpretException, lambda: mapper.RefCount(IntPtr.Zero)) mapper.Dispose()
def testDecRefObjectWithZeroRefCountFails(self): allocator = HGlobalAllocator() mapper = PythonMapper(allocator) deallocTypes = CreateTypes(mapper) # need to use same allocator as mapper, otherwise it gets upset on shutdown objPtr = allocator.Alloc(Marshal.SizeOf(PyObject())) CPyMarshal.WriteIntField(objPtr, PyObject, "ob_refcnt", 0) CPyMarshal.WritePtrField(objPtr, PyObject, "ob_type", mapper.PyBaseObject_Type) mapper.StoreBridge(objPtr, object()) self.assertRaisesClr(BadRefCountException, lambda: mapper.DecRef(objPtr)) mapper.Dispose() deallocTypes()
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 testPyList_Append(self): allocs = [] deallocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, deallocs)) deallocTypes = CreateTypes(mapper) del allocs[:] listPtr = mapper.PyList_New(0) self.assertEquals(allocs, [(listPtr, Marshal.SizeOf(PyListObject))], "bad alloc") item1 = object() item2 = object() itemPtr1 = mapper.Store(item1) itemPtr2 = mapper.Store(item2) self.assertEquals(mapper.PyList_Append(listPtr, itemPtr1), 0, "failed to report success") self.assertEquals(len(allocs), 4, "didn't allocate memory for data store (list; item1; item2; data store comes 4th)") dataPtrAfterFirstAppend = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") self.assertEquals(allocs[3], (dataPtrAfterFirstAppend, CPyMarshal.PtrSize), "allocated wrong amount of memory") self.assertEquals(CPyMarshal.ReadPtr(dataPtrAfterFirstAppend), itemPtr1, "failed to fill memory") self.assertEquals(mapper.RefCount(itemPtr1), 2, "failed to incref new contents") self.assertEquals(mapper.Retrieve(listPtr), [item1], "retrieved wrong list") # make refcount 1, to prove that references are not lost when reallocing data mapper.DecRef(itemPtr1) self.assertEquals(mapper.PyList_Append(listPtr, itemPtr2), 0, "failed to report success") self.assertEquals(len(allocs), 5, "didn't allocate memory for new, larger data store") self.assertEquals(deallocs, [dataPtrAfterFirstAppend]) dataPtrAfterSecondAppend = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") self.assertEquals(allocs[4], (dataPtrAfterSecondAppend, (CPyMarshal.PtrSize * 2)), "allocated wrong amount of memory") self.assertEquals(CPyMarshal.ReadPtr(dataPtrAfterSecondAppend), itemPtr1, "failed to keep reference to first item") self.assertEquals(CPyMarshal.ReadPtr(OffsetPtr(dataPtrAfterSecondAppend, CPyMarshal.PtrSize)), itemPtr2, "failed to keep reference to first item") self.assertEquals(mapper.RefCount(itemPtr1), 1, "wrong refcount for item existing only in list") self.assertEquals(mapper.RefCount(itemPtr2), 2, "wrong refcount newly-added item") self.assertEquals(mapper.Retrieve(listPtr), [item1, item2], "retrieved wrong list") mapper.Dispose() deallocTypes()
def testFinalDecRefComplainsAboutMissing_tp_dealloc(self): frees = [] mapper = PythonMapper(GetAllocatingTestAllocator([], frees)) deallocTypes = CreateTypes(mapper) typePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) CPyMarshal.WritePtrField(typePtr, PyTypeObject, "tp_dealloc", IntPtr.Zero) obj = object() objPtr = mapper.Store(obj) CPyMarshal.WritePtrField(objPtr, PyObject, "ob_type", typePtr) mapper.IncRef(objPtr) del frees [:] mapper.DecRef(objPtr) self.assertEquals(frees, [], "freed prematurely") self.assertRaisesClr(CannotInterpretException, mapper.DecRef, objPtr) mapper.Dispose() deallocTypes()
def testPyDict_New(self): allocs = [] frees = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, frees)) deallocTypes = CreateTypes(mapper) try: del allocs[:] dictPtr = mapper.PyDict_New() self.assertEquals(mapper.RefCount(dictPtr), 1, "bad refcount") self.assertEquals(allocs, [(dictPtr, Marshal.SizeOf(PyObject))], "did not allocate as expected") self.assertEquals( CPyMarshal.ReadPtrField(dictPtr, PyObject, "ob_type"), mapper.PyDict_Type, "wrong type") dictObj = mapper.Retrieve(dictPtr) self.assertEquals(dictObj, {}, "retrieved unexpected value") mapper.DecRef(dictPtr) self.assertEquals(frees, [dictPtr], "did not release memory") finally: mapper.Dispose() deallocTypes()