def testSizes(self, mapper, _): tp_basicsize = CPyMarshal.ReadIntField(mapper.PyString_Type, PyTypeObject, 'tp_basicsize') self.assertNotEquals(tp_basicsize, 0) tp_itemsize = CPyMarshal.ReadIntField(mapper.PyString_Type, PyTypeObject, 'tp_itemsize') self.assertNotEquals(tp_itemsize, 0)
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 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 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 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 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 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 testStoreType(self, mapper, _): self.assertEquals(mapper.Retrieve(mapper.PyFunction_Type), FunctionType) self.assertEquals( CPyMarshal.ReadIntField(mapper.PyFunction_Type, PyTypeObject, 'tp_basicsize'), Marshal.SizeOf(PyFunctionObject()))
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 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 testStoreOldStyle(self, mapper, _): class O(): pass OPtr = mapper.Store(O) self.assertEquals(CPyMarshal.ReadIntField(OPtr, PyObject, "ob_refcnt"), 2) # again, leak classes deliberately self.assertEquals(CPyMarshal.ReadPtrField(OPtr, PyObject, "ob_type"), mapper.PyClass_Type) self.assertEquals( mapper.Retrieve( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_bases")), ()) self.assertEquals( mapper.Retrieve( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_name")), "O") self.assertEquals( mapper.Retrieve( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_dict")) is O.__dict__, True) self.assertEquals( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_getattr"), IntPtr.Zero) self.assertEquals( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_setattr"), IntPtr.Zero) self.assertEquals( CPyMarshal.ReadPtrField(OPtr, PyClassObject, "cl_delattr"), IntPtr.Zero) o = O() oPtr = mapper.Store(o) self.assertEquals(CPyMarshal.ReadIntField(oPtr, PyObject, "ob_refcnt"), 1) self.assertEquals(CPyMarshal.ReadPtrField(oPtr, PyObject, "ob_type"), mapper.PyInstance_Type) self.assertEquals( CPyMarshal.ReadPtrField(oPtr, PyInstanceObject, "in_class"), OPtr) self.assertEquals( mapper.Retrieve( CPyMarshal.ReadPtrField(oPtr, PyInstanceObject, "in_dict")) is o.__dict__, True) self.assertEquals( CPyMarshal.ReadPtrField(oPtr, PyInstanceObject, "in_weakreflist"), IntPtr.Zero)
def testPyInt_FromSsize_t(self, mapper, _): for value in (0, Int32.MaxValue, Int32.MinValue): ptr = mapper.PyInt_FromSsize_t(value) self.assertEquals(mapper.Retrieve(ptr), value) self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyIntObject, "ob_type"), mapper.PyInt_Type) self.assertEquals( CPyMarshal.ReadIntField(ptr, PyIntObject, "ob_ival"), value) mapper.DecRef(ptr)
def testStoreInt(self, mapper, _): for value in (0, Int32.MaxValue, Int32.MinValue): ptr = mapper.Store(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyIntObject, "ob_type"), mapper.PyInt_Type) self.assertEquals( CPyMarshal.ReadIntField(ptr, PyIntObject, "ob_ival"), value) mapper.DecRef(ptr)
def testReadIntField(self): data = Marshal.AllocHGlobal(Marshal.SizeOf(PyIntObject())) CPyMarshal.Zero(data, Marshal.SizeOf(PyIntObject())) for value in (Int32.MaxValue, Int32.MinValue): CPyMarshal.WriteIntField(data, PyIntObject, "ob_ival", value) self.assertEquals( CPyMarshal.ReadIntField(data, PyIntObject, "ob_ival"), value, "failed to read") Marshal.FreeHGlobal(data)
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 testPyFloat_FromDouble(self, mapper, _): for value in (0.0, 3.3e33, -3.3e-33): ptr = mapper.PyFloat_FromDouble(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadIntField(ptr, PyFloatObject, "ob_refcnt"), 1) self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyFloatObject, "ob_type"), mapper.PyFloat_Type) self.assertEquals( CPyMarshal.ReadDoubleField(ptr, PyFloatObject, "ob_fval"), value) mapper.DecRef(ptr)
def testStoreUnknownType(self, mapper, _): class C(object): __name__ = "cantankerous.cochineal" cPtr = mapper.Store(C) self.assertEquals(CPyMarshal.ReadIntField(cPtr, PyTypeObject, "ob_refcnt"), 2, "seems easiest to 'leak' types, and ensure they live forever") self.assertEquals(CPyMarshal.ReadPtrField(cPtr, PyTypeObject, "ob_type"), mapper.PyType_Type) self.assertEquals(CPyMarshal.ReadPtrField(cPtr, PyTypeObject, "tp_base"), mapper.PyBaseObject_Type) self.assertEquals(CPyMarshal.ReadPtrField(cPtr, PyTypeObject, "tp_bases"), IntPtr.Zero) self.assertEquals(CPyMarshal.ReadPtrField(cPtr, PyTypeObject, "tp_as_number"), IntPtr.Zero) namePtr = CPyMarshal.ReadPtrField(cPtr, PyTypeObject, "tp_name") self.assertEquals(mapper.Retrieve(namePtr), "cantankerous.cochineal") baseFlags = CPyMarshal.ReadIntField(cPtr, PyTypeObject, "tp_flags") self.assertEquals(baseFlags & UInt32(Py_TPFLAGS.READY), UInt32(Py_TPFLAGS.READY), "did not ready newly-stored type") instancePtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject)) CPyMarshal.WritePtrField(instancePtr, PyObject, "ob_type", cPtr) CPyMarshal.WriteIntField(instancePtr, PyObject, "ob_refcnt", 2) instance = mapper.Retrieve(instancePtr) self.assertEquals(isinstance(instance, C), True) self.assertEquals(mapper.Store(instance), instancePtr)
def testPySequence_GetItem_DoesNotActualiseTuples(self, mapper, _): obj1 = object() obj1Ptr = mapper.Store(obj1) obj2 = object() obj2Ptr = mapper.Store(obj2) tuplePtr = mapper.PyTuple_New(1) CPyMarshal.WritePtrField(tuplePtr, PyTupleObject, "ob_item", obj1Ptr) # check that GetItem returns correct object, increffed self.assertEquals(mapper.PySequence_GetItem(tuplePtr, 0), obj1Ptr) self.assertEquals(CPyMarshal.ReadIntField(obj1Ptr, PyObject, "ob_refcnt"), 2) # replace item, check that correct object is retrieved CPyMarshal.WritePtrField(tuplePtr, PyTupleObject, "ob_item", obj2Ptr) self.assertEquals(mapper.Retrieve(tuplePtr), (obj2,))
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 testStoreComplex(self, mapper, _): for value in (0 + 0j, 1 + 3.3e33j, -3.3e-33 - 1j): ptr = mapper.Store(value) self.assertEquals(mapper.Retrieve(ptr), value, "stored/retrieved wrong") self.assertEquals( CPyMarshal.ReadIntField(ptr, PyComplexObject, "ob_refcnt"), 1) self.assertEquals( CPyMarshal.ReadPtrField(ptr, PyComplexObject, "ob_type"), mapper.PyComplex_Type) cpxptr = CPyMarshal.GetField(ptr, PyComplexObject, "cval") self.assertEquals( CPyMarshal.ReadDoubleField(cpxptr, Py_complex, "real"), value.real) self.assertEquals( CPyMarshal.ReadDoubleField(cpxptr, Py_complex, "imag"), value.imag) mapper.DecRef(ptr)
def test_PyObject_New(self): allocs = [] allocator = GetAllocatingTestAllocator(allocs, []) mapper = PythonMapper(allocator) deallocTypes = CreateTypes(mapper) typeObjSize = Marshal.SizeOf(PyTypeObject()) typePtr = Marshal.AllocHGlobal(typeObjSize) CPyMarshal.Zero(typePtr, typeObjSize) CPyMarshal.WriteIntField(typePtr, PyTypeObject, "tp_basicsize", 31337) del allocs[:] objPtr = mapper._PyObject_New(typePtr) self.assertEquals(allocs, [(objPtr, 31337)]) self.assertEquals(CPyMarshal.ReadPtrField(objPtr, PyObject, 'ob_type'), typePtr) self.assertEquals(CPyMarshal.ReadIntField(objPtr, PyObject, 'ob_refcnt'), 1) self.assertEquals(mapper.HasPtr(objPtr), False) mapper.Dispose() deallocTypes()
def assertNoTypeSubclassFlag(self, mapper, t): typeFlags = CPyMarshal.ReadIntField(mapper.Store(t), PyTypeObject, "tp_flags") self.assertEquals(typeFlags & SUBCLASS_FLAGS_MASK, 0, "had bad flag")
def assertTypeSubclassFlag(self, mapper, t, f): typeFlags = CPyMarshal.ReadIntField(mapper.Store(t), PyTypeObject, "tp_flags") self.assertEquals(typeFlags & UInt32(f), UInt32(f), "did not have appropriate flag")
def assertSizes(self, ptr, basic, item=0): self.assertEquals(CPyMarshal.ReadIntField(ptr, PyTypeObject, "tp_basicsize"), basic) self.assertEquals(CPyMarshal.ReadIntField(ptr, PyTypeObject, "tp_itemsize"), item)