from unittest import TestCase from .context import Bits, Bytes class TestBits(TestCase): def setUp(self): self.testObjects = [ {"bytes": b'\x7f', "bits": "01111111", "int": 127, "reverse": 254, "bitsObject": Bits(127) }, {"bytes": b'\xcf', "bits": "11001111", "int": 207, "reverse": 243, "bitsObject": Bits(207) }, {"bytes": b'{', "bits": "01111011", "int": 123, "reverse": 222, "bitsObject": Bits(123) }, {"bytes": b'<', "bits": "00111100", "int": 60, "reverse": 60, "bitsObject": Bits(60) }, {"bytes": b'>', "bits": "00111110", "int": 62, "reverse": 124, "bitsObject": Bits(62) } ] def test_class(self): """ Test various class features """ with self.subTest("Reject values > 255"): self.assertRaises(ValueError, Bits, 256) with self.subTest("Reject values < 0"): self.assertRaises(ValueError, Bits, -1) with self.subTest("Reject binary strings longer than 8 characters"): self.assertRaises(TypeError, Bits, '1100110011') with self.subTest("Index errors"): with self.assertRaises(IndexError): Bits(127)[9] with self.subTest("Test length"): self.assertEqual(len(Bits(0)), 8) def test_bytes(self): """ Test conversion to bytes object """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"])): self.assertEqual(bytes(testcase["bitsObject"]), testcase["bytes"]) def test_int(self): """ Test integer conversion """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"])): self.assertEqual(int(testcase["bitsObject"]), testcase["int"]) def test_str(self): """ Test string representation """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"])): s = str(testcase["bitsObject"]) self.assertEqual(s, testcase["bits"]) def test_bits(self): """ Test bit representation """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"])): self.assertEqual(testcase["bitsObject"].bin(), testcase["bits"]) with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [without leading zeros]"): self.assertEqual(testcase["bitsObject"].bin(pad=False), testcase["bits"].lstrip("0")) def test_reverse(self): """ Test the reverse function changes the object bitorder and value """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"])): testcase["bitsObject"].reverse() self.assertEqual(testcase["bitsObject"].bin(), testcase["bits"][::-1]) def test_membership_operators(self): """ Test the membership operator (x in y) """ with self.subTest("should all be True"): for i in range(1, 256): self.assertTrue(i in Bits(255), f"Bits({i}) in Bits(255) fail") with self.subTest("should all be False"): for i in range(1, 256): self.assertFalse(i in Bits(0), f"Bits({i}) in Bits(0) fail") with self.subTest("should pass"): self.assertIn(1, Bits("00100111"), "1 in Bits(39)") self.assertIn(2, Bits(39), "2 in Bits(39)") self.assertIn(4, Bits(39), "4 in Bits(39)") self.assertNotIn(8, Bits(39), "8 in Bits(39)") self.assertNotIn(16, Bits(39), "16 in Bits(39)") self.assertIn(32, Bits(39), "32 in Bits(39)") self.assertNotIn(64, Bits(39), "64 in Bits(39)") self.assertNotIn(128, Bits(39), "128 in Bits(39)") def test_binary_operations(self): self.assertEqual((Bits("00000100") << 3), Bits("00100000"), "Bits(4) << 3 == Bits(32)") self.assertEqual((Bits("00100000") << 1), Bits("01000000"), "Bits(32) << 1 == Bits(64)") self.assertEqual((Bits(64) >> 2), Bits(16), "Bits(64) >> 2 == Bits(16)") self.assertEqual(( 2 << Bits(6)), Bits(128), "2 << Bits(6) == Bits(128)") self.assertEqual((Bits(255) & Bits(64)), Bits(64), "Bits(255) and Bits(64) == Bits(64)") self.assertNotEqual((Bits(32) & Bits(64)), Bits(64), "Bits(32) and Bits(64) != Bits(64)") self.assertEqual((Bits(2) | Bits(32)), 34, "Bits(2) or Bits(32) == 34") self.assertEqual((Bits(80) | Bits(64)), Bits(80), "Bits(80) or Bits(64) == Bits(80)") self.assertEqual((Bits(80) ^ Bits(64)), Bits(16), "Bits(80) xor Bits(64) == Bits(16)") self.assertEqual((Bits(80) & Bits(64)), Bits(64), "Bits(80) and Bits(64) == Bits(64)") def test_comparisons(self): """ Test the comparison operators """ for testcase in self.testObjects: with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [==]"): self.assertEqual(testcase["bitsObject"], Bits(testcase["int"])) with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [!=]"): # Toggle bit 3 testobj = Bits(testcase["int"]) testobj[3] = not testobj[3] self.assertNotEqual(testobj, testcase["bitsObject"]) with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [<]"): if testcase["int"] < 255: self.assertLess(testcase["bitsObject"], Bits(255)) else: self.skipTest("value is MAX") with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [<=]"): if testcase["int"] < 255: self.assertLessEqual(testcase["bitsObject"], Bits(255)) self.assertLessEqual(testcase["bitsObject"], Bits(testcase["int"])) with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [>]"): if testcase["int"] > 0: self.assertGreater(testcase["bitsObject"], Bits(0)) else: self.skipTest("value is MIN") with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [>=]"): if testcase["int"] > 0: self.assertGreaterEqual(testcase["bitsObject"], Bits(0)) self.assertLessEqual(testcase["bitsObject"], Bits(testcase["int"]))