def test_edge_case_schemas(self): """ Test if schemas containing large number of keys are handled correctly """ large_schema = MagicMock() large_schema.__len__.return_value = 300 very_large_schema = MagicMock() very_large_schema.__len__.return_value = int(math.pow(2, 32) - 1) edge_case_schema = MagicMock() edge_case_schema.__len__.return_value = sys.maxsize try: MessageFactory(large_schema) MessageFactory(very_large_schema) MessageFactory(edge_case_schema) except ImproperlyConfigured: self.fail()
def setUp(self): self.factory = MessageFactory(self.schema)
class TestMessages(unittest.TestCase): """ Full test suite for message packing/unpacking and error handling """ schema = { 'FooMessage': { 'enums': { 'direction': { 'north': 1, 'south': 2, 'east': 3, 'west': 4 } }, 'format': { 'x': 'uint', 'y': 'uint', 'direction': 'enum' } }, 'BarMessage': { 'format': { 'name': 'string', 'score': 'ushort', } }, 'VectorMessage': { 'format': { 'x': 'float', 'y': 'float' } } } def setUp(self): self.factory = MessageFactory(self.schema) def get_foo_msg(self, x=1, y=3, direction='south'): """" Returns an instance of a FooMessage """ msg = self.factory.get('FooMessage')() msg['x'] = x msg['y'] = y msg['direction'] = direction return msg def get_bar_msg(self, name=u'Yoda', score=42): """" Returns an instance of BarMessage """ msg = self.factory.get("BarMessage")() msg['name'] = name msg['score'] = score return msg def get_vector_msg(self, x=1, y=7.77): """" Returns an instance of VectorMessage """ msg = self.factory.get("VectorMessage")() msg['x'] = x msg['y'] = y return msg def test_message_factory(self): """" Test if factory produces correct classes """ FooMessage = self.factory.get('FooMessage') BarMessage = self.factory.get('BarMessage') self.assertEqual(FooMessage.__name__, 'FooMessage') self.assertEqual(FooMessage.binary_format, '!BBII') self.assertEqual(FooMessage.id, 2) self.assertEqual(BarMessage.binary_format, '!BI{}sH') self.assertEqual(BarMessage.id, 1) def test_packing(self): """" Test if message is packed correctly into a binary string """ msg = self.get_foo_msg(x=2, y=4, direction='east') packed = pack_message(msg) self.assertEqual(len(packed), 1 + 1 + 4 + 4) self.assertEqual(packed[0:1], struct.pack('!B', 2)) # msg id self.assertEqual(packed[1:2], struct.pack('!B', 3)) # direction self.assertEqual(packed[2:6], struct.pack('!I', 2)) # x self.assertEqual(packed[6:10], struct.pack('!I', 4)) # y def test_packing_with_string(self): """ Test if message containing an unicode string is correctly packed into a binary string """ msg = self.get_bar_msg(name=u'Mr ☃') string_length = len(bytes(u'Mr ☃', 'utf-8')) packed = pack_message(msg) self.assertEqual(len(packed), 1 + 2 + 4 + string_length) self.assertEqual(packed[0:1], struct.pack('!B', 1)) # msg id self.assertEqual(packed[1:5], struct.pack( '!I', string_length)) # length of the following string self.assertEqual( packed[5:5 + string_length], struct.pack('!{}s'.format(string_length), bytes(u'Mr ☃', 'utf-8'))) self.assertEqual(packed[5 + string_length:7 + string_length], struct.pack('!H', 42)) # score def test_unpacking(self): """ Test if message is correctly unpacked from a binary string back into an object """ x = 1 y = 7.77 msg = self.get_vector_msg(x=1, y=7.77) packed = struct.pack("!B", 3) + \ struct.pack("!f", 1) + \ struct.pack("!f", 7.77) msg = unpack_message(packed, self.factory) self.assertEqual(msg['x'], x) self.assertAlmostEqual(msg['y'], y, places=4) def test_unpacking_with_string(self): """ Test if message containing an unicode string is is correctly unpacked from a binary string back into an object """ msg = self.get_bar_msg(name=u'Mr ☃') string_length = len(bytes(u'Mr ☃', 'utf-8')) packed = struct.pack("!B", 1) + \ struct.pack("!I", string_length) + \ struct.pack( "!{}s".format(string_length), bytes(u'Mr ☃', 'utf-8') ) + \ struct.pack("!H", 42) msg = unpack_message(packed, self.factory) self.assertEqual(msg['name'], u'Mr ☃') self.assertEqual(msg['score'], 42) def test_eating_own_dog_food(self): """ Test if message remaines the same after packing/unpacking cycle """ msg = self.get_foo_msg() packed = pack_message(msg) unpacked = unpack_message(packed, self.factory) self.assertEqual(msg, unpacked) def test_unpacking_many(self): """ Test if multiple messages are correctly unpacked from a binary string ot an array of objects """ msg = self.get_foo_msg() packed = struct.pack("!B", msg.__class__.id) + struct.pack("!B", 2) + \ struct.pack('!I', 1) + struct.pack('!I', 3) msg = self.get_bar_msg() string_length = len(bytes(msg['name'], 'utf-8')) packed += struct.pack("!B", msg.__class__.id) + \ struct.pack("!I", string_length) + \ struct.pack("!{}s".format(string_length), bytes(msg['name'], 'utf-8')) + \ struct.pack("!H", 42) msg = self.get_vector_msg() packed += struct.pack("!B", msg.__class__.id) + \ struct.pack("!f", 1) + \ struct.pack("!f", 7.77) unpacked = unpack_messages(packed, self.factory) self.assertEqual(unpacked[0].__class__.__name__, 'FooMessage') self.assertEqual(unpacked[1].__class__.__name__, 'BarMessage') self.assertEqual(unpacked[2].__class__.__name__, 'VectorMessage') self.assertEqual(unpacked[0]['direction'], 'south') self.assertEqual(unpacked[0]['x'], 1) self.assertEqual(unpacked[0]['y'], 3) self.assertEqual(unpacked[1]['name'], u'Yoda') self.assertEqual(unpacked[1]['score'], 42) self.assertEqual(unpacked[2]['x'], 1) self.assertAlmostEqual(unpacked[2]['y'], 7.77, places=2) def test_unpacking_many_of_one_type(self): """ Test if multiple messages of one kind are correctly unpacked from a binary string ot an array of objects """ packed = b'' for n in range(10): msg = self.get_foo_msg() packed += struct.pack("!B", msg.__class__.id) + struct.pack("!B", 2) + \ struct.pack('!I', 1) + struct.pack('!I', 3) unpacked = unpack_messages(packed, self.factory) self.assertEqual(unpacked[0].__class__.__name__, 'FooMessage') self.assertEqual(unpacked[1].__class__.__name__, 'FooMessage') self.assertEqual(unpacked[0]['direction'], 'south') self.assertEqual(unpacked[0]['x'], 1) self.assertEqual(unpacked[0]['y'], 3) def test_packing_many(self): """ Test if an array of messages is correctly packed into a binary string """ messages = [] msg1 = self.get_foo_msg() messages.append(msg1) our_packed = struct.pack("!B", msg1.__class__.id) + \ struct.pack("!B", 2) + \ struct.pack('!I', 1) + \ struct.pack('!I', 3) msg2 = self.get_bar_msg() messages.append(msg2) string_length = len(bytes(msg2['name'], 'utf-8')) our_packed += struct.pack("!B", msg2.__class__.id) + \ struct.pack("!I", string_length) + \ struct.pack("!{}s".format(string_length), bytes(msg2['name'], 'utf-8')) + \ struct.pack("!H", 42) msg3 = self.get_vector_msg() messages.append(msg3) our_packed += struct.pack("!B", msg3.__class__.id) + \ struct.pack("!f", 1) + \ struct.pack("!f", 7.77) their_packed = pack_messages(messages) self.assertEqual(our_packed, their_packed) def test_packing_many_of_one_type(self): """ Test if an array of messages is correctly packed into a binary string """ messages = [] our_packed = b'' for n in range(10): msg = self.get_foo_msg() messages.append(msg) our_packed += struct.pack("!B", msg.__class__.id) + \ struct.pack("!B", 2) + \ struct.pack('!I', 1) + \ struct.pack('!I', 3) their_packed = pack_messages_of_single_type(messages) self.assertEqual(our_packed, their_packed) def test_edge_case_schemas(self): """ Test if schemas containing large number of keys are handled correctly """ large_schema = MagicMock() large_schema.__len__.return_value = 300 very_large_schema = MagicMock() very_large_schema.__len__.return_value = int(math.pow(2, 32) - 1) edge_case_schema = MagicMock() edge_case_schema.__len__.return_value = sys.maxsize try: MessageFactory(large_schema) MessageFactory(very_large_schema) MessageFactory(edge_case_schema) except ImproperlyConfigured: self.fail() def test_bad_schema(self): """ Test if schemas containing too many keys are caught correctly Test if schemas containing incorrect value types are caught correctly """ bad_schema = MagicMock() bad_schema.__len__.return_value = sys.maxsize + 1 bad_format_schema = { 'BadMessage': { 'format': { 'bad_property': 'shibboleth', } } } self.assertRaises(ImproperlyConfigured, MessageFactory, bad_schema) self.assertRaises(ImproperlyConfigured, MessageFactory, bad_format_schema) def test_bad_enum(self): """ Test if schema with invalid enums is caught correctly """ allthings = MagicMock() allthings.__len__.return_value = sys.maxsize + 1 bad_schema = { 'BadMessage': { 'enums': { 'allthings': allthings }, 'format': { 'allthings': 'enum' } } } self.assertRaises(ImproperlyConfigured, MessageFactory, bad_schema) def test_bad_msg_lookup(self): """ Test if making an invalid message class lookup is caught correctly """ try: self.factory.get('FooMessage') self.factory.get(1) except KeyError: self.fail() self.assertRaises(KeyError, self.factory.get, 'FlyingCars') self.assertRaises(KeyError, self.factory.get, 999) def test_bad_enum_lookup(self): """ Test if making an invalid enum lookup is caught correctly """ FooMessage = self.factory.get('FooMessage') try: FooMessage.enum_lookup('direction', 'south') except KeyError: self.fail() try: FooMessage.enum_reverse_lookup('direction', 2) except KeyError: self.fail() self.assertRaises(KeyError, FooMessage.enum_lookup, 'direction', 'shibboleth') self.assertRaises(KeyError, FooMessage.enum_lookup, 'shibboleth', 'south') self.assertRaises(KeyError, FooMessage.enum_reverse_lookup, 'direction', 5) self.assertRaises(KeyError, FooMessage.enum_reverse_lookup, 'shibboleth', 2)
class TestMessages(unittest.TestCase): """ Full test suite for message packing/unpacking and error handling """ schema = { "FooMessage": { "enums": {"direction": {"north": 1, "south": 2, "east": 3, "west": 4}}, "format": {"x": "uint", "y": "uint", "direction": "enum"}, }, "BarMessage": {"format": {"name": "string", "score": "ushort"}}, "VectorMessage": {"format": {"x": "float", "y": "float"}}, } def setUp(self): self.factory = MessageFactory(self.schema) def get_foo_msg(self, x=1, y=3, direction="south"): """" Returns an instance of a FooMessage """ msg = self.factory.get("FooMessage")() msg["x"] = x msg["y"] = y msg["direction"] = direction return msg def get_bar_msg(self, name=u"Yoda", score=42): """" Returns an instance of BarMessage """ msg = self.factory.get("BarMessage")() msg["name"] = name msg["score"] = score return msg def get_vector_msg(self, x=1, y=7.77): """" Returns an instance of VectorMessage """ msg = self.factory.get("VectorMessage")() msg["x"] = x msg["y"] = y return msg def test_message_factory(self): """" Test if factory produces correct classes """ FooMessage = self.factory.get("FooMessage") BarMessage = self.factory.get("BarMessage") self.assertEqual(FooMessage.__name__, "FooMessage") self.assertEqual(FooMessage.binary_format, "!BBII") self.assertEqual(FooMessage.id, 2) self.assertEqual(BarMessage.binary_format, "!BI{}sH") self.assertEqual(BarMessage.id, 1) def test_packing(self): """" Test if message is packed correctly into a binary string """ msg = self.get_foo_msg(x=2, y=4, direction="east") packed = pack_message(msg) self.assertEqual(len(packed), 1 + 1 + 4 + 4) self.assertEqual(packed[0:1], struct.pack("!B", 2)) # msg id self.assertEqual(packed[1:2], struct.pack("!B", 3)) # direction self.assertEqual(packed[2:6], struct.pack("!I", 2)) # x self.assertEqual(packed[6:10], struct.pack("!I", 4)) # y def test_packing_with_string(self): """ Test if message containing an unicode string is correctly packed into a binary string """ msg = self.get_bar_msg(name=u"Mr ☃") string_length = len(bytes(u"Mr ☃", "utf-8")) packed = pack_message(msg) self.assertEqual(len(packed), 1 + 2 + 4 + string_length) self.assertEqual(packed[0:1], struct.pack("!B", 1)) # msg id self.assertEqual(packed[1:5], struct.pack("!I", string_length)) # length of the following string self.assertEqual( packed[5 : 5 + string_length], struct.pack("!{}s".format(string_length), bytes(u"Mr ☃", "utf-8")) ) self.assertEqual(packed[5 + string_length : 7 + string_length], struct.pack("!H", 42)) # score def test_unpacking(self): """ Test if message is correctly unpacked from a binary string back into an object """ x = 1 y = 7.77 msg = self.get_vector_msg(x=1, y=7.77) packed = struct.pack("!B", 3) + struct.pack("!f", 1) + struct.pack("!f", 7.77) msg = unpack_message(packed, self.factory) self.assertEqual(msg["x"], x) self.assertAlmostEqual(msg["y"], y, places=4) def test_unpacking_with_string(self): """ Test if message containing an unicode string is is correctly unpacked from a binary string back into an object """ msg = self.get_bar_msg(name=u"Mr ☃") string_length = len(bytes(u"Mr ☃", "utf-8")) packed = ( struct.pack("!B", 1) + struct.pack("!I", string_length) + struct.pack("!{}s".format(string_length), bytes(u"Mr ☃", "utf-8")) + struct.pack("!H", 42) ) msg = unpack_message(packed, self.factory) self.assertEqual(msg["name"], u"Mr ☃") self.assertEqual(msg["score"], 42) def test_eating_own_dog_food(self): """ Test if message remaines the same after packing/unpacking cycle """ msg = self.get_foo_msg() packed = pack_message(msg) unpacked = unpack_message(packed, self.factory) self.assertEqual(msg, unpacked) def test_unpacking_many(self): """ Test if multiple messages are correctly unpacked from a binary string ot an array of objects """ msg = self.get_foo_msg() packed = ( struct.pack("!B", msg.__class__.id) + struct.pack("!B", 2) + struct.pack("!I", 1) + struct.pack("!I", 3) ) msg = self.get_bar_msg() string_length = len(bytes(msg["name"], "utf-8")) packed += ( struct.pack("!B", msg.__class__.id) + struct.pack("!I", string_length) + struct.pack("!{}s".format(string_length), bytes(msg["name"], "utf-8")) + struct.pack("!H", 42) ) msg = self.get_vector_msg() packed += struct.pack("!B", msg.__class__.id) + struct.pack("!f", 1) + struct.pack("!f", 7.77) unpacked = unpack_messages(packed, self.factory) self.assertEqual(unpacked[0].__class__.__name__, "FooMessage") self.assertEqual(unpacked[1].__class__.__name__, "BarMessage") self.assertEqual(unpacked[2].__class__.__name__, "VectorMessage") self.assertEqual(unpacked[0]["direction"], "south") self.assertEqual(unpacked[0]["x"], 1) self.assertEqual(unpacked[0]["y"], 3) self.assertEqual(unpacked[1]["name"], u"Yoda") self.assertEqual(unpacked[1]["score"], 42) self.assertEqual(unpacked[2]["x"], 1) self.assertAlmostEqual(unpacked[2]["y"], 7.77, places=2) def test_unpacking_many_of_one_type(self): """ Test if multiple messages of one kind are correctly unpacked from a binary string ot an array of objects """ packed = b"" for n in range(10): msg = self.get_foo_msg() packed += ( struct.pack("!B", msg.__class__.id) + struct.pack("!B", 2) + struct.pack("!I", 1) + struct.pack("!I", 3) ) unpacked = unpack_messages(packed, self.factory) self.assertEqual(unpacked[0].__class__.__name__, "FooMessage") self.assertEqual(unpacked[1].__class__.__name__, "FooMessage") self.assertEqual(unpacked[0]["direction"], "south") self.assertEqual(unpacked[0]["x"], 1) self.assertEqual(unpacked[0]["y"], 3) def test_packing_many(self): """ Test if an array of messages is correctly packed into a binary string """ messages = [] msg1 = self.get_foo_msg() messages.append(msg1) our_packed = ( struct.pack("!B", msg1.__class__.id) + struct.pack("!B", 2) + struct.pack("!I", 1) + struct.pack("!I", 3) ) msg2 = self.get_bar_msg() messages.append(msg2) string_length = len(bytes(msg2["name"], "utf-8")) our_packed += ( struct.pack("!B", msg2.__class__.id) + struct.pack("!I", string_length) + struct.pack("!{}s".format(string_length), bytes(msg2["name"], "utf-8")) + struct.pack("!H", 42) ) msg3 = self.get_vector_msg() messages.append(msg3) our_packed += struct.pack("!B", msg3.__class__.id) + struct.pack("!f", 1) + struct.pack("!f", 7.77) their_packed = pack_messages(messages) self.assertEqual(our_packed, their_packed) def test_packing_many_of_one_type(self): """ Test if an array of messages is correctly packed into a binary string """ messages = [] our_packed = b"" for n in range(10): msg = self.get_foo_msg() messages.append(msg) our_packed += ( struct.pack("!B", msg.__class__.id) + struct.pack("!B", 2) + struct.pack("!I", 1) + struct.pack("!I", 3) ) their_packed = pack_messages_of_single_type(messages) self.assertEqual(our_packed, their_packed) def test_edge_case_schemas(self): """ Test if schemas containing large number of keys are handled correctly """ large_schema = MagicMock() large_schema.__len__.return_value = 300 very_large_schema = MagicMock() very_large_schema.__len__.return_value = int(math.pow(2, 32) - 1) edge_case_schema = MagicMock() edge_case_schema.__len__.return_value = sys.maxsize try: MessageFactory(large_schema) MessageFactory(very_large_schema) MessageFactory(edge_case_schema) except ImproperlyConfigured: self.fail() def test_bad_schema(self): """ Test if schemas containing too many keys are caught correctly Test if schemas containing incorrect value types are caught correctly """ bad_schema = MagicMock() bad_schema.__len__.return_value = sys.maxsize + 1 bad_format_schema = {"BadMessage": {"format": {"bad_property": "shibboleth"}}} self.assertRaises(ImproperlyConfigured, MessageFactory, bad_schema) self.assertRaises(ImproperlyConfigured, MessageFactory, bad_format_schema) def test_bad_enum(self): """ Test if schema with invalid enums is caught correctly """ allthings = MagicMock() allthings.__len__.return_value = sys.maxsize + 1 bad_schema = {"BadMessage": {"enums": {"allthings": allthings}, "format": {"allthings": "enum"}}} self.assertRaises(ImproperlyConfigured, MessageFactory, bad_schema) def test_bad_msg_lookup(self): """ Test if making an invalid message class lookup is caught correctly """ try: self.factory.get("FooMessage") self.factory.get(1) except KeyError: self.fail() self.assertRaises(KeyError, self.factory.get, "FlyingCars") self.assertRaises(KeyError, self.factory.get, 999) def test_bad_enum_lookup(self): """ Test if making an invalid enum lookup is caught correctly """ FooMessage = self.factory.get("FooMessage") try: FooMessage.enum_lookup("direction", "south") except KeyError: self.fail() try: FooMessage.enum_reverse_lookup("direction", 2) except KeyError: self.fail() self.assertRaises(KeyError, FooMessage.enum_lookup, "direction", "shibboleth") self.assertRaises(KeyError, FooMessage.enum_lookup, "shibboleth", "south") self.assertRaises(KeyError, FooMessage.enum_reverse_lookup, "direction", 5) self.assertRaises(KeyError, FooMessage.enum_reverse_lookup, "shibboleth", 2)