diff options
Diffstat (limited to 'python/macholib/macholib_tests/test_ptypes.py')
-rw-r--r-- | python/macholib/macholib_tests/test_ptypes.py | 191 |
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() |