def testUnmanagedThreadState(self, mapper, _): mapper.ReleaseGIL() # current thread state should be null if nobody has the GIL self.assertEquals(CPyMarshal.ReadPtr(mapper._PyThreadState_Current), IntPtr.Zero) mapper.EnsureGIL() mapper.LastException = NameError("Harold") ts = CPyMarshal.ReadPtr(mapper._PyThreadState_Current) curexc_type = CPyMarshal.ReadPtrField(ts, PyThreadState, "curexc_type") curexc_value = CPyMarshal.ReadPtrField(ts, PyThreadState, "curexc_value") self.assertEquals(mapper.Retrieve(curexc_type), NameError) self.assertEquals(mapper.Retrieve(curexc_value), "Harold") mapper.ReleaseGIL() def CheckOtherThread(): mapper.EnsureGIL() ts2 = CPyMarshal.ReadPtr(mapper._PyThreadState_Current) self.assertNotEquals(ts2, ts) curexc_type = CPyMarshal.ReadPtrField(ts2, PyThreadState, "curexc_type") curexc_value = CPyMarshal.ReadPtrField(ts2, PyThreadState, "curexc_value") self.assertEquals(curexc_type, IntPtr.Zero) self.assertEquals(curexc_value, IntPtr.Zero) mapper.ReleaseGIL() thread = Thread(ThreadStart(CheckOtherThread)) thread.Start() thread.Join() mapper.EnsureGIL()
def testReadyBuiltinTypes(self, mapper, _): mapper.ReadyBuiltinTypes() for _type in BUILTIN_TYPES: typePtr = getattr(mapper, _type) basePtr = CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base") if typePtr != mapper.PySeqIter_Type: # PySeqIter_Type is suprrisingly tedious to turn into a proper PythonType in C# tp_dict = mapper.Retrieve( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_dict")) self.assertEquals(mapper.Retrieve(typePtr).__dict__, tp_dict) if typePtr not in (mapper.PyBaseObject_Type, mapper.PyBool_Type): self.assertEquals( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base"), mapper.PyBaseObject_Type) if typePtr == mapper.PyBool_Type: self.assertEquals( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base"), mapper.PyInt_Type) typeTypePtr = CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "ob_type") if typePtr != mapper.PyType_Type: self.assertEquals(typeTypePtr, mapper.PyType_Type)
def testStoreSlice(self, mapper, _): obj = slice(1, 2, 3) objPtr = mapper.Store(obj) self.assertEquals(mapper.RefCount(objPtr), 1) self.assertEquals(mapper.Retrieve(objPtr), obj) self.assertEquals( CPyMarshal.ReadPtrField(objPtr, PySliceObject, "ob_type"), mapper.PySlice_Type) self.assertEquals( CPyMarshal.ReadIntField(objPtr, PySliceObject, "ob_refcnt"), 1) startPtr = CPyMarshal.ReadPtrField(objPtr, PySliceObject, "start") self.assertEquals(mapper.Retrieve(startPtr), 1) mapper.IncRef(startPtr) stopPtr = CPyMarshal.ReadPtrField(objPtr, PySliceObject, "stop") self.assertEquals(mapper.Retrieve(stopPtr), 2) mapper.IncRef(stopPtr) stepPtr = CPyMarshal.ReadPtrField(objPtr, PySliceObject, "step") self.assertEquals(mapper.Retrieve(stepPtr), 3) mapper.IncRef(stepPtr) mapper.DecRef(objPtr) self.assertEquals(mapper.RefCount(startPtr), 1) self.assertEquals(mapper.RefCount(stopPtr), 1) self.assertEquals(mapper.RefCount(stepPtr), 1)
def testNumberMethods(self, mapper, _): numberTypes = ("PyInt_Type", "PyLong_Type", "PyFloat_Type", "PyComplex_Type") implementedFields = { "nb_int": mapper.GetFuncPtr("PyNumber_Int"), "nb_long": mapper.GetFuncPtr("PyNumber_Long"), "nb_float": mapper.GetFuncPtr("PyNumber_Float"), "nb_multiply": mapper.GetFuncPtr("PyNumber_Multiply") } for _type in numberTypes: typePtr = getattr(mapper, _type) nmPtr = CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_as_number") self.assertNotEquals(nmPtr, IntPtr.Zero) for field in implementedFields: fieldPtr = CPyMarshal.ReadPtrField(nmPtr, PyNumberMethods, field) self.assertNotEquals(fieldPtr, IntPtr.Zero) self.assertEquals(fieldPtr, implementedFields[field]) flags = CPyMarshal.ReadIntField(typePtr, PyTypeObject, "tp_flags") hasIndex = bool(flags & int(Py_TPFLAGS.HAVE_INDEX)) if (not _type in ("PyFloat_Type", "PyComplex_Type")): self.assertEquals(hasIndex, True, _type) fieldPtr = CPyMarshal.ReadPtrField(nmPtr, PyNumberMethods, "nb_index") self.assertNotEquals(fieldPtr, IntPtr.Zero) self.assertEquals(fieldPtr, mapper.GetFuncPtr("PyNumber_Index")) else: self.assertEquals(hasIndex, False)
def testFields(self, mapper, CallLater): basePtr, deallocBase = MakeTypePtr(mapper, {}) typePtr, deallocType = MakeTypePtr(mapper, {}) CallLater(deallocBase) CallLater(deallocType) # The purpose of this rigmarole is to enable me to use SOME_VALUE # for every field, rather than creating 'proper' values for every # field -- once I've Retrieved the types, I won't actualise them # again, so I can put any old non-zero nonsense in any field to # check that it gets inherited (or not) mapper.Retrieve(basePtr) mapper.Retrieve(typePtr) CPyMarshal.WriteIntField(typePtr, PyTypeObject, "tp_flags", int(Py_TPFLAGS.HAVE_CLASS)) # end rigmarole CPyMarshal.WritePtrField(typePtr, PyTypeObject, "tp_base", basePtr) for field in INHERIT_FIELDS + DONT_INHERIT_FIELDS: CPyMarshal.WritePtrField(typePtr, PyTypeObject, field, NO_VALUE) CPyMarshal.WritePtrField(basePtr, PyTypeObject, field, SOME_VALUE) mapper.PyType_Ready(typePtr) for field in INHERIT_FIELDS: self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, field), SOME_VALUE) for field in DONT_INHERIT_FIELDS: self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, field), NO_VALUE)
def testPyType_Ready(self, mapper, addToCleanUp): typePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) CPyMarshal.Zero(typePtr, Marshal.SizeOf(PyTypeObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(typePtr)) self.assertEquals(mapper.PyType_Ready(typePtr), 0, "wrong") self.assertEquals( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "ob_type"), mapper.PyType_Type, "failed to fill in missing ob_type") self.assertEquals( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base"), mapper.PyBaseObject_Type, "failed to fill in missing tp_base") tp_dict = mapper.Retrieve( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_dict")) self.assertEquals(mapper.Retrieve(typePtr).__dict__, tp_dict) typeFlags = CPyMarshal.ReadIntField(typePtr, PyTypeObject, "tp_flags") self.assertEquals(typeFlags & UInt32(Py_TPFLAGS.READY), UInt32(Py_TPFLAGS.READY), "did not ready type") self.assertEquals( typeFlags & UInt32(Py_TPFLAGS.HAVE_CLASS), UInt32(Py_TPFLAGS.HAVE_CLASS), "we always set this flag, for no better reason than 'it makes ctypes kinda work'" ) CPyMarshal.WritePtrField(typePtr, PyTypeObject, "ob_type", IntPtr.Zero) self.assertEquals(mapper.PyType_Ready(typePtr), 0, "wrong") self.assertEquals( CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "ob_type"), IntPtr.Zero, "unexpectedly and unnecessarily rereadied type")
def testTrueFalse(self, mapper, _): truePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyIntObject)) mapper.RegisterData("_Py_TrueStruct", truePtr) self.assertTrue(mapper.Retrieve(truePtr) is True) self.assertEquals( CPyMarshal.ReadPtrField(truePtr, PyIntObject, 'ob_type'), mapper.PyBool_Type) self.assertEquals( CPyMarshal.ReadIntField(truePtr, PyIntObject, 'ob_refcnt'), 1) self.assertEquals( CPyMarshal.ReadIntField(truePtr, PyIntObject, 'ob_ival'), 1) truePtr2 = mapper.Store(True) self.assertEquals(truePtr2, truePtr) self.assertEquals(mapper.RefCount(truePtr), 2) falsePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyIntObject)) mapper.RegisterData("_Py_ZeroStruct", falsePtr) self.assertTrue(mapper.Retrieve(falsePtr) is False) self.assertEquals( CPyMarshal.ReadPtrField(falsePtr, PyIntObject, 'ob_type'), mapper.PyBool_Type) self.assertEquals( CPyMarshal.ReadIntField(falsePtr, PyIntObject, 'ob_refcnt'), 1) self.assertEquals( CPyMarshal.ReadIntField(falsePtr, PyIntObject, 'ob_ival'), 0) falsePtr2 = mapper.Store(False) self.assertEquals(falsePtr2, falsePtr) self.assertEquals(mapper.RefCount(falsePtr), 2)
def testStoreIPyFile(self, mapper, _): f = open(*READ_ARGS) fPtr = mapper.Store(f) self.assertEquals(CPyMarshal.ReadPtrField(fPtr, PyObject, 'ob_type'), mapper.PyFile_Type) self.assertEquals(CPyMarshal.ReadIntField(fPtr, PyObject, 'ob_refcnt'), 1) self.assertEquals(CPyMarshal.ReadIntField(fPtr, PyFileObject, 'f_fp'), -2) self.assertEquals(mapper.Retrieve(CPyMarshal.ReadPtrField(fPtr, PyFileObject, 'f_name')), READ_ARGS[0]) self.assertEquals(mapper.Retrieve(CPyMarshal.ReadPtrField(fPtr, PyFileObject, 'f_mode')), READ_ARGS[1])
def testBaseTypeMissing(self, mapper, CallLater): mapper.PyType_Ready(mapper.PyBaseObject_Type) self.assertEquals(CPyMarshal.ReadPtrField(mapper.PyBaseObject_Type, PyTypeObject, "tp_base"), IntPtr.Zero) typePtr, deallocType = MakeTypePtr(mapper, {}) CallLater(deallocType) CPyMarshal.WritePtrField(typePtr, PyTypeObject, "tp_base", NO_VALUE) mapper.PyType_Ready(typePtr) self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base"), mapper.PyBaseObject_Type)
def testStringifiers(self, mapper, _): IC_PyString_Str = mapper.GetFuncPtr("IC_PyString_Str") tp_str = CPyMarshal.ReadPtrField(mapper.PyString_Type, PyTypeObject, "tp_str") self.assertEquals(tp_str, IC_PyString_Str) PyObject_Repr = mapper.GetFuncPtr("PyObject_Repr") tp_repr = CPyMarshal.ReadPtrField(mapper.PyString_Type, PyTypeObject, "tp_repr") self.assertEquals(tp_repr, PyObject_Repr)
def CheckOtherThread(): mapper.EnsureGIL() ts2 = CPyMarshal.ReadPtr(mapper._PyThreadState_Current) self.assertNotEquals(ts2, ts) curexc_type = CPyMarshal.ReadPtrField(ts2, PyThreadState, "curexc_type") curexc_value = CPyMarshal.ReadPtrField(ts2, PyThreadState, "curexc_value") self.assertEquals(curexc_type, IntPtr.Zero) self.assertEquals(curexc_value, IntPtr.Zero) mapper.ReleaseGIL()
def testSequenceProtocol(self, mapper, _): strPtr = mapper.PyString_Type seqPtr = CPyMarshal.ReadPtrField(strPtr, PyTypeObject, 'tp_as_sequence') self.assertNotEquals(seqPtr, IntPtr.Zero) concatPtr = CPyMarshal.ReadPtrField(seqPtr, PySequenceMethods, 'sq_concat') # concat_core tested further down self.assertEquals(concatPtr, mapper.GetFuncPtr('IC_PyString_Concat_Core'))
def testStoreList(self, mapper, _): list_ = [1, 2, 3] listPtr = mapper.Store(list_) self.assertEquals(id(mapper.Retrieve(listPtr)), id(list_)) typePtr = CPyMarshal.ReadPtrField(listPtr, PyObject, "ob_type") self.assertEquals(typePtr, mapper.PyList_Type, "wrong type") dataStore = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") for i in range(1, 4): self.assertEquals(mapper.Retrieve(CPyMarshal.ReadPtr(dataStore)), i, "contents not stored") self.assertEquals(mapper.RefCount(CPyMarshal.ReadPtr(dataStore)), 1, "bad refcount for items") dataStore = OffsetPtr(dataStore, CPyMarshal.PtrSize)
def testStoreTupleCreatesTupleType(self): allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, [])) typeBlock = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) mapper.RegisterData("PyTuple_Type", typeBlock) theTuple = (0, 1, 2) tuplePtr = mapper.Store(theTuple) self.assertEquals( CPyMarshal.ReadPtrField(tuplePtr, PyTupleObject, "ob_type"), typeBlock, "wrong type") dataPtr = OffsetPtr(tuplePtr, Marshal.OffsetOf(PyTupleObject, "ob_item")) for i in range(3): item = mapper.Retrieve(CPyMarshal.ReadPtr(dataPtr)) self.assertEquals(item, i, "did not store data") dataPtr = OffsetPtr(dataPtr, CPyMarshal.PtrSize) tuplePtr2 = mapper.Store(theTuple) self.assertEquals(tuplePtr2, tuplePtr, "didn't realise already had this tuple") self.assertEquals(mapper.RefCount(tuplePtr), 2, "didn't incref") mapper.Dispose() Marshal.FreeHGlobal(typeBlock)
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 testStoreTypeDictCreatesDictTypeWhichWorks(self, mapper, addToCleanUp): typeBlock = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject)) addToCleanUp(lambda: Marshal.FreeHGlobal(typeBlock)) mapper.RegisterData("PyDict_Type", typeBlock) class klass(object): pass dictPtr = mapper.Store(klass.__dict__) self.assertEquals( CPyMarshal.ReadPtrField(dictPtr, PyObject, "ob_type"), typeBlock, "wrong type") self.assertEquals( mapper.PyDict_SetItemString(dictPtr, 'foo', mapper.Store('bar')), 0) self.assertEquals( mapper.PyDict_SetItem(dictPtr, mapper.Store('baz'), mapper.Store('qux')), 0) self.assertEquals( mapper.Retrieve(mapper.PyDict_GetItemString(dictPtr, 'foo')), 'bar') self.assertEquals( mapper.Retrieve(mapper.PyDict_GetItem(dictPtr, mapper.Store('baz'))), 'qux') self.assertEquals(klass.foo, 'bar') self.assertEquals(klass.baz, 'qux') self.assertEquals(mapper.PyDict_Size(dictPtr), len(klass.__dict__))
def CreateInstance(mapper, calls): listPtr = mapper.Store([1, 2, 3]) dataStore = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") for _ in range(3): itemPtrs.append(CPyMarshal.ReadPtr(dataStore)) dataStore = OffsetPtr(dataStore, CPyMarshal.PtrSize) return listPtr
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 log_info(obj, size=None): """ Print useful debugging information about the first argument. Optional second argument allows you to specify how many bytes of the object's unmanaged representation to print; it is not generally useful or wise to make use of it. """ print print 'before storing:' _mapper.LogMappingInfo(id(obj)) print print 'after storing:' objPtr = _mapper.Store(obj) if size is None: typePtr = CPyMarshal.ReadPtrField(objPtr, PyObject, "ob_type") size = CPyMarshal.ReadIntField(typePtr, PyTypeObject, "tp_basicsize") itemsize = CPyMarshal.ReadIntField(typePtr, PyTypeObject, "tp_itemsize") if itemsize > 0: itemcount = CPyMarshal.ReadIntField(objPtr, PyVarObject, "ob_size") size += itemcount * itemsize print 'printing %d bytes of object at %x' % (size, objPtr) CPyMarshal.Log(objPtr, size) print _mapper.DecRef(objPtr)
def testTypeMappings(self, mapper, _): for (k, v) in BUILTIN_TYPES.items(): typePtr = getattr(mapper, k) self.assertEquals(CPyMarshal.ReadCStringField(typePtr, PyTypeObject, 'tp_name'), v.__name__) if typePtr == mapper.PyFile_Type: self.assertNotEquals(mapper.Retrieve(typePtr), v, "failed to map PyFile_Type to something-that-isn't file") else: self.assertEquals(mapper.Retrieve(typePtr), v, "failed to map " + k) if typePtr in (mapper.PyType_Type, mapper.PyBaseObject_Type): # surprising refcount because of the unmanaged PyFile malarkey self.assertEquals(mapper.RefCount(typePtr), 2, "failed to add reference to " + k) else: self.assertEquals(mapper.RefCount(typePtr), 1, "failed to add reference to " + k) mapper.PyType_Ready(typePtr) self.assertNotEquals(CPyMarshal.ReadIntField(typePtr, PyTypeObject, "tp_basicsize"), 0) basePtr = CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base") if k == "PyBaseObject_Type": self.assertEquals(basePtr, IntPtr.Zero) elif k == "PyBool_Type": self.assertEquals(basePtr, mapper.PyInt_Type) else: self.assertEquals(basePtr, mapper.PyBaseObject_Type)
def testSomeItems(self): allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, [])) deallocTypes = CreateTypes(mapper) typeSpec = { "tp_basicsize": 32, "tp_itemsize": 64, } typePtr, deallocType = MakeTypePtr(mapper, typeSpec) del allocs[:] result = mapper.PyType_GenericAlloc(typePtr, 3) self.assertEquals(allocs, [(result, 224)], "allocated wrong") refcount = CPyMarshal.ReadIntField(result, PyObject, "ob_refcnt") self.assertEquals(refcount, 1, "bad initialisation") instanceType = CPyMarshal.ReadPtrField(result, PyObject, "ob_type") self.assertEquals(instanceType, typePtr, "bad type ptr") size = CPyMarshal.ReadIntField(result, PyVarObject, "ob_size") self.assertEquals(size, 3, "bad ob_size") headerSize = Marshal.SizeOf(PyVarObject) zerosPtr = OffsetPtr(result, headerSize) for i in range(224 - headerSize): self.assertEquals(CPyMarshal.ReadByte(zerosPtr), 0, "not zeroed") zerosPtr = OffsetPtr(zerosPtr, 1) mapper.Dispose() deallocTypes() deallocType()
def testBufferProtocol(self, mapper, later): # should all be implemented in C really, but weaving cpy string type into # our code feels too much like hard work for now strPtr = mapper.PyString_Type bufPtr = CPyMarshal.ReadPtrField(strPtr, PyTypeObject, 'tp_as_buffer') self.assertNotEquals(bufPtr, IntPtr.Zero) getreadbuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getreadbuffer', dgt_int_ptrintptr) getwritebuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getwritebuffer', dgt_int_ptrintptr) getcharbuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getcharbuffer', dgt_int_ptrintptr) getsegcount = CPyMarshal.ReadFunctionPtrField(bufPtr, PyBufferProcs, 'bf_getsegcount', dgt_int_ptrptr) ptrptr = Marshal.AllocHGlobal(Marshal.SizeOf(IntPtr)) later(lambda: Marshal.FreeHGlobal(ptrptr)) strptr = mapper.Store("hullo") for getter in (getreadbuffer, getcharbuffer): self.assertEquals(getter(strptr, 0, ptrptr), 5) self.assertEquals( CPyMarshal.ReadPtr(ptrptr), CPyMarshal.GetField(strptr, PyStringObject, 'ob_sval')) self.assertEquals(getter(strptr, 1, ptrptr), -1) self.assertMapperHasError(mapper, SystemError) self.assertEquals(getwritebuffer(strptr, 0, ptrptr), -1) self.assertMapperHasError(mapper, SystemError) self.assertEquals(getsegcount(strptr, ptrptr), 1) self.assertEquals(CPyMarshal.ReadInt(ptrptr), 5) self.assertEquals(getsegcount(strptr, IntPtr.Zero), 1)
def testPyList_DeallocDecRefsItemsAndCallsCorrectFreeFunction(self): frees = [] mapper = PythonMapper(GetAllocatingTestAllocator([], frees)) deallocTypes = CreateTypes(mapper) calls = [] def CustomFree(ptr): calls.append(ptr) mapper.PyObject_Free(listPtr) self.freeDgt = dgt_void_ptr(CustomFree) CPyMarshal.WriteFunctionPtrField(mapper.PyList_Type, PyTypeObject, "tp_free", self.freeDgt) listPtr = mapper.Store([1, 2, 3]) itemPtrs = [] dataStore = CPyMarshal.ReadPtrField(listPtr, PyListObject, "ob_item") for _ in range(3): itemPtrs.append(CPyMarshal.ReadPtr(dataStore)) dataStore = OffsetPtr(dataStore, CPyMarshal.PtrSize) mapper.IC_PyList_Dealloc(listPtr) for itemPtr in itemPtrs: self.assertEquals(itemPtr in frees, True, "did not decref item") self.assertEquals(calls, [listPtr], "did not call type's free function") mapper.Dispose() deallocTypes()
def testPyLong_FromUnsignedLongLong(self, mapper, _): for value in map(UInt64, (18000000000000000000, 0)): ptr = mapper.PyLong_FromUnsignedLongLong(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyObject, "ob_type"), mapper.PyLong_Type, "bad type")
def testStoreUnknownTypeWithBases(self, mapper, _): class C(object): pass class D(object): pass class E(C, D): pass ePtr = mapper.Store(E) basesPtr = CPyMarshal.ReadPtrField(ePtr, PyTypeObject, "tp_bases") self.assertEquals(mapper.Retrieve(basesPtr), (C, D))
def testPyLong_FromDouble(self, mapper, _): for value in (0.0, 1.0, 12345678.9, -123456.789): ptr = mapper.PyLong_FromDouble(value) self.assertEquals(mapper.Retrieve(ptr), long(value), "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyObject, "ob_type"), mapper.PyLong_Type, "bad type")
def testPyLong_FromLong(self, mapper, _): for value in (1555555555, -1555555555, 0): ptr = mapper.PyLong_FromLong(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyObject, "ob_type"), mapper.PyLong_Type, "bad type")
def testStoreDictCreatesDictType(self, mapper, addToCleanUp): typeBlock = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject)) addToCleanUp(lambda: Marshal.FreeHGlobal(typeBlock)) mapper.RegisterData("PyDict_Type", typeBlock) dictPtr = mapper.Store({0: 1, 2: 3}) self.assertEquals( CPyMarshal.ReadPtrField(dictPtr, PyObject, "ob_type"), typeBlock, "wrong type")
def testStoreLong(self, mapper, _): for value in (5555555555, -5555555555, long(0), UInt32.MaxValue): ptr = mapper.Store(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyObject, "ob_type"), mapper.PyLong_Type, "bad type") mapper.DecRef(ptr)
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()