from unittest import TestCase from .context import Bit, Bits, Bytes class TestBits(TestCase): def setUp(self): self.testObjects = [ {"bytes": b'\x7f', "str": "01111111", "int": 127, "hex": "7f", "reverse": 254, "bitsObject": Bits(127), "list": [Bit(0), Bit(1), Bit(1), Bit(1), Bit(1), Bit(1), Bit(1), Bit(1) ] }, {"bytes": b'\xcf', "str": "11001111", "int": 207, "hex": "cf", "reverse": 243, "bitsObject": Bits(207), "list": [1, 1, 0, 0, 1, 1, 1, 1] }, {"bytes": b'{', "str": "01111011", "int": 123, "hex": "7b", "reverse": 222, "bitsObject": Bits(123), "list": ["0", "1", "1", "1", "1", "0", "1", "1"] }, {"bytes": b'<', "str": "00111100", "int": 60, "hex": "3c", "reverse": 60, "bitsObject": Bits(60), "list": [False, False, True, True, True, True, False, False ] }, {"bytes": b'>', "str": "00111110", "int": 62, "hex": "3e", "reverse": 124, "bitsObject": Bits(62), "list": [0, False, "1", 1, Bit("1"), Bit(True), Bit(1), Bit(False) ] }, {"bytes": b'=', "str": "00111101", "int": 61, "hex": "3d", "reverse": 188, "bitsObject": Bits(61), "list": [True, 1, 1, True, Bit(0), Bit(1)] } ] 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 objects""" 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_hex(self): """Test conversion to hex""" for testcase in self.testObjects: with self.subTest("testcase[\"hex\"]: " + str(testcase["hex"])): self.assertEqual(testcase["bitsObject"].hex(), testcase["hex"]) 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["str"]) def test_list(self): """Test list conversion""" for testcase in self.testObjects: with self.subTest("testcase[\"list\"]: " + str(testcase["list"])): self.assertEqual(testcase["bytes"], bytes(Bits(testcase["list"]))) 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["str"]) with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \ + " [without leading zeros]"): self.assertEqual(testcase["bitsObject"].bin(pad=False), testcase["str"].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["str"][::-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"]))