def _assert_align(self, value, length, raw): field = Field('uint', 'name', to_bin(value), aligned_len=length) self.assertEqual(field.int, int(value, 16)) self.assertEqual(field.hex, value) self.assertEqual(field._raw, to_bin(raw)) self.assertEqual(field.bytes, to_bin(value)) if length: self.assertEqual(int(field.__len__()), length)
def test_validate_chars(self): field = Field('chars', 'field', 'foo\x00\x00') field_regEx = Field('chars', 'field', '{ Message In Braces }') self._should_pass(Char(5, 'field', 'foo').validate({'field': field}, {})) self._should_pass(Char(5, 'field', '(what|foo|bar)').validate({'field': field}, {})) self._should_pass(Char(5, 'field', 'REGEXP:^{[a-zA-Z ]+}$').validate({'field': field_regEx}, {})) self._should_pass(Char(5, 'field', 'REGEXP:^foo').validate({'field': field}, {})) self._should_pass(Char(5, 'field', 'REGEXP:').validate({'field': field}, {})) self._should_fail(Char(5, 'field', 'REGEXP:^abc').validate({'field': field}, {}), 1)
def test_validate_int(self): field = Field('int', 'field', to_bin('0xffb8')) self._should_pass(Int(2, 'field', -72).validate({'field': field}, {})) self._should_pass(Int(2, 'field', '-72').validate({'field': field}, {})) self._should_pass(Int(2, 'field', '-0x48').validate({'field': field}, {})) self._should_pass(Int(2, 'field', '-0x0048').validate({'field': field}, {})) self._should_pass(Int(2, 'field', '(0|-72)').validate({'field': field}, {}))
def test_validate_uint(self): field = Field('uint', 'field', to_bin('0x0004')) self._should_pass(UInt(2, 'field', 4).validate({'field': field}, {})) self._should_pass(UInt(2, 'field', '4').validate({'field': field}, {})) self._should_pass(UInt(2, 'field', '0x04').validate({'field': field}, {})) self._should_pass(UInt(2, 'field', '0x0004').validate({'field': field}, {})) self._should_pass(UInt(2, 'field', '(0|4)').validate({'field': field}, {}))
def _to_field(self, name, value, parent, little_endian=False): field_name, field_value = self._encode_value( value, parent, little_endian=little_endian) return Field(self.type, self._get_name(name), field_name, field_value, little_endian=little_endian)
def test_conversions(self): field = Field('unit', 'name', to_bin('0x00616200')) self.assertEquals(field.int, 0x00616200) self.assertEquals(field.hex, '0x00616200') self.assertEquals(field.ascii, 'ab') self.assertEquals(field.bytes, '\x00\x61\x62\x00') self.assertEquals(field.chars, 'ab') self.assertEquals(field.bin, '0b00000000' + '01100001' + '01100010' + '00000000')
def decode(self, data, parent=None, name=None, little_endian=False): self._verify_not_little_endian(little_endian) container = self._get_struct(name, parent) a = to_tbcd_value(data) index = 0 for field in self._fields.values(): field_length = field.length.decode(container, len(data) * 2 - index) container[field.name] = Field(field.type, field.name, to_tbcd_binary(a[index:index + field_length])) index += field_length return container
def decode(self, data, message, name=None, little_endian=False): data = self._prepare_data(data) length, aligned_length = self.length.decode_lengths(message, len(data)) if len(data) < aligned_length: raise Exception("Not enough data for '%s'. Needs %s bytes, given %s" % (self._get_recursive_name(message), aligned_length, len(data))) return Field(self.type, self._get_name(name), data[:length], aligned_len=aligned_length, little_endian=little_endian and self.can_be_little_endian)
def test_little_endian_with_align(self): field = Field('uint', 'name', to_bin('0x0100'), aligned_len=5, little_endian=True) self.assertEqual(field._raw, to_bin('0x0100000000')) self.assertEqual(field.int, 1) self.assertEqual(field.bytes, to_bin('0x0001')) self.assertEqual(field.hex, '0x0001')
def test_set_char_value_from_message_field(self): msg_field = Field('chars', 'char_field', '\x00a\x00b', aligned_len=5) field = Char(5, "char_field", '') self.assertEquals( field.encode({ 'char_field': msg_field }, {}, None)._raw, '\x00a\x00b\x00') self.assertEquals( field.encode({ 'char_field': msg_field }, {}, None).bytes, '\x00a\x00b\x00')
def uint_field(value='0x00'): return Field('uint', 'name', to_bin(value))
def test_little_endian(self): field = Field('uint', 'name', to_bin('0x0100'), little_endian=True) self.assertEquals(field._raw, to_bin('0x0100')) self.assertEquals(field.int, 1) self.assertEquals(field.bytes, to_bin('0x0001')) self.assertEquals(field.hex, '0x0001')
def test_decode_dynamic_with_subtractor(self): msg = Struct('foo', 'foo_type') msg['len'] = Field('uint', 'len', to_bin('0x04')) dyn_len = Length('len-2') self.assertEqual(dyn_len.decode(msg), 2)
def test_fail_validating_uint(self): template = UInt(2, 'field', 4) field = Field('uint', 'field', to_bin('0x0004')) self._should_fail(template.validate({'field': field}, {'field': '42'}), 1)
def test_validate_chars(self): field = Field('chars', 'field', 'foo\x00\x00') self._should_pass( Char(5, 'field', 'foo').validate({'field': field}, {})) self._should_pass( Char(5, 'field', '(what|foo|bar)').validate({'field': field}, {}))
def test_decode_dynamic(self): msg = Struct('foo', 'foo_type') msg['len'] = Field('uint', 'len', to_bin('0x04')) dyn_len = Length('len') self.assertEquals(dyn_len.decode(msg), 4)