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 testWritePtrField(self): data = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) CPyMarshal.Zero(data, Marshal.SizeOf(PyObject())) CPyMarshal.WritePtrField(data, PyObject, "ob_type", IntPtr(12345)) dataStruct = PtrToStructure(data, PyObject) self.assertEquals(dataStruct.ob_type, IntPtr(12345), "failed to write") Marshal.FreeHGlobal(data)
def testBasicStoreRetrieveFree(self): frees = [] allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, frees)) deallocTypes = CreateTypes(mapper) del allocs[:] obj1 = object() ptr = mapper.Store(obj1) self.assertEquals(len(allocs), 1, "unexpected number of allocations") self.assertEquals(allocs[0], (ptr, Marshal.SizeOf(PyObject())), "unexpected result") self.assertNotEquals(ptr, IntPtr.Zero, "did not store reference") self.assertEquals(mapper.RefCount(ptr), 1, "unexpected refcount") self.assertEquals(CPyMarshal.ReadPtrField(ptr, PyObject, "ob_type"), mapper.PyBaseObject_Type, "nearly-opaque pointer had wrong type") obj2 = mapper.Retrieve(ptr) self.assertTrue(obj1 is obj2, "retrieved wrong object") self.assertEquals(frees, [], "unexpected deallocations") mapper.PyObject_Free(ptr) self.assertEquals(frees, [ptr], "unexpected deallocations") self.assertRaises(KeyError, lambda: mapper.PyObject_Free(ptr)) mapper.Dispose() deallocTypes()
def testFinds_Py_NotImplementedStruct(self): class MyPM(PythonApi): def Register__Py_NotImplementedStruct(self, address): WritePyObject(address) self.assertDataSetterSetsAndRemembers(MyPM, "_Py_NotImplementedStruct", Marshal.SizeOf(PyObject()), TestWrotePyObject)
def testIgnoresBridgeObjectsNotAllocatedByAllocator(self): obj = object() ptr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) CPyMarshal.WriteIntField(ptr, PyObject, 'ob_refcnt', 2) mapper = PythonMapper() mapper.StoreBridge(ptr, obj) mapper.Dispose()
def testFinds_PyExc_OverflowError(self): # and, by assertion, all other error types # TODO: improve ;) class MyPM(PythonApi): def Register_PyExc_OverflowError(self, address): WritePtr(address) self.assertDataSetterSetsAndRemembers(MyPM, "PyExc_OverflowError", Marshal.SizeOf(PyObject()), TestWrotePtr)
def testPyObject_Init(self, mapper, addToCleanUp): typePtr, deallocType = MakeTypePtr(mapper, {'tp_name': 'FooType'}) addToCleanUp(deallocType) objPtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(objPtr)) self.assertEquals(mapper.PyObject_Init(objPtr, typePtr), objPtr, 'did not return the "new instance"') self.assertEquals(CPyMarshal.ReadPtrField(objPtr, PyObject, "ob_type"), typePtr, "wrong type") self.assertEquals(CPyMarshal.ReadIntField(objPtr, PyObject, "ob_refcnt"), 1, "wrong refcount") self.assertEquals(mapper.HasPtr(objPtr), False)
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
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 testPyBaseObject_TypeDeallocCallsObjTypesFreeFunction(self, mapper, addToCleanUp): calls = [] def Some_FreeFunc(objPtr): calls.append(objPtr) self.freeDgt = dgt_void_ptr(Some_FreeFunc) baseObjTypeBlock = mapper.PyBaseObject_Type objTypeBlock = mapper.PyDict_Type # type not actually important objPtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(objPtr)) CPyMarshal.WriteFunctionPtrField(objTypeBlock, PyTypeObject, "tp_free", self.freeDgt) CPyMarshal.WritePtrField(objPtr, PyObject, "ob_type", objTypeBlock) gcwait() # this should make the function pointers invalid if we forgot to store references to the delegates mapper.IC_PyBaseObject_Dealloc(objPtr) self.assertEquals(calls, [objPtr], "wrong calls")
def testCreateEllipsis(self, mapper, addToCleanUp): ellipsisTypePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(ellipsisTypePtr)) ellipsisPtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(ellipsisPtr)) mapper.RegisterData("PyEllipsis_Type", ellipsisTypePtr) mapper.RegisterData("_Py_EllipsisObject", ellipsisPtr) self.assertEquals( CPyMarshal.ReadPtrField(ellipsisPtr, PyObject, "ob_type"), mapper.PyEllipsis_Type) self.assertEquals( CPyMarshal.ReadIntField(ellipsisPtr, PyObject, "ob_refcnt"), 1) self.assertEquals(mapper.Store(Ellipsis), ellipsisPtr) self.assertEquals(mapper.RefCount(ellipsisPtr), 2)
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 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()
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.assertRaisesClr(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()
def getVars(self): obj = object() ptr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) CPyMarshal.WriteIntField(ptr, PyObject, 'ob_refcnt', 1) self.ptrs.append(ptr) return InterestingPtrMap(), ptr, obj, WeakReference(obj)
def GetWriteBytes(bytes): intCount = bytes / CPyMarshal.IntSize def WriteBytes(address): for a in range(intCount): ptr = OffsetPtr(address, a * CPyMarshal.IntSize) Marshal.WriteInt32(ptr, TEST_NUMBER) return WriteBytes WritePyTypeObject = GetWriteBytes(Marshal.SizeOf(PyTypeObject())) TestWrotePyTypeObject = GetTestWroteBytes(Marshal.SizeOf(PyTypeObject())) WritePyObject = GetWriteBytes(Marshal.SizeOf(PyObject())) TestWrotePyObject = GetTestWroteBytes(Marshal.SizeOf(PyObject())) WritePtr = GetWriteBytes(Marshal.SizeOf(IntPtr())) TestWrotePtr = GetTestWroteBytes(Marshal.SizeOf(IntPtr())) TYPES = ( "PyBool_Type", "PyClass_Type", "PyInstance_Type", "PyMethod_Type", "PyComplex_Type", "PyWrapperDescr_Type", "PyProperty_Type", "PyDict_Type", "PyEnum_Type",