import unittest import sys PY3K = sys.version_info[0] >= 3 from fixedint import * tests = [] # ---------------------------------------------------------------------------- class ClassTests(unittest.TestCase): def test_subclass_base(self): self.assertRaises(Exception, type, 'TestClass', (FixedInt,), {}) self.assertRaises(Exception, type, 'TestClass', (MutableFixedInt,), {}) def test_class_cache(self): self.assertEqual(FixedInt(99), FixedInt(99)) self.assertEqual(MutableFixedInt(42), MutableFixedInt(42)) def test_aliases(self): self.assertEqual(FixedInt(8), Int8) self.assertEqual(FixedInt(16), Int16) self.assertEqual(FixedInt(32), Int32) self.assertEqual(FixedInt(64), Int64) self.assertEqual(FixedInt(8, signed=False), UInt8) self.assertEqual(FixedInt(16, signed=False), UInt16) self.assertEqual(FixedInt(32, signed=False), UInt32) self.assertEqual(FixedInt(64, signed=False), UInt64) def test_subclassing(self): from fixedint.util import HexFormattingMixin class MyUInt32(HexFormattingMixin, UInt32): pass self.assertEqual(str(MyUInt32(32)), '0x00000020') tests.append(ClassTests) # ---------------------------------------------------------------------------- class BasicTests(unittest.TestCase): def test_properties(self): f3 = FixedInt(3) self.assertEqual(f3.width, 3) self.assertEqual(f3.mutable, False) self.assertEqual(f3.signed, True) self.assertEqual(f3.minval, -4) self.assertEqual(f3.maxval, 3) f3 = MutableFixedInt(3) self.assertEqual(f3.width, 3) self.assertEqual(f3.mutable, True) self.assertEqual(f3.signed, True) self.assertEqual(f3.minval, -4) self.assertEqual(f3.maxval, 3) f3 = FixedInt(3, signed=False) self.assertEqual(f3.width, 3) self.assertEqual(f3.mutable, False) self.assertEqual(f3.signed, False) self.assertEqual(f3.minval, 0) self.assertEqual(f3.maxval, 7) f3 = MutableFixedInt(3, signed=False) self.assertEqual(f3.width, 3) self.assertEqual(f3.mutable, True) self.assertEqual(f3.signed, False) self.assertEqual(f3.minval, 0) self.assertEqual(f3.maxval, 7) def test_rectify(self): for f10 in [FixedInt(10), MutableFixedInt(10)]: self.assertEqual(int(f10(1024)), 0) self.assertEqual(int(f10(1025)), 1) self.assertEqual(int(f10(511)), 511) self.assertEqual(int(f10(512)), -512) for f10 in [FixedInt(10, signed=False), MutableFixedInt(10, signed=False)]: self.assertEqual(int(f10(1024)), 0) self.assertEqual(int(f10(1025)), 1) self.assertEqual(int(f10(511)), 511) self.assertEqual(int(f10(512)), 512) def test_simple_arith(self): for f8 in [Int8, MutableInt8]: a = f8(15) b = f8(10) self.assertEqual(int(a+b), 25) self.assertEqual(int(a-b), 5) self.assertEqual(int(a*b), (150-256)) self.assertEqual(a.__truediv__(b), 1.5) self.assertEqual(int(a // b), 1) self.assertEqual(divmod(a, b), (1, 5)) self.assertEqual(divmod(15, b), (1, 5)) self.assertEqual(divmod(a, 10), (1, 5)) self.assertEqual(int(a)**b, 15**10) self.assertEqual(int(a<<8), 0) self.assertEqual(8<= (2,5): self.assertEqual(list(range(100))[x], 42) if sys.version_info[:2] >= (2,6): self.assertEqual(math.trunc(x), 42) x = f16(0) self.assertEqual(bool(x), False) def test_compare(self): for f32 in [Int32, MutableInt32]: x = f32(1000000) self.assertEqual(x, 1000000) self.assertNotEqual(x, 1000000 + (1<<32)) self.assertEqual(x, f32(1000000 + (1<<32))) self.assertNotEqual(x, 1000001) self.assertTrue(x <= 1000000) self.assertTrue(x >= 1000000) self.assertTrue(x < 1000001) self.assertTrue(x > 999999) if not PY3K: self.assertTrue(cmp(x, 999999) > 0) def test_implicit_conversion(self): f = FixedInt(72) x = f(32767) y = x self.assertEqual(x, y) x += 100 self.assertNotEqual(x, y) x += FixedInt(80)(1<<79) self.assertEqual(x.width, 80) def test_inplace_operators(self): mf = MutableFixedInt(72) x = mf(32767) y = x self.assertEqual(x, y) x += 100 self.assertEqual(x, y) x += MutableFixedInt(80)(1<<79) self.assertEqual(x.width, 72) x >>= 100 self.assertEqual(x, 0) x += 2 self.assertEqual(y, 2) x **= 70 self.assertEqual(y, 2**70) def test_str(self): for ff in [FixedInt(12), MutableFixedInt(12), FixedInt(91), MutableFixedInt(91)]: self.assertEqual(str(ff(1)), '1') self.assertEqual(repr(ff(1)), '%s(1)' % ff.__name__) self.assertEqual(str(ff(-1)), '-1') self.assertEqual(hex(ff(1)), '0x1') tests.append(BasicTests) # ---------------------------------------------------------------------------- class ExtraFunctionTests(unittest.TestCase): def test_bytes(self): for ff in [FixedInt(96), MutableFixedInt(96)]: val = ff(-1) if PY3K: byte = lambda c: bytes([c]) else: byte = lambda c: chr(c) self.assertEqual(val.to_bytes(), byte(255) * 12) self.assertEqual(val.to_bytes(8), byte(255) * 8) self.assertEqual(ff.from_bytes(byte(255) * 12), val) for ff in [FixedInt(32), MutableFixedInt(32)]: for v in [0xdeadbeef, 0xfeedface, 0x0badf00d, 0x12345678, 0x87654321]: for endian in ['big', 'little']: val = ff(v) data = val.to_bytes(byteorder=endian) self.assertEqual(len(data), 4) val2 = ff.from_bytes(data, byteorder=endian) self.assertEqual(val, val2) for ff in [UInt32, MutableUInt32]: for v in [0xdeadbeef, 0xfeedface, 0x0badf00d, 0x12345678, 0x87654321]: for endian in ['big', 'little']: val = ff(v) data = val.to_bytes(byteorder=endian) self.assertEqual(len(data), 4) val2 = FixedInt.from_bytes(data, byteorder=endian, signed=False) self.assertTrue(type(val2).__name__.endswith('UInt32')) self.assertEqual(val, val2) t = UInt32(32).to_bytes() self.assertRaises(ValueError, UInt32.from_bytes, t, signed=True) def test_slice_errors(self): ff = FixedInt(24) val = ff(1024) # Steps unsupported self.assertRaises(ValueError, lambda:val[::-1]) self.assertRaises(ValueError, lambda:val[::1]) # Mixed complex numbers unsupported self.assertRaises(ValueError, lambda:val[:2+4j]) # Invalid indices self.assertRaises(IndexError, lambda:val[100:200]) self.assertRaises(IndexError, lambda:val[5:0]) self.assertRaises(IndexError, lambda:val[1024]) def test_getslice(self): for ff in [FixedInt(48), MutableFixedInt(48)]: testval = 0xfedcba123456 fixed = ff(testval) x = testval for i in range(48): self.assertEqual(fixed[i], x & 1) x >>= 1 x = testval for i in range(12): r = fixed[i*4:i*4+4] self.assertEqual(r, x & 0xf) self.assertEqual(r.width, 4) self.assertEqual(r.signed, False) x >>= 4 x = testval for i in range(12): r = fixed[i*4:4j] self.assertEqual(r, x & 0xf) self.assertEqual(r.width, 4) self.assertEqual(r.signed, False) x >>= 4 def test_setslice(self): ff = MutableFixedInt(28, signed=False) testval = 0xbadf00d val = ff(0) for i in range(28): val[i] = testval & (1<>= 4 self.assertEqual(val, testval) val = ff(0) x = testval for i in range(7): val[i*4:4j] = x & 0xf x >>= 4 self.assertEqual(val, testval) val = ff(0) val2 = val val[:] = testval self.assertEqual(val2, testval) def test_setslice_fixedint(self): # Regression test for GitHub issue #3 f16 = FixedInt(16, signed=False, mutable=True) f8 = FixedInt(8, signed=False, mutable=True) x = f16(0x0FFF) y = f8(3) x[0:8] = int(y) assert repr(x) == 'MutableUInt16(3843)' x[0:8] = y assert repr(x) == 'MutableUInt16(3843)' f95 = FixedInt(95, signed=False, mutable=True) f40 = FixedInt(40, signed=False, mutable=True) x = f95(0x0FFFFFFFFFFFFFFF) y = f40(0xF)[0:40] x[0:40] = int(y) assert bin(x) == '0b111111111111111111110000000000000000000000000000000000001111' x[0:40] = y assert bin(x) == '0b111111111111111111110000000000000000000000000000000000001111' tests.append(ExtraFunctionTests) # ---------------------------------------------------------------------------- def run(verbosity=1, repeat=1): suite = unittest.TestSuite() for cls in tests: for _ in range(repeat): suite.addTest(unittest.makeSuite(cls)) runner = unittest.TextTestRunner(verbosity=verbosity) return runner.run(suite) if __name__ == '__main__': run()