Mypal/python/macholib/macholib_tests/test_ptypes.py

192 lines
7.0 KiB
Python

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()