def assertPyTuple_New_Works(self, length): allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, [])) typeBlock = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject)) mapper.RegisterData("PyTuple_Type", typeBlock) tuplePtr = mapper.PyTuple_New(length) expectedSize = Marshal.SizeOf(PyTupleObject) + (CPyMarshal.PtrSize * (length - 1)) self.assertEquals(allocs, [(tuplePtr, expectedSize)], "bad alloc") tupleStruct = Marshal.PtrToStructure(tuplePtr, PyTupleObject) self.assertEquals(tupleStruct.ob_refcnt, 1, "bad refcount") self.assertEquals(tupleStruct.ob_type, mapper.PyTuple_Type, "bad type") self.assertEquals(tupleStruct.ob_size, length, "bad size") self.assertEquals(mapper.PyTuple_Size(tuplePtr), length, "should still work with uninitialised tuple imo") dataPtr = OffsetPtr(tuplePtr, Marshal.OffsetOf(PyTupleObject, "ob_item")) itemPtrs = [] for i in range(length): self.assertEquals(CPyMarshal.ReadPtr(dataPtr), IntPtr.Zero, "item memory not zeroed") itemPtr = mapper.Store(i + 100) CPyMarshal.WritePtr(dataPtr, itemPtr) itemPtrs.append(itemPtr) dataPtr = OffsetPtr(dataPtr, CPyMarshal.PtrSize) immutableTuple = mapper.Retrieve(tuplePtr) self.assertEquals(immutableTuple, tuple(i + 100 for i in range(length)), "broken") tuplePtr2 = mapper.Store(immutableTuple) self.assertEquals(tuplePtr2, tuplePtr, "didn't realise already had this object stored") self.assertEquals(mapper.RefCount(tuplePtr), 2, "didn't incref") mapper.Dispose() Marshal.FreeHGlobal(typeBlock)
def testConvertPyFileToDescriptor(self, mapper, _): testDir = tempfile.mkdtemp() outFile = os.path.join(testDir, "test") pyFile = file(outFile, 'w') pyFile.write("I love streams ") pyFile.flush() fd = mapper.ConvertPyFileToDescriptor(pyFile) FILE = Unmanaged._fdopen(fd, "w") testStr = "and file descriptors!" testStrPtr = mapper.Store(testStr) testDataPtr = OffsetPtr(testStrPtr, Marshal.OffsetOf(PyStringObject, "ob_sval")) self.assertTrue( Unmanaged.fwrite(testDataPtr, 1, len(testStr), FILE) > 0, "writing failed") Unmanaged.fflush(FILE) pyFile.close() stream = file(outFile, 'r') output = stream.read() stream.close() self.assertEquals(output, "I love streams and file descriptors!")
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 testIC_PyFile_AsFile_Write(self, mapper, addToCleanUp, _): testDir = tempfile.mkdtemp() addToCleanUp(lambda: shutil.rmtree(testDir)) path = os.path.join(testDir, "test") testStr = "meh, string data" testLength = len(testStr) testStrPtr = mapper.Store(testStr) testDataPtr = OffsetPtr(testStrPtr, Marshal.OffsetOf(PyStringObject, "ob_sval")) filePtr = mapper.Store(open(path, 'w')) f = mapper.IC_PyFile_AsFile(filePtr) self.assertEquals(Unmanaged.fwrite(testDataPtr, 1, testLength, f), testLength, "didn't work") # nasty test: patch out PyObject_Free # the memory will not be deallocated, but the FILE handle should be calls = [] def Free(ptr): calls.append(ptr) freeDgt = dgt_void_ptr(Free) CPyMarshal.WriteFunctionPtrField(mapper.PyFile_Type, PyTypeObject, 'tp_free', freeDgt) mapper.DecRef(filePtr) self.assertEquals(calls, [filePtr], 'failed to call tp_free function') mgdF = open(path) result = mgdF.read() self.assertEquals(result, testStr, "failed to write (got >>%s<<) -- deallocing filePtr did not close FILE" % result) mgdF.close()
def CreateInstance(mapper, calls): tuplePtr = mapper.PyTuple_New(len(model)) dataPtr = OffsetPtr(tuplePtr, Marshal.OffsetOf(PyTupleObject, "ob_item")) for i in range(len(model)): itemPtr = mapper.Store(model[i]) itemPtrs.append(itemPtr) CPyMarshal.WritePtr(dataPtr, itemPtr) dataPtr = OffsetPtr(dataPtr, CPyMarshal.PtrSize) return tuplePtr
def testWorks(self, mapper, _): strPtr = mapper.Store( "You're fighting a business hippy. This is a hippy that understands the law of supply and demand." ) strData = CPyMarshal.Offset( strPtr, Marshal.OffsetOf(PyStringObject, 'ob_sval')) self.assertEquals(mapper.PyString_AsString(strPtr), self.dataPtrFromStrPtr(strPtr)) notstrPtr = mapper.Store(object()) self.assertEquals(mapper.PyString_AsString(notstrPtr), IntPtr.Zero) self.assertMapperHasError(mapper, TypeError)
def testFinalDecRefOfObjectWithTypeCalls_tp_dealloc(self, mapper, _): calls = [] def TypeDealloc(ptr): calls.append(ptr) deallocDgt = dgt_void_ptr(TypeDealloc) deallocFP = Marshal.GetFunctionPointerForDelegate(deallocDgt) typePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) deallocPtr = CPyMarshal.Offset(typePtr, Marshal.OffsetOf(PyTypeObject, "tp_dealloc")) CPyMarshal.WritePtr(deallocPtr, deallocFP) obj = object() objPtr = mapper.Store(obj) CPyMarshal.WritePtrField(objPtr, PyObject, "ob_type", typePtr) mapper.IncRef(objPtr) mapper.DecRef(objPtr) self.assertEquals(calls, [], "called prematurely") mapper.DecRef(objPtr) self.assertEquals(calls, [objPtr], "not called when refcount hit 0")
def dataPtrFromStrPtr(self, strPtr): return OffsetPtr(strPtr, Marshal.OffsetOf(PyStringObject, "ob_sval"))