def test_valid_make(self): """Test full packing.""" my_message = Message('my_msg', [ ('my_fixed', 'F', 'i', 8), ('not_specified_fixed', 'F', 'i', 8), ('other_fixed', 'F', 'i', 8, 3), ('just_a_num', 'i'), ('a_string', '32s'), ('this_fixed', 'F', 'i', 5), ], Mode.Big) data = { 'my_fixed': 1.1 + 2.2, 'other_fixed': Decimal('1.1') + Decimal('2.2'), 'not_specified_fixed': Decimal('1.1') + Decimal('2.2'), 'just_a_num': 16, 'a_string': '=====================', 'this_fixed': '1.9375', } packed = my_message.pack(data) unpacked = my_message.unpack(packed) assert unpacked.a_string == data['a_string'] assert unpacked.just_a_num == data['just_a_num'] assert unpacked.other_fixed == Decimal('3.3') assert unpacked.my_fixed == Decimal('3.296875') assert unpacked.not_specified_fixed == Decimal('3.296875') assert unpacked.this_fixed == Decimal(data['this_fixed'])
def test_pack_big_endian(self): """Test pack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Big) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member packed_msg = test_msg.pack(**self.testvalues[idx]) self.assertEqual(self.testbytes['big'][idx], packed_msg)
def test_single_element_2(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ('single_data', self.VarTest), ]) test_data = { 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'single_data': { 'x': 6, 'y': 11 }, } made = TestStruct.make(test_data) assert len(made.vardata) == 2 assert made.single_data.x == 6 assert made.single_data.y == 11
def test_byte_length_no_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 0, 'vardata': [], 'length_in_bytes': 0, 'bytesdata': [], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 0 assert made.vardata == [] assert made.length_in_bytes == 0 assert made.bytesdata == [] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 0) + \ struct.pack('H', 0)
def test_unpacking_of_too_many_bytes(self): packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) with pytest.raises(ValueError): unpacked = TestStruct.unpack(packed_element) assert unpacked
def test_unpack_in_the_middle(self): SomeMessage = Message('SomeMessage', [ ('regular', 'B'), ('irregular', 'B'), ('confused', 'B'), ]) TestStruct = Message('TestStruct', [ ('regular', 'B'), ('middle_constant', 'II', (0xAB, 0xBA)), ('a_variable_length', 'H', 'msg'), ('msg', SomeMessage, 'a_variable_length') ], Mode.Little) test_data = { 'regular': 8, 'a_variable_length': 2, 'msg': [ {'regular': 4, 'irregular': 0, 'confused': 6}, {'regular': 5, 'irregular': 2, 'confused': 4}, ], } made = TestStruct.make(**test_data) assert made.regular == 8 assert made.middle_constant == (0xAB, 0xBA) packed = TestStruct.pack(test_data) assert packed == b'\x08\xab\x00\x00\x00\xba\x00\x00\x00\x02\x00\x04\x00\x06\x05\x02\x04' unpacked = TestStruct.unpack(packed) assert unpacked.regular == 8 assert unpacked.middle_constant == (0xAB, 0xBA)
def test_no_error_message(self): def adder(*args): return sum(args) AdderMessage = Message('AdderMessage', [ ('item_a', 'H'), ('item_b', 'B'), ('item_c', 'B'), ('item_d', 'B'), ('item_e', 'B'), # Note, there is no item 'e' in the list of arguments ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d'], False), ]) # Test with incorrect result test_data_2 = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, 'function_data': -1, } made = AdderMessage.make(test_data_2) assert made.function_data == -1
def test_some_data(self): num_repeats = 3 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 2, 'vardata': [ {'x': 1, 'y': 2}, {'x': 3, 'y': 4}, ], 'repeated_data': [ {'x': 7, 'z': 13}, {'x': 2, 'z': 27}, {'x': 6, 'z': 11}, ], } made = TestStruct.make(test_data) assert made.length == 2 assert len(made.vardata) == 2 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 2) + \ struct.pack('BB', 1, 2) + \ struct.pack('BB', 3, 4) + \ (struct.pack('B', 7) + struct.pack('H', 13)) + \ (struct.pack('B', 2) + struct.pack('H', 27)) + \ (struct.pack('B', 6) + struct.pack('H', 11))
def test_not_all_fixed_data(self): num_repeats = 5 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 1, 'vardata': [ {'x': 255, 'y': 127}, ], 'repeated_data': [ {'x': 6, 'z': 12}, {'x': 1, 'z': 26}, {'x': 5, 'z': 10}, ], } made = TestStruct.make(test_data) assert made.length == 1 assert len(made.vardata) == 1 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ (struct.pack('B', 6) + struct.pack('H', 12)) + \ (struct.pack('B', 1) + struct.pack('H', 26)) + \ (struct.pack('B', 5) + struct.pack('H', 10)) + \ (struct.pack('B', 0) + struct.pack('H', 0)) * 2
def test_make_andk_pack(self): """Test field formats that are valid ElementString elements.""" TestStruct = Message( "TestStruct", [ ("a", "c"), # single character ("b", "2c"), # 2 char string ("c", "10s"), # 10 char string (variable) ("d", "9p"), # 9 ( - 1 ) char string (fixed) ("e", "5c"), ], ) test_data = {"a": "i", "b": "hi", "c": "short", "d": "long", "e": ["l", "i", "s", "t"]} made = TestStruct.make(test_data) assert made.a == ["i"] assert made.b == ["h", "i"] assert made.c == "short" assert made.d == "long\x00\x00\x00\x00" assert made.e == ["l", "i", "s", "t", "\x00"] packed = TestStruct.pack(test_data) unpacked = TestStruct.unpack(packed) assert made == unpacked
def test_length_after_item(self): num_repeats = 3 TestStruct = Message('TestStruct', [ ('vardata', self.VarTest, 'length'), ('length', 'H', 'vardata'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 2, 'vardata': [ {'x': 1, 'y': 2}, {'x': 3, 'y': 4}, ], 'repeated_data': [ {'x': 7, 'z': 13}, {'x': 2, 'z': 27}, {'x': 6, 'z': 11}, ], } made = TestStruct.make(test_data) assert made.length == 2 assert made.vardata[0].x == 1 assert made.vardata[0].y == 2 packed = TestStruct.pack(test_data) unpacked = TestStruct.unpack(packed) assert unpacked
def test_byte_length_more_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 1, 'vardata': [ {'x': 255, 'y': 127}, ], 'length_in_bytes': 10, 'bytesdata': [ {'x': 254, 'y': 126}, {'x': 25, 'y': 16}, {'x': 24, 'y': 26}, {'x': 54, 'y': 17}, {'x': 25, 'y': 12}, ], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 1 assert made.vardata == [ self.VarTest.make( {'x': 255, 'y': 127} )] assert made.length_in_bytes == 10 assert made.bytesdata == [ self.VarTest.make( {'x': 254, 'y': 126} ), self.VarTest.make( {'x': 25, 'y': 16}, ), self.VarTest.make( {'x': 24, 'y': 26}, ), self.VarTest.make( {'x': 54, 'y': 17}, ), self.VarTest.make( {'x': 25, 'y': 12}, ), ] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) + \ struct.pack('BB', 25, 12)
def test_bad_values(self): """Test field formats that are valid ElementString elements.""" TestStruct = Message("TestStruct", [("a", "c"), ("b", "2c")]) # single character # 2 char string test_data = {"a": [5], "b": "no"} with pytest.raises(TypeError): TestStruct.make(test_data)
def test_alignment(self): """Test field formats that are valid ElementString elements.""" TestStruct = Message("TestStruct", [("a", "c"), ("b", "2c")]) # single character # 2 char string test_data = {"a": "a", "b": "no"} TestStruct.update(alignment=4) packed = TestStruct.pack(test_data) assert packed == b"a\x00\x00\x00no\x00\x00"
def test_unpack_big_endian(self): """Test unpack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Big) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member (unpacked_partial_msg, unused) = test_msg.unpack_partial(self.testbytes['big'][idx] + b'\xde\xad') self.assertEqual(unused, b'\xde\xad') unpacked_msg = test_msg.unpack(self.testbytes['big'][idx]) expected_tuple = test_msg.make(**self.testvalues[idx]) # pylint: disable=protected-access self.assertEqual(unpacked_msg, unpacked_partial_msg) self.assertEqual(unpacked_msg, expected_tuple)
def test_self_pack(self): my_message = Message('MyMessage', self.teststruct) my_instance_1 = my_message.make(self.testvalues[0]) my_instance_2 = my_message.make(self.testvalues[1]) my_bytes_1 = my_message.pack(self.testvalues[0]) my_bytes_2 = my_message.pack(self.testvalues[1]) assert my_instance_1.pack() == my_bytes_1 assert my_instance_2.pack() == my_bytes_2
def test_unpack_little_endian(self): """Test unpack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Little) assert test_msg.mode.to_byteorder() == 'little' for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member (unpacked_partial_msg, unused) = test_msg.unpack_partial(self.testbytes['little'][idx] + b'\xde\xad') self.assertEqual(unused, b'\xde\xad') unpacked_msg = test_msg.unpack(self.testbytes['little'][idx]) expected_tuple = test_msg.make(**self.testvalues[idx]) # pylint: disable=protected-access self.assertEqual(unpacked_msg, unpacked_partial_msg) self.assertEqual(unpacked_msg, expected_tuple)
def test_some_data(self): num_repeats = 3 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'repeated_data': [ { 'x': 7, 'z': 13 }, { 'x': 2, 'z': 27 }, { 'x': 6, 'z': 11 }, ], } made = TestStruct.make(test_data) assert made.length == 2 assert len(made.vardata) == 2 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 2) + \ struct.pack('BB', 1, 2) + \ struct.pack('BB', 3, 4) + \ (struct.pack('B', 7) + struct.pack('H', 13)) + \ (struct.pack('B', 2) + struct.pack('H', 27)) + \ (struct.pack('B', 6) + struct.pack('H', 11))
def test_self_pack(self): my_message = Message('MyMessage', self.teststruct) my_instance_1 = my_message.make(self.testvalues[0]) my_instance_2 = my_message.make(self.testvalues[1]) my_bytes_1 = my_message.pack(self.testvalues[0]) my_bytes_2 = my_message.pack(self.testvalues[1]) assert my_instance_1.pack() == my_bytes_1 assert my_instance_2.pack() == my_bytes_2 assert my_message._name == 'MyMessage' assert my_instance_1._name == 'MyMessage'
def test_one_element(self): TestStruct = Message('TestStruct', [ ('regular', 'B'), # Two regular messages ('fill_in_later', 'H'), ('ending_sequence', 'II', (0xAA, 0xBB)), # An ending sequence to a message ]) test_data = { 'regular': 13, 'fill_in_later': 4, } made = TestStruct.make(**test_data) assert made.regular == 13 assert made.fill_in_later == 4 assert made.ending_sequence == (0xAA, 0xBB)
def test_not_all_fixed_data(self): num_repeats = 5 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'repeated_data': [ { 'x': 6, 'z': 12 }, { 'x': 1, 'z': 26 }, { 'x': 5, 'z': 10 }, ], } made = TestStruct.make(test_data) assert made.length == 1 assert len(made.vardata) == 1 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ (struct.pack('B', 6) + struct.pack('H', 12)) + \ (struct.pack('B', 1) + struct.pack('H', 26)) + \ (struct.pack('B', 5) + struct.pack('H', 10)) + \ (struct.pack('B', 0) + struct.pack('H', 0)) * 2
def test_init_invalid_mode(self): """Test invalid Message modes.""" for mode in ['=', 'stuff', 0, -1, 1]: with self.subTest(mode): # pylint: disable=no-member with self.assertRaises(TypeError) as cm: Message('test', self.teststruct, mode) self.assertEqual(str(cm.exception), 'invalid mode: {}'.format(mode))
def test_init_invalid_name(self): """Test invalid Message names.""" for name in [None, '', 1, dict(), list()]: with self.subTest(name): # pylint: disable=no-member with self.assertRaises(TypeError) as cm: Message(name, self.teststruct) self.assertEqual(str(cm.exception), 'invalid name: {}'.format(name))
def test_variable_length(self): dont_know_how_to_test = Message('DontKnow', [ ('numNames', 'B', 'names'), ('names', MyNamed, 'numNames'), ]) # Not sure how to test this one yet # could do some multiples thing or just let it be. print(len(dont_know_how_to_test))
def test_one_element(self): TestStruct = Message( 'TestStruct', [ ('regular', 'B'), # Two regular messages ('fill_in_later', 'H'), ('ending_sequence', 'II', (0xAA, 0xBB)), # An ending sequence to a message ]) test_data = { 'regular': 13, 'fill_in_later': 4, } made = TestStruct.make(**test_data) assert made.regular == 13 assert made.fill_in_later == 4 assert made.ending_sequence == (0xAA, 0xBB)
def test_unpack(self): TestStruct = Message('TestStruct', [ ('regular', 'B'), # Two regular messages ('fill_in_later', 'H'), ('ending_sequence', 'II', (0xAB, 0xBA)), # An ending sequence to a message ], Mode.Little) test_data = { 'regular': 8, 'fill_in_later': 7, } test_bytes = b'\x08\x07\x00\xab\x00\x00\x00\xba\x00\x00\x00' assert test_bytes == TestStruct.pack(**test_data) unpacked = TestStruct.unpack(test_bytes) assert unpacked.regular == 8 assert unpacked.fill_in_later == 7 assert unpacked.ending_sequence == (0xAB, 0xBA)
def test_adding_element(self): def adder(x, y): return x + y AdderMessage = Message('AdderMessage', [ ('item_a', 'H'), ('item_b', 'B'), ('function_data', 'I', adder, ['item_a', 'item_b']), ]) test_data = { 'item_a': 2, 'item_b': 5, } made = AdderMessage.make(test_data) assert made.item_a == 2 assert made.item_b == 5 assert made.function_data == 7
def test_single_element_2(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ('single_data', self.VarTest), ]) test_data = { 'length': 2, 'vardata': [ {'x': 1, 'y': 2}, {'x': 3, 'y': 4}, ], 'single_data': {'x': 6, 'y': 11}, } made = TestStruct.make(test_data) assert len(made.vardata) == 2 assert made.single_data.x == 6 assert made.single_data.y == 11
def test_bad_length_item(self): bad_message = Message('BadMessage', [ ('type', 'B', MyEnum), ('data', { MyEnum.THIS: MyNamed, MyEnum.THAT: NotSameMessage, MyEnum.OTHER: MyOtherNamed, }, 'type'), ]) with self.assertRaises(AttributeError): print(len(bad_message))
def test_unpacking_of_too_little_bytes(self): # Only pack four elements, instead of the five packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) with pytest.raises(struct.error): unpacked = TestStruct.unpack(packed_element) assert unpacked
def test_one_element(self): def crc32_wrapper(*args): return crc32(b''.join(args)) CompareMessage = Message('CompareMessage', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ]) CRCedMessage = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ('function_data', 'I', crc32_wrapper, [b'length_in_objects', b'vardata']), ]) test_data = { 'length_in_objects': 2, 'vardata': [ {'x': 1, 'y': 2}, {'x': 3, 'y': 4}, ], } made = CRCedMessage.make(test_data) # assert len(made) == 5 assert len(made.vardata) == 2 assert made.vardata[0].x == 1 assert made.vardata[0].y == 2 assert made.function_data == crc32(CompareMessage.pack(test_data))
def test_single_element_2(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ]) CRCedMessage = Message('CRCedMessage', [ ('data', TestStruct), ('function_data', 'I', crc32, [b'data']), ]) test_data = { 'data': { 'length_in_objects': 2, 'vardata': [ {'x': 1, 'y': 2}, {'x': 3, 'y': 4}, ], }, } made = CRCedMessage.make(test_data) # assert len(made) == 5 assert len(made.data.vardata) == 2 assert made.data.vardata[0].x == 1 assert made.data.vardata[0].y == 2 assert made.function_data == crc32(TestStruct.pack(test_data['data']))
def test_no_data(self): num_repeats = 4 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data_no_data = { 'length': 0, 'vardata': [], 'repeated_data': [ ], } made = TestStruct.make(test_data_no_data) assert made.length == 0 assert made.vardata == [] assert made.repeated_data == [] packed = TestStruct.pack(test_data_no_data) assert packed == struct.pack('H', 0) + (struct.pack('B', 0) + struct.pack('H', 0)) * num_repeats
def test_bad_names(self): with pytest.raises(ValueError) as e: test_msg = Message('test', [ ('pack', 'H'), ('_elements', 'H'), ('_fields', 'H'), ]) print(test_msg) assert 'pack' in str(e) assert '_elements' in str(e) assert '_fields' in str(e)
def test_no_data(self): num_repeats = 4 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data_no_data = { 'length': 0, 'vardata': [], 'repeated_data': [], } made = TestStruct.make(test_data_no_data) assert made.length == 0 assert made.vardata == [] assert made.repeated_data == [] packed = TestStruct.pack(test_data_no_data) assert packed == struct.pack( 'H', 0) + (struct.pack('B', 0) + struct.pack('H', 0)) * num_repeats
def test_unpack(self): TestStruct = Message( 'TestStruct', [ ('regular', 'B'), # Two regular messages ('fill_in_later', 'H'), ('ending_sequence', 'II', (0xAB, 0xBA)), # An ending sequence to a message ], Mode.Little) test_data = { 'regular': 8, 'fill_in_later': 7, } test_bytes = b'\x08\x07\x00\xab\x00\x00\x00\xba\x00\x00\x00' assert test_bytes == TestStruct.pack(**test_data) unpacked = TestStruct.unpack(test_bytes) assert unpacked.regular == 8 assert unpacked.fill_in_later == 7 assert unpacked.ending_sequence == (0xAB, 0xBA)
def test_unpacking_of_correct_size(self): packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) + \ struct.pack('BB', 25, 12) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) unpacked = TestStruct.unpack(packed_element) assert unpacked assert unpacked.length_in_objects == 1 assert unpacked.length_in_bytes == 10
def test_byte_length_some_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'length_in_bytes': 2, 'bytesdata': [ { 'x': 254, 'y': 126 }, ], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 1 assert made.vardata == [self.VarTest.make({'x': 255, 'y': 127})] assert made.length_in_bytes == 2 assert made.bytesdata == [self.VarTest.make({'x': 254, 'y': 126})] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 2) + \ struct.pack('BB', 254, 126)
def test_long_item(self): long_message = Message('ThisIsALongOne', [ ('ID', 'B'), ('delay', 'B'), ('a_byte', 'B'), ('type', 'B', MyEnum), ('data', { MyEnum.THIS: MyNamed, MyEnum.THAT: MyNamed, MyEnum.OTHER: MyOtherNamed, }, 'type'), ]) # Second size is from the MyNamed Enum above my_named_format = 'B32s' assert len(long_message) == struct.calcsize('BBBB' + my_named_format)
def test_unpack_in_the_middle(self): SomeMessage = Message('SomeMessage', [ ('regular', 'B'), ('irregular', 'B'), ('confused', 'B'), ]) TestStruct = Message('TestStruct', [('regular', 'B'), ('middle_constant', 'II', (0xAB, 0xBA)), ('a_variable_length', 'H', 'msg'), ('msg', SomeMessage, 'a_variable_length')], Mode.Little) test_data = { 'regular': 8, 'a_variable_length': 2, 'msg': [ { 'regular': 4, 'irregular': 0, 'confused': 6 }, { 'regular': 5, 'irregular': 2, 'confused': 4 }, ], } made = TestStruct.make(**test_data) assert made.regular == 8 assert made.middle_constant == (0xAB, 0xBA) packed = TestStruct.pack(test_data) assert packed == b'\x08\xab\x00\x00\x00\xba\x00\x00\x00\x02\x00\x04\x00\x06\x05\x02\x04' unpacked = TestStruct.unpack(packed) assert unpacked.regular == 8 assert unpacked.middle_constant == (0xAB, 0xBA)
class TestStarStruct(unittest.TestCase): """Test class for self packing of messages""" teststruct = [ ('a', 'b'), # signed byte: -128, 127 ('pad1', '3x'), # 3 pad bytes ('b', 'H'), # unsigned short: 0, 65535 ('pad2', 'x'), # 1 pad byte ] testvalues = [ { 'a': -128, 'b': 0, }, { 'a': 127, 'b': 65535, }, ] VarTest = Message('VarTest', [ ('x', 'B'), ('y', 'B'), ]) Repeated = Message('Repeated', [ ('x', 'B'), ('z', 'H'), ]) def test_self_pack(self): my_message = Message('MyMessage', self.teststruct) my_instance_1 = my_message.make(self.testvalues[0]) my_instance_2 = my_message.make(self.testvalues[1]) my_bytes_1 = my_message.pack(self.testvalues[0]) my_bytes_2 = my_message.pack(self.testvalues[1]) assert my_instance_1.pack() == my_bytes_1 assert my_instance_2.pack() == my_bytes_2 def test_no_data(self): num_repeats = 4 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data_no_data = { 'length': 0, 'vardata': [], 'repeated_data': [ ], } made = TestStruct.make(test_data_no_data) assert made.length == 0 assert made.vardata == [] assert made.repeated_data == [] packed = TestStruct.pack(test_data_no_data) assert packed == struct.pack('H', 0) + (struct.pack('B', 0) + struct.pack('H', 0)) * num_repeats assert packed == made.pack()
def test_adding_element_list(self): def adder(*args): return sum(args) AdderMessage = Message('AdderMessage', [ ('item_a', 'H'), ('item_b', 'B'), ('item_c', 'B'), ('item_d', 'B'), ('item_e', 'B'), # Note, there is no item 'e' in the list of arguments ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d']), ]) # Test getting the correct result test_data = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, } made = AdderMessage.make(test_data) assert made.item_a == 2 assert made.item_b == 5 assert made.function_data == 2 + 5 + 7 + 4 # Check packing and unpacking packed = AdderMessage.pack(test_data) assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00' assert packed == made.pack() unpacked = AdderMessage.unpack(packed) assert made == unpacked # Test with correct result test_data_2 = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, 'function_data': 2 + 5 + 7 + 4, } made = AdderMessage.make(test_data_2) assert made.item_a == 2 assert made.item_b == 5 assert made.function_data == 2 + 5 + 7 + 4 # Test with incorrect result test_data_2 = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, 'function_data': -1, } with pytest.raises(ValueError): made = AdderMessage.make(test_data_2)
def test_verifying_unpack(self): def adder(*args): return sum(args) AdderMessage = Message('AdderMessage', [ ('item_a', 'H'), ('item_b', 'B'), ('item_c', 'B'), ('item_d', 'B'), ('item_e', 'B'), # Note, there is no item 'e' in the list of arguments ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d']), ]) # Test getting the correct result test_data = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, } made = AdderMessage.make(test_data) assert made.item_a == 2 assert made.item_b == 5 assert made.function_data == 2 + 5 + 7 + 4 # Check packing and unpacking packed = AdderMessage.pack(test_data) assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00' assert packed == made.pack() unpacked = AdderMessage.unpack(packed) assert made == unpacked # Now we modify the data we are going to unpack, and we should get an error modified_packed = b'\x02\x00\x05\x07\x04\x06\x11\x11\x11\x11' with pytest.raises(ValueError): unpacked = AdderMessage.unpack(modified_packed) AdderMessageFalse = Message('AdderMessageFalse', [ ('item_a', 'H'), ('item_b', 'B'), ('item_c', 'B'), ('item_d', 'B'), ('item_e', 'B'), # Note, there is no item 'e' in the list of arguments ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d'], False), ]) # Test getting the correct result test_data = { 'item_a': 2, 'item_b': 5, 'item_c': 7, 'item_d': 4, 'item_e': 6, } made = AdderMessageFalse.make(test_data) assert made.item_a == 2 assert made.item_b == 5 assert made.function_data == 2 + 5 + 7 + 4 # Check packing and unpacking packed = AdderMessageFalse.pack(test_data) assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00' assert packed == made.pack() unpacked = AdderMessageFalse.unpack(packed) assert made == unpacked # Now we modify the data we are going to unpack, and we should get an error modified_packed = b'\x02\x00\x05\x07\x04\x06\x11\x11\x11\x11' # This time it won't fail because we set False for this message unpacked = AdderMessageFalse.unpack(modified_packed) assert unpacked.item_a == 2
class TestStarStruct(unittest.TestCase): """StarStruct module tests""" teststruct = [ ('a', 'b'), # signed byte: -128, 127 ('pad1', '3x'), # 3 pad bytes ('b', 'H'), # unsigned short: 0, 65535 ('pad2', 'x'), # 1 pad byte ('c', '10s'), # 10 byte string ('d', 'x'), # 1 pad byte ('e', '2H'), # 4 unsigned bytes: 0, 2^32-1 ('type', 'B', SimpleEnum), # unsigned byte, enum validated ('length', 'H', 'vardata'), # unsigned short length field ('vardata', # variable length data Message('VarTest', [('x', 'B'), ('y', 'B')]), 'length'), ('data', { # discriminated data SimpleEnum.one: Message('Struct1', [('y', 'B'), ('pad', '3x'), ('z', 'i')]), SimpleEnum.two: Message('Struct2', [('z', '20s')]), SimpleEnum.three: Message('Struct3', []), }, 'type'), ] testvalues = [ { 'a': -128, 'b': 0, 'c': '0123456789', 'e': 0, 'type': SimpleEnum.one, 'length': 0, 'vardata': [], 'data': { 'y': 50, 'z': 0x5577AACC, }, }, { 'a': 127, 'b': 65535, 'c': 'abcdefghij', 'e': 0xFFFFFFFF, 'type': SimpleEnum.two, 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'data': { 'z': '0123456789abcdefghij', }, }, { 'a': -1, 'b': 32767, 'c': '\n\tzyx', 'e': 0x7FFFFFFF, 'type': SimpleEnum.three, 'length': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'data': {}, }, { 'a': 100, 'b': 100, 'c': 'a0b1c2d3e4', 'e': 10000, 'type': SimpleEnum.one, 'length': 10, 'vardata': [ { 'x': 255, 'y': 127 }, { 'x': 254, 'y': 128 }, { 'x': 253, 'y': 129 }, { 'x': 252, 'y': 130 }, { 'x': 251, 'y': 131 }, { 'x': 250, 'y': 132 }, { 'x': 249, 'y': 133 }, { 'x': 248, 'y': 134 }, { 'x': 247, 'y': 135 }, { 'x': 246, 'y': 136 }, ], 'data': { 'y': 100, 'z': 2000, }, }, ] testbytes = { 'little': [ b'\x80\x00\x00\x00\x00\x00\x00\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x00\x00\x00\x00\x00\x01\x00\x00\x32\x00\x00\x00\xCC\xAA\x77\x55', b'\x7F\x00\x00\x00\xFF\xFF\x00\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x00\xFF\xFF\xFF\xFF\x02\x02\x00\x01\x02\x03\x04\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a', b'\xFF\x00\x00\x00\xFF\x7F\x00\x0A\x09\x7A\x79\x78\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\x7F\x03\x01\x00\xFF\x7F', b'\x64\x00\x00\x00\x64\x00\x00\x61\x30\x62\x31\x63\x32\x64\x33\x65\x34\x00\x10\x27\x00\x00\x01\x0A\x00\xFF\x7F\xFE\x80\xFD\x81\xFC\x82\xFB\x83\xFA\x84\xF9\x85\xF8\x86\xF7\x87\xF6\x88\x64\x00\x00\x00\xD0\x07\x00\x00', ], 'big': [ b'\x80\x00\x00\x00\x00\x00\x00\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x00\x00\x00\x00\x00\x01\x00\x00\x32\x00\x00\x00\x55\x77\xAA\xCC', b'\x7F\x00\x00\x00\xFF\xFF\x00\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x00\xFF\xFF\xFF\xFF\x02\x00\x02\x01\x02\x03\x04\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a', b'\xFF\x00\x00\x00\x7F\xFF\x00\x0A\x09\x7A\x79\x78\x00\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\x03\x00\x01\xFF\x7F', b'\x64\x00\x00\x00\x00\x64\x00\x61\x30\x62\x31\x63\x32\x64\x33\x65\x34\x00\x00\x00\x27\x10\x01\x00\x0A\xFF\x7F\xFE\x80\xFD\x81\xFC\x82\xFB\x83\xFA\x84\xF9\x85\xF8\x86\xF7\x87\xF6\x88\x64\x00\x00\x00\x00\x00\x07\xD0', ], } def test_init_invalid_name(self): """Test invalid Message names.""" for name in [None, '', 1, dict(), list()]: with self.subTest(name): # pylint: disable=no-member with self.assertRaises(TypeError) as cm: Message(name, self.teststruct) self.assertEqual(str(cm.exception), 'invalid name: {}'.format(name)) def test_init_invalid_mode(self): """Test invalid Message modes.""" for mode in ['=', 'stuff', 0, -1, 1]: with self.subTest(mode): # pylint: disable=no-member with self.assertRaises(TypeError) as cm: Message('test', self.teststruct, mode) self.assertEqual(str(cm.exception), 'invalid mode: {}'.format(mode)) def test_init_empty_struct(self): """Test an empty Message.""" val = Message('test', []) self.assertEqual(val._tuple._fields, ()) # pylint: disable=protected-access def test_pack_little_endian(self): """Test pack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Little) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member packed_msg = test_msg.pack(**self.testvalues[idx]) self.assertEqual(self.testbytes['little'][idx], packed_msg) def test_unpack_little_endian(self): """Test unpack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Little) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member (unpacked_partial_msg, unused ) = test_msg.unpack_partial(self.testbytes['little'][idx] + b'\xde\xad') self.assertEqual(unused, b'\xde\xad') unpacked_msg = test_msg.unpack(self.testbytes['little'][idx]) expected_tuple = test_msg.make(**self.testvalues[idx]) # pylint: disable=protected-access self.assertEqual(unpacked_msg, unpacked_partial_msg) self.assertEqual(unpacked_msg, expected_tuple) def test_pack_big_endian(self): """Test pack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Big) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member packed_msg = test_msg.pack(**self.testvalues[idx]) self.assertEqual(self.testbytes['big'][idx], packed_msg) def test_unpack_big_endian(self): """Test unpack the test formats.""" test_msg = Message('test', self.teststruct, Mode.Big) for idx in range(len(self.testvalues)): with self.subTest(idx): # pylint: disable=no-member (unpacked_partial_msg, unused) = test_msg.unpack_partial(self.testbytes['big'][idx] + b'\xde\xad') self.assertEqual(unused, b'\xde\xad') unpacked_msg = test_msg.unpack(self.testbytes['big'][idx]) expected_tuple = test_msg.make(**self.testvalues[idx]) # pylint: disable=protected-access self.assertEqual(unpacked_msg, unpacked_partial_msg) self.assertEqual(unpacked_msg, expected_tuple)
def test_init_empty_struct(self): """Test an empty Message.""" val = Message('test', []) self.assertEqual(val._tuple._fields, ()) # pylint: disable=protected-access
class TestStarStruct(unittest.TestCase): """StarStruct module tests""" VarTest = Message('VarTest', [ ('x', 'B'), ('y', 'B'), ]) Repeated = Message('Repeated', [ ('x', 'B'), ('z', 'H'), ]) def test_no_data(self): num_repeats = 4 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data_no_data = { 'length': 0, 'vardata': [], 'repeated_data': [], } made = TestStruct.make(test_data_no_data) assert made.length == 0 assert made.vardata == [] assert made.repeated_data == [] packed = TestStruct.pack(test_data_no_data) assert packed == struct.pack( 'H', 0) + (struct.pack('B', 0) + struct.pack('H', 0)) * num_repeats def test_some_data(self): num_repeats = 3 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'repeated_data': [ { 'x': 7, 'z': 13 }, { 'x': 2, 'z': 27 }, { 'x': 6, 'z': 11 }, ], } made = TestStruct.make(test_data) assert made.length == 2 assert len(made.vardata) == 2 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 2) + \ struct.pack('BB', 1, 2) + \ struct.pack('BB', 3, 4) + \ (struct.pack('B', 7) + struct.pack('H', 13)) + \ (struct.pack('B', 2) + struct.pack('H', 27)) + \ (struct.pack('B', 6) + struct.pack('H', 11)) def test_not_all_fixed_data(self): num_repeats = 5 TestStruct = Message('TestStruct', [ ('length', 'H', 'vardata'), ('vardata', self.VarTest, 'length'), ('repeated_data', self.Repeated, num_repeats), ]) test_data = { 'length': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'repeated_data': [ { 'x': 6, 'z': 12 }, { 'x': 1, 'z': 26 }, { 'x': 5, 'z': 10 }, ], } made = TestStruct.make(test_data) assert made.length == 1 assert len(made.vardata) == 1 assert len(made.repeated_data) == 3 packed = TestStruct.pack(test_data) assert packed == struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ (struct.pack('B', 6) + struct.pack('H', 12)) + \ (struct.pack('B', 1) + struct.pack('H', 26)) + \ (struct.pack('B', 5) + struct.pack('H', 10)) + \ (struct.pack('B', 0) + struct.pack('H', 0)) * 2 def test_byte_length_no_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 0, 'vardata': [], 'length_in_bytes': 0, 'bytesdata': [], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 0 assert made.vardata == [] assert made.length_in_bytes == 0 assert made.bytesdata == [] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 0) + \ struct.pack('H', 0) def test_byte_length_some_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'length_in_bytes': 2, 'bytesdata': [ { 'x': 254, 'y': 126 }, ], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 1 assert made.vardata == [self.VarTest.make({'x': 255, 'y': 127})] assert made.length_in_bytes == 2 assert made.bytesdata == [self.VarTest.make({'x': 254, 'y': 126})] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 2) + \ struct.pack('BB', 254, 126) def test_byte_length_more_data(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) test_data_no_data = { 'length_in_objects': 1, 'vardata': [ { 'x': 255, 'y': 127 }, ], 'length_in_bytes': 10, 'bytesdata': [ { 'x': 254, 'y': 126 }, { 'x': 25, 'y': 16 }, { 'x': 24, 'y': 26 }, { 'x': 54, 'y': 17 }, { 'x': 25, 'y': 12 }, ], } made = TestStruct.make(test_data_no_data) assert made.length_in_objects == 1 assert made.vardata == [self.VarTest.make({'x': 255, 'y': 127})] assert made.length_in_bytes == 10 assert made.bytesdata == [ self.VarTest.make({ 'x': 254, 'y': 126 }), self.VarTest.make({ 'x': 25, 'y': 16 }, ), self.VarTest.make({ 'x': 24, 'y': 26 }, ), self.VarTest.make({ 'x': 54, 'y': 17 }, ), self.VarTest.make({ 'x': 25, 'y': 12 }, ), ] packed = TestStruct.pack(test_data_no_data) assert packed == \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) + \ struct.pack('BB', 25, 12) def test_unpacking_of_correct_size(self): packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) + \ struct.pack('BB', 25, 12) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) unpacked = TestStruct.unpack(packed_element) assert unpacked assert unpacked.length_in_objects == 1 assert unpacked.length_in_bytes == 10 def test_unpacking_of_too_little_bytes(self): # Only pack four elements, instead of the five packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) with pytest.raises(struct.error): unpacked = TestStruct.unpack(packed_element) assert unpacked def test_unpacking_of_too_many_bytes(self): packed_element = \ struct.pack('H', 1) + \ struct.pack('BB', 255, 127) + \ struct.pack('H', 10) + \ struct.pack('BB', 254, 126) + \ struct.pack('BB', 25, 16) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 24, 26) + \ struct.pack('BB', 54, 17) TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), (b'length_in_bytes', 'H', 'bytesdata'), ('bytesdata', self.VarTest, b'length_in_bytes'), ]) with pytest.raises(ValueError): unpacked = TestStruct.unpack(packed_element) assert unpacked def test_single_element(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ('single_data', self.VarTest), ]) test_data = { 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'single_data': [ { 'x': 6, 'y': 11 }, ], } made = TestStruct.make(test_data) assert len(made.vardata) == 2 assert made.single_data.x == 6 assert made.single_data.y == 11 def test_single_element_2(self): TestStruct = Message('TestStruct', [ ('length_in_objects', 'H', 'vardata'), ('vardata', self.VarTest, 'length_in_objects'), ('single_data', self.VarTest), ]) test_data = { 'length': 2, 'vardata': [ { 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, ], 'single_data': { 'x': 6, 'y': 11 }, } made = TestStruct.make(test_data) assert len(made.vardata) == 2 assert made.single_data.x == 6 assert made.single_data.y == 11