2020-10-03 20:35:46 -05:00
|
|
|
from unittest import TestCase
|
|
|
|
|
2020-11-23 01:51:45 -06:00
|
|
|
from .context import Bit, Bits, Bytes
|
2020-10-03 20:35:46 -05:00
|
|
|
|
2020-10-06 23:29:55 -05:00
|
|
|
class TestBits(TestCase):
|
2020-10-03 20:35:46 -05:00
|
|
|
def setUp(self):
|
|
|
|
self.testObjects = [
|
2020-10-06 23:29:55 -05:00
|
|
|
{"bytes": b'\x7f',
|
2020-11-23 01:51:45 -06:00
|
|
|
"str": "01111111",
|
2020-10-06 23:29:55 -05:00
|
|
|
"int": 127,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "7f",
|
2020-10-06 23:29:55 -05:00
|
|
|
"reverse": 254,
|
2020-11-23 01:51:45 -06:00
|
|
|
"bitsObject": Bits(127),
|
|
|
|
"list": [Bit(0),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1),
|
|
|
|
Bit(1)
|
|
|
|
]
|
2020-10-06 23:29:55 -05:00
|
|
|
},
|
|
|
|
{"bytes": b'\xcf',
|
2020-11-23 01:51:45 -06:00
|
|
|
"str": "11001111",
|
2020-10-06 23:29:55 -05:00
|
|
|
"int": 207,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "cf",
|
2020-10-06 23:29:55 -05:00
|
|
|
"reverse": 243,
|
2020-11-23 01:51:45 -06:00
|
|
|
"bitsObject": Bits(207),
|
|
|
|
"list": [1, 1, 0, 0, 1, 1, 1, 1]
|
2020-10-06 23:29:55 -05:00
|
|
|
},
|
|
|
|
{"bytes": b'{',
|
2020-11-23 01:51:45 -06:00
|
|
|
"str": "01111011",
|
2020-10-06 23:29:55 -05:00
|
|
|
"int": 123,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "7b",
|
2020-10-06 23:29:55 -05:00
|
|
|
"reverse": 222,
|
2020-11-23 01:51:45 -06:00
|
|
|
"bitsObject": Bits(123),
|
|
|
|
"list": ["0", "1", "1", "1", "1", "0", "1", "1"]
|
|
|
|
|
2020-10-06 23:29:55 -05:00
|
|
|
},
|
|
|
|
{"bytes": b'<',
|
2020-11-23 01:51:45 -06:00
|
|
|
"str": "00111100",
|
2020-10-06 23:29:55 -05:00
|
|
|
"int": 60,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "3c",
|
2020-10-06 23:29:55 -05:00
|
|
|
"reverse": 60,
|
2020-11-23 01:51:45 -06:00
|
|
|
"bitsObject": Bits(60),
|
|
|
|
"list": [False,
|
|
|
|
False,
|
|
|
|
True,
|
|
|
|
True,
|
|
|
|
True,
|
|
|
|
True,
|
|
|
|
False,
|
|
|
|
False
|
|
|
|
]
|
2020-10-06 23:29:55 -05:00
|
|
|
},
|
|
|
|
{"bytes": b'>',
|
2020-11-23 01:51:45 -06:00
|
|
|
"str": "00111110",
|
2020-10-06 23:29:55 -05:00
|
|
|
"int": 62,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "3e",
|
2020-10-06 23:29:55 -05:00
|
|
|
"reverse": 124,
|
2020-11-23 01:51:45 -06:00
|
|
|
"bitsObject": Bits(62),
|
|
|
|
"list": [0,
|
|
|
|
False,
|
|
|
|
"1",
|
|
|
|
1,
|
|
|
|
Bit("1"),
|
|
|
|
Bit(True),
|
|
|
|
Bit(1),
|
|
|
|
Bit(False)
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{"bytes": b'=',
|
|
|
|
"str": "00111101",
|
|
|
|
"int": 61,
|
2021-04-13 01:41:39 -05:00
|
|
|
"hex": "3d",
|
2020-11-23 01:51:45 -06:00
|
|
|
"reverse": 188,
|
|
|
|
"bitsObject": Bits(61),
|
|
|
|
"list": [True, 1, 1, True, Bit(0), Bit(1)]
|
2020-10-03 20:35:46 -05:00
|
|
|
}
|
|
|
|
]
|
|
|
|
|
2020-10-06 23:29:55 -05:00
|
|
|
def test_class(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test various class features"""
|
2020-10-06 23:29:55 -05:00
|
|
|
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)
|
|
|
|
|
2020-10-03 20:35:46 -05:00
|
|
|
def test_bytes(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test conversion to bytes objects"""
|
2020-10-03 20:35:46 -05:00
|
|
|
for testcase in self.testObjects:
|
2020-10-06 23:29:55 -05:00
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"])):
|
|
|
|
self.assertEqual(bytes(testcase["bitsObject"]),
|
|
|
|
testcase["bytes"])
|
2020-10-03 20:35:46 -05:00
|
|
|
|
|
|
|
def test_int(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test integer conversion"""
|
2020-10-03 20:35:46 -05:00
|
|
|
for testcase in self.testObjects:
|
2020-10-06 23:29:55 -05:00
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"])):
|
|
|
|
self.assertEqual(int(testcase["bitsObject"]), testcase["int"])
|
2020-10-03 20:35:46 -05:00
|
|
|
|
2021-04-13 01:41:39 -05:00
|
|
|
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"])
|
|
|
|
|
2020-10-03 20:35:46 -05:00
|
|
|
def test_str(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test string representation"""
|
2020-10-06 23:29:55 -05:00
|
|
|
for testcase in self.testObjects:
|
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"])):
|
|
|
|
s = str(testcase["bitsObject"])
|
2020-11-23 01:51:45 -06:00
|
|
|
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"])))
|
2020-10-06 23:29:55 -05:00
|
|
|
|
|
|
|
def test_bits(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test bit representation"""
|
2020-10-06 23:29:55 -05:00
|
|
|
for testcase in self.testObjects:
|
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"])):
|
|
|
|
self.assertEqual(testcase["bitsObject"].bin(),
|
2020-11-23 01:51:45 -06:00
|
|
|
testcase["str"])
|
2020-10-06 23:29:55 -05:00
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"]) \
|
|
|
|
+ " [without leading zeros]"):
|
|
|
|
self.assertEqual(testcase["bitsObject"].bin(pad=False),
|
2020-11-23 01:51:45 -06:00
|
|
|
testcase["str"].lstrip("0"))
|
2020-10-06 23:29:55 -05:00
|
|
|
|
|
|
|
def test_reverse(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test the reverse function changes the object bitorder and value"""
|
2020-10-04 13:11:46 -05:00
|
|
|
for testcase in self.testObjects:
|
2020-10-06 23:29:55 -05:00
|
|
|
with self.subTest("testcase[\"int\"]: " + str(testcase["int"])):
|
|
|
|
testcase["bitsObject"].reverse()
|
|
|
|
self.assertEqual(testcase["bitsObject"].bin(),
|
2020-11-23 01:51:45 -06:00
|
|
|
testcase["str"][::-1])
|
2020-10-03 20:35:46 -05:00
|
|
|
|
2020-10-13 01:32:50 -05:00
|
|
|
def test_membership_operators(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test the membership operator (x in y)"""
|
2020-10-13 01:32:50 -05:00
|
|
|
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)")
|
|
|
|
|
2020-10-06 23:29:55 -05:00
|
|
|
def test_comparisons(self):
|
2020-11-23 01:51:45 -06:00
|
|
|
"""Test the comparison operators"""
|
2020-10-04 13:11:46 -05:00
|
|
|
for testcase in self.testObjects:
|
2020-10-06 23:29:55 -05:00
|
|
|
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"]))
|
2020-10-03 20:35:46 -05:00
|
|
|
|