summaryrefslogtreecommitdiffstats
path: root/python/macholib/macholib_tests/test_ptypes.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/macholib/macholib_tests/test_ptypes.py')
-rw-r--r--python/macholib/macholib_tests/test_ptypes.py191
1 files changed, 191 insertions, 0 deletions
diff --git a/python/macholib/macholib_tests/test_ptypes.py b/python/macholib/macholib_tests/test_ptypes.py
new file mode 100644
index 000000000..f221d37d3
--- /dev/null
+++ b/python/macholib/macholib_tests/test_ptypes.py
@@ -0,0 +1,191 @@
+from macholib import ptypes
+
+import unittest
+import sys
+if sys.version_info[:2] <= (2,6):
+ import unittest2 as unittest
+else:
+ import unittest
+
+try:
+ from io import BytesIO
+except ImportError:
+ from cStringIO import StringIO as BytesIO
+import mmap
+
+try:
+ long
+except NameError:
+ long = int
+
+
+class TestPTypes (unittest.TestCase):
+ if not hasattr(unittest.TestCase, 'assertIsSubclass'):
+ def assertIsSubclass(self, class1, class2, message=None):
+ self.assertTrue(issubclass(class1, class2),
+ message or "%r is not a subclass of %r"%(class1, class2))
+
+ if not hasattr(unittest.TestCase, 'assertIsInstance'):
+ def assertIsInstance(self, value, types, message=None):
+ self.assertTrue(isinstance(value, types),
+ message or "%r is not an instance of %r"%(value, types))
+
+ def test_sizeof(self):
+ self.assertEqual(ptypes.sizeof(b"foobar"), 6)
+
+ self.assertRaises(ValueError, ptypes.sizeof, [])
+ self.assertRaises(ValueError, ptypes.sizeof, {})
+ self.assertRaises(ValueError, ptypes.sizeof, b"foo".decode('ascii'))
+
+ class M (object):
+ pass
+
+ m = M()
+ m._size_ = 42
+ self.assertEqual(ptypes.sizeof(m), 42)
+
+
+ def verifyType(self, ptype, size, pytype, values):
+ self.assertEqual(ptypes.sizeof(ptype), size)
+ self.assertIsSubclass(ptype, pytype)
+
+ for v in values:
+ pv = ptype(v)
+ packed = pv.to_str()
+ self.assertIsInstance(packed, bytes)
+ self.assertEqual(len(packed), size)
+
+ unp = ptype.from_str(packed)
+ self.assertIsInstance(unp, ptype)
+ self.assertEqual(unp, pv)
+
+ fp = BytesIO(packed)
+ unp = ptype.from_fileobj(fp)
+ fp.close()
+ self.assertIsInstance(unp, ptype)
+ self.assertEqual(unp, pv)
+
+ fp = BytesIO()
+ pv.to_fileobj(fp)
+ data = fp.getvalue()
+ fp.close()
+ self.assertEqual(data, packed)
+
+ mm = mmap.mmap(-1, size+20)
+ mm[:] = b'\x00' * (size+20)
+ pv.to_mmap(mm, 10)
+
+ self.assertEqual(ptype.from_mmap(mm, 10), pv)
+ self.assertEqual(mm[:], (b'\x00'*10) + packed + (b'\x00'*10))
+
+ self.assertEqual(ptype.from_tuple((v,)), pv)
+
+ def test_basic_types(self):
+ self.verifyType(ptypes.p_char, 1, bytes, [b'a', b'b'])
+ self.verifyType(ptypes.p_int8, 1, int, [1, 42, -4])
+ self.verifyType(ptypes.p_uint8, 1, int, [1, 42, 253])
+
+ self.verifyType(ptypes.p_int16, 2, int, [1, 400, -10, -5000])
+ self.verifyType(ptypes.p_uint16, 2, int, [1, 400, 65000])
+
+ self.verifyType(ptypes.p_int32, 4, int, [1, 400, 2**24, -10, -5000, -2**24])
+ self.verifyType(ptypes.p_uint32, 4, long, [1, 400, 2*31+5, 65000])
+
+ self.verifyType(ptypes.p_int64, 8, long, [1, 400, 2**43, -10, -5000, -2**43])
+ self.verifyType(ptypes.p_uint64, 8, long, [1, 400, 2*63+5, 65000])
+
+ self.verifyType(ptypes.p_float, 4, float, [1.0, 42.5])
+ self.verifyType(ptypes.p_double, 8, float, [1.0, 42.5])
+
+ def test_basic_types_deprecated(self):
+ self.verifyType(ptypes.p_byte, 1, int, [1, 42, -4])
+ self.verifyType(ptypes.p_ubyte, 1, int, [1, 42, 253])
+
+ self.verifyType(ptypes.p_short, 2, int, [1, 400, -10, -5000])
+ self.verifyType(ptypes.p_ushort, 2, int, [1, 400, 65000])
+
+ self.verifyType(ptypes.p_int, 4, int, [1, 400, 2**24, -10, -5000, -2**24])
+ self.verifyType(ptypes.p_uint, 4, long, [1, 400, 2*31+5, 65000])
+
+ self.verifyType(ptypes.p_long, 4, int, [1, 400, 2**24, -10, -5000, -2**24])
+ self.verifyType(ptypes.p_ulong, 4, long, [1, 400, 2*31+5, 65000])
+
+ self.verifyType(ptypes.p_longlong, 8, long, [1, 400, 2**43, -10, -5000, -2**43])
+ self.verifyType(ptypes.p_ulonglong, 8, long, [1, 400, 2*63+5, 65000])
+
+class TestPTypesPrivate (unittest.TestCase):
+ # These are tests for functions that aren't part of the public
+ # API.
+
+ def test_formatinfo(self):
+ self.assertEqual(ptypes._formatinfo(">b"), (1, 1))
+ self.assertEqual(ptypes._formatinfo(">h"), (2, 1))
+ self.assertEqual(ptypes._formatinfo(">HhL"), (8, 3))
+ self.assertEqual(ptypes._formatinfo("<b"), (1, 1))
+ self.assertEqual(ptypes._formatinfo("<h"), (2, 1))
+ self.assertEqual(ptypes._formatinfo("<HhL"), (8, 3))
+
+
+class MyStructure (ptypes.Structure):
+ _fields_ = (
+ ('foo', ptypes.p_int32),
+ ('bar', ptypes.p_uint8),
+ )
+
+class MyFunStructure (ptypes.Structure):
+ _fields_ = (
+ ('fun', ptypes.p_char),
+ ('mystruct', MyStructure),
+ )
+
+class TestPTypesSimple (unittest.TestCase):
+ # Quick port of tests that used to be part of
+ # the macholib.ptypes source code
+ #
+ # Moving these in a structured manner to TestPTypes
+ # would be nice, but is not extremely important.
+
+ def testBasic(self):
+ for endian in '><':
+ kw = dict(_endian_=endian)
+ MYSTRUCTURE = b'\x00\x11\x22\x33\xFF'
+ for fn, args in [
+ ('from_str', (MYSTRUCTURE,)),
+ ('from_mmap', (MYSTRUCTURE, 0)),
+ ('from_fileobj', (BytesIO(MYSTRUCTURE),)),
+ ]:
+ myStructure = getattr(MyStructure, fn)(*args, **kw)
+ if endian == '>':
+ self.assertEqual(myStructure.foo, 0x00112233)
+ else:
+ self.assertEqual( myStructure.foo, 0x33221100)
+ self.assertEqual(myStructure.bar, 0xFF)
+ self.assertEqual(myStructure.to_str(), MYSTRUCTURE)
+
+ MYFUNSTRUCTURE = b'!' + MYSTRUCTURE
+ for fn, args in [
+ ('from_str', (MYFUNSTRUCTURE,)),
+ ('from_mmap', (MYFUNSTRUCTURE, 0)),
+ ('from_fileobj', (BytesIO(MYFUNSTRUCTURE),)),
+ ]:
+ myFunStructure = getattr(MyFunStructure, fn)(*args, **kw)
+ self.assertEqual(myFunStructure.mystruct, myStructure)
+ self.assertEqual(myFunStructure.fun, b'!', (myFunStructure.fun, b'!'))
+ self.assertEqual(myFunStructure.to_str(), MYFUNSTRUCTURE)
+
+ sio = BytesIO()
+ myFunStructure.to_fileobj(sio)
+ self.assertEqual(sio.getvalue(), MYFUNSTRUCTURE)
+
+ mm = mmap.mmap(-1, ptypes.sizeof(MyFunStructure) * 2)
+ mm[:] = b'\x00' * (ptypes.sizeof(MyFunStructure) * 2)
+ myFunStructure.to_mmap(mm, 0)
+ self.assertEqual(MyFunStructure.from_mmap(mm, 0, **kw), myFunStructure)
+ self.assertEqual(mm[:ptypes.sizeof(MyFunStructure)], MYFUNSTRUCTURE)
+ self.assertEqual(mm[ptypes.sizeof(MyFunStructure):], b'\x00' * ptypes.sizeof(MyFunStructure))
+ myFunStructure.to_mmap(mm, ptypes.sizeof(MyFunStructure))
+ self.assertEqual(mm[:], MYFUNSTRUCTURE + MYFUNSTRUCTURE)
+ self.assertEqual(MyFunStructure.from_mmap(mm, ptypes.sizeof(MyFunStructure), **kw), myFunStructure)
+
+if __name__ == "__main__":
+ unittest.main()