Beispiel #1
0
 def test_encode_zero_length_hex_field(self):
     a = Sequence('a', [
             Field('b:', length=8),
             Field('c', format=Field.HEX, length=parse('${b:} * 8'))
             ])
     self.assertEqual('\x02ab', encode(a, {'c':'6162'}).bytes())
     self.assertEqual('\x00', encode(a, {'c':''}).bytes())
Beispiel #2
0
 def test_integer_with_variable_length(self):
     a = Sequence('a', [
         Field('length:', length=8 ),
         Field('b:', format=Field.INTEGER, length=parse('${length:} * 8'))],
         value=parse('${b:}'))
     self.assertEqual('\x01\x00', encode(a, 0).bytes())
     self.assertEqual('\x01\xff', encode(a, 255).bytes())
     self.assertEqual('\x02\xff\xff', encode(a, 65535).bytes())
Beispiel #3
0
 def test_integer_with_fixed_length_reference(self):
     # This sort of a construct is used in the presense specifications
     a = Sequence('a', [
         Sequence('length:', [], value=parse('16')),
         Field('b:', format=Field.INTEGER, length=parse('${length:}'))],
         value=parse('${b:}'))
     self.assertEqual('\x00\x00', encode(a, 0).bytes())
     self.assertEqual('\x00\xff', encode(a, 255).bytes())
     self.assertEqual('\xff\xff', encode(a, 65535).bytes())
Beispiel #4
0
 def test_visible_param_passed_in(self):
     # Test that we correctly pass visible parameters into hidden entries.
     # This is commonly used in conditional entries.
     a = Sequence('a', [
         Field('b', length=8, format=Field.INTEGER),
         Sequence('c:', [Field('d:', length=parse('${b} * 8'))])])
     self.assertEqual('\x00', encode(a, {'b':0}).bytes())
     self.assertEqual('\x01\x00', encode(a, {'b':1}).bytes())
     self.assertEqual('\x03\x00\x00\x00', encode(a, {'b':3}).bytes())
Beispiel #5
0
 def test_cyclic_dependency_error(self):
     # This tests that we get a good error when we are unable to encode due
     # to cyclic dependencies. In this case, we cannot encode 'payload' without
     # knowing the length of 'header:', but we cannot encode 'header:'
     # without knowing the length to put in 'header:.length'.
     a = Sequence('a', [
         Sequence('header:', [Field('length', length=8)]),
         Field('payload', length=parse('${header:.length} * 8 - len{header:}'), format=Field.TEXT)])
     try:
         encode(a, {'payload':'boom'})
     except CyclicEncodingError, ex:
         self.assertTrue("'header:' -> 'payload' -> 'header:'" in str(ex), str(ex))
Beispiel #6
0
 def test_value_of_variable_length_binary_field(self):
     number = Sequence('b:', [
             Field('len:', length=8),
             #Field('value:', length=parse('${len:} * 8'), format=Field.INTEGER) ],
             Field('value:', length=parse('${len:} * 8'))],
             value=parse('${value:}'))
     a = Sequence('a', [
         number,
         Sequence('c', [], value=parse('${b:}'))
         ])
     self.assertEqual('\x01\x00', encode(a, {'c':0}).bytes())
     self.assertEqual('\x02\x10\xff', encode(a, {'c':0x10ff}).bytes())
Beispiel #7
0
    def _encode(self, protocol, value):
        """
        Wrapper around inst.encode.

        Also validates that we can decode the encoded data, and get the
        same data back again.
        """
        data = inst.encode(protocol, value)

        # Now validate that we can decode that data...
        re_decoded = inst.decode(protocol, data.copy())
        self.assertEqual(data, inst.encode(protocol, re_decoded))
        return data.bytes()
Beispiel #8
0
    def test_multi_digit_encode(self):
        # Test encoding a multiple text digit entry
        digit = Sequence('digit',
                [Field('char:', length=8, constraints=[Minimum(48), Maximum(57)])],
                value=parse('${char:} - 48'))
        two_digits = Sequence('two digits', [
            Child('digit 1:', digit), Child('digit 2:', digit)],
            value=parse('${digit 1:} * 10 + ${digit 2:}'))
        four_digits = Sequence('four digits', [
            Child('digits 1:', two_digits), Child('digits 2:', two_digits)],
            value=parse('${digits 1:} * 100 + ${digits 2:}'))

        self.assertEqual('12', encode(two_digits, 12).bytes())
        self.assertEqual('1234', encode(four_digits, 1234).bytes())
        self.assertEqual('7632', encode(four_digits, 7632).bytes())
Beispiel #9
0
 def test_unicode_field(self):
     a = Sequence('a', [
             Field('b:', length=8),
             Field('c', format=Field.TEXT, length=parse('${b:} * 8'), encoding='utf8')
             ])
     self.assertEqual('\x0c\xe3\x83\xad\xe3\x82\xb0\xe3\x82\xa4\xe3\x83\xb3',
             encode(a, {'c':u'ログイン'}).bytes())
Beispiel #10
0
    def test_encode_reference(self):
        # Test that we correctly encode a reference
        a = Sequence('a', [
            Field("b:", 8, format=Field.INTEGER),
            Sequence('c', [], value=parse('${b:}'))])

        self.assertEqual("\x01", encode(a, {"c" : 0x01}).bytes())
Beispiel #11
0
 def test_encode_hidden_count(self):
     # Test that we correctly encode a hidden count
     a = Sequence('a', [
         Field('count:', length=8),
         SequenceOf('c', Field('d', length=8, format=Field.TEXT), count=parse("${count:}")),
         ])
     self.assertEqual('\x03abc', encode(a, {'c' : ['a', 'b', 'c']}).bytes())
Beispiel #12
0
    def decode(self, input_file):
        # Encode aivdm data back into binary
        fragments = []
        payload = self._aivdm[1][0]
        data = Data(input_file)
        while data:
            try:
                calculated_crc = self._get_crc(data)
                packet = decode(self._aivdm[0], data)
                if packet.checksum != calculated_crc:
                    sys.stderr.write('Crc mismatch; expected %02X, but '
                            'calculated %02X. Skipping packet.\n' %
                            (packet.checksum, calculated_crc))
                    continue

                bits = encode(payload, list(ord(c.character) for c in packet.payload))
                bits = bits.pop(len(bits) - packet.num_fill_bits)
                if len(fragments) == packet.fragment_number - 1:
                    fragments.append(bits)
                    if len(fragments) == packet.fragment_count:
                        self._decode_ais(reduce(operator.add, fragments))
                        fragments = []
                else:
                    sys.stderr.write('Expected fragment number %i, got %i (of %i)\n' % (
                        len(fragments) + 1, packet.fragment_number, packet.fragment_count))
                    fragments = []
            except DecodeError, ex:
                filename, line_number, column_number = self._aivdm[2][ex.entry]
                sys.stderr.write('%s[%i] - %s\n' %  (filename, line_number, ex))
                fragments = []

                # Read to the next newline
                while data and data.pop(8).text('ascii') != '\n':
                    pass
Beispiel #13
0
 def test_hidden_sequence_with_input_param(self):
     # Here we have a hidden entry that will have to be mocked, but still
     # requires that data is passed in.
     c = Sequence('a', [
         Child('b:', Sequence('b', [Field('c', length=8)])),
         Sequence('d', [], value=parse('${b:.c}'))])
     self.assertEqual('\x09', encode(c, {'d':9}).bytes())
Beispiel #14
0
 def test_length_reference(self):
     # Test that we can correctly encode entries that use length references
     a = Sequence('a', [
         Field('packet length:', length=8),
         Field('data length:', length=8),
         Field('data', length=parse('${data length:} * 8'), format=Field.TEXT),
         Field('unused', length=parse('${packet length:} * 8 - len{data}'), format=Field.TEXT)])
     self.assertEqual('\x05\x03aaabb', encode(a, {'data':'aaa', 'unused':'bb'}).bytes())
Beispiel #15
0
 def test_reference_in_constraint(self):
     # Test that the code correctly encodes when constraints have references
     a = Sequence('a', [
         Sequence('b:', [
             Sequence('b1', [], value=parse('1')),
             Sequence('b2', [], value=parse('2')),
             Sequence('b3', [], value=parse('3')),
             ]),
         Choice('c', [
             Field('c1', length=8, constraints=[Equals(parse('${b:.b1}'))]),
             Field('c2', length=8, constraints=[Equals(parse('${b:.b2}'))]),
             Sequence('c3', [Field('uint8:', length=8)],
                 value=parse('${uint8:}'), constraints=[Equals(parse('${b:.b3}'))]),
             ])
         ])
     self.assertEqual('\x01', encode(a, {'c1':None}).bytes())
     self.assertEqual('\x02', encode(a, {'c2':None}).bytes())
     self.assertEqual('\x03', encode(a, {'c3':None}).bytes())
Beispiel #16
0
 def test_complex_length_reference(self):
     # Here we try to encode a complex length reference that includes a
     # length reference
     a = Sequence('a', [
         Field('packet length:', length=8, format=Field.INTEGER),
         Field('header length:', length=8, format=Field.INTEGER),
         Field('header', length=parse('${header length:} * 8'), format=Field.TEXT),
         Field('packet', length=parse('${packet length:} * 8 - len{header}'), format=Field.TEXT)])
     self.assertEqual('\x06\x02hhpppp', encode(a, {'header':'hh', 'packet':'pppp'}).bytes())
Beispiel #17
0
 def test_common_entry_with_referenced_value(self):
     # Just because an entry is sometimes referenced doesn't mean it always
     # has to be... here we create an element 'a' whose value is only
     # sometimes referenced elsewhere.
     a = Field('a', length=8)
     c = Sequence('c', [
         a,
         Sequence('b', [Child('a:', a)], value=parse('${a:}'))])
     self.assertEqual('\x45\x23', encode(c, {'a':0x45, 'b':0x23}).bytes())
Beispiel #18
0
 def test_encode_length_reference(self):
     a = Sequence('a', [
         Field('length:', 8),
         Sequence('payload', [
             Field('data', length=32, format=Field.TEXT)
             ], length=parse("${length:} * 8"))])
     data = {
             'payload':{'data':'abcd'}
             }
     self.assertEqual('\x04abcd', encode(a, data).bytes())
Beispiel #19
0
 def test_referencing_implicit_length(self):
     # There was a problem when encoding length references to entries that
     # didn't have an explicit length. Test this.
     a = Sequence('a', [
         Field('length:', length=8),
         Sequence('b', [
             Field('b1 length:', length=8),
             Field('b1', length=parse('${b1 length:} * 8'), format=Field.TEXT)]),
         Field('unused:', length=parse('${length:} * 8 - len{b}'))
         ])
     self.assertEqual('\x05\x04abcd', encode(a, {'b':{'b1':'abcd'}}).bytes())
Beispiel #20
0
    def test_fixed_sequence_value(self):
        # We create an entry with a fixed / visible value, and reference it
        # within a choice when deciding how to encode. This is similar to how
        # the optional big/little endian fields work.
        optional_endian = Sequence('optional_endian', [
            Choice('number:', [
                Sequence('big endian:', [
                    Sequence('big check:', [], value=parse('${is big endian:}'), constraints=[Equals(1)]),
                    Field('internal:', length=16)],
                    value=parse('${internal:}')),
                Sequence('little endian:', [
                    Sequence('little check:', [], value=parse('${is big endian:}'), constraints=[Equals(0)]),
                    Sequence('internal:', [
                        Field('byte 1:', length=8),
                        Field('byte 2:', length=8)],
                        value=parse('(${byte 2:} << 8) + ${byte 1:}'))],
                    value=parse('${internal:}'))])],
            value=parse('${number:}'))

        # Check that we correctly encode when the 'is big endian' is a fixed value
        a = Sequence('a', [
            Sequence('is big endian:', [], value=parse('1')),
            Child('value', optional_endian)])
        self.assertEqual('\x00\x01', encode(a, {'value':1}).bytes())

        b = Sequence('b', [
            Sequence('is big endian:', [], value=parse('0')),
            Child('value', optional_endian)])
        self.assertEqual('\x01\x00', encode(b, {'value':1}).bytes())

        # FIXME: This fails, because the 'number:' decide that as 'is big endian:'
        # is hidden (and doesn't have an expected value) that it must be derived,
        # so changes the 'is big endian:' from an output to an input. See issue247.

        # Check that we correctly encode when the 'is big endian' is a field
        c = Sequence('c', [
            Field('is big endian', length=8, format=Field.INTEGER),
            Sequence('is big endian:', [], value=parse('${is big endian}')),
            Child('value', optional_endian)])
Beispiel #21
0
 def test_secondary_dependency(self):
     # Test that when A depends on C, and B depends on A, we don't attempt
     # to encode B before A.
     blah = Sequence('blah', [
         Sequence('a', [
             Field('a1', 8, format=Field.INTEGER),
             Field('a2:', 8, format=Field.INTEGER)]),
         Field('b', parse('${a.a1} * 8'), format=Field.TEXT),
         Field('c', parse('${a.a2:} * 8'), format=Field.TEXT)])
     self.assertEqual('\x03\x02xyzst', encode(blah, {
         'a' : {'a1' : 3},
         'b' : 'xyz',
         'c' : 'st'}).bytes())
Beispiel #22
0
 def test_hidden_detection(self):
     # Test the parameter passing when the common entry is first found
     # in a hidden context. There was a bug if a common entry was initially
     # found 'hidden', it would always be treated as hidden. This tests it
     # by creating a common entry that is referenced in two places, once
     # hidden, once not. For the test to pass the code must be dealing
     # correctly with the parameters.
     a = Field('a', length=8, format=Field.INTEGER)
     b = Sequence('b', [
         Sequence('c:', [a]),
         Field('d', length=parse('${c:.a} * 8'), format=Field.TEXT),
         a,
         Field('e', length=parse('${a} * 8'), format=Field.TEXT)])
     self.assertEqual('\x02dd\x03eee', encode(b, {'d':'dd', 'a':3, 'e':'eee'}).bytes())
Beispiel #23
0
 def test_default_value_of_variable_length_field(self):
     # When encoding 'd' we should choose a suitable value for the unknown
     # output reference 'number'. As we know it's not zero (as that was
     # used by the 'c' option), we expect the next digit (one).
     number = Sequence(
         "number",
         [
             Field("integer length:", length=8),
             Field("value:", format=Field.INTEGER, length=ValueResult("integer length:") * Constant(8)),
         ],
         value=ValueResult("value:"),
     )
     a = Sequence(
         "a",
         [
             Child("number:", number),
             Choice(
                 "data",
                 [Sequence("c", [], value=ValueResult("number:"), constraints=[Equals(0)]), Sequence("d", [])],
             ),
         ],
     )
     self.assertEqual(Data("\x01\x00"), encode(a, {"c": 0}))
     self.assertEqual(Data("\x01\x01"), encode(a, {"d": None}))
Beispiel #24
0
    def test_visible_common_entry_is_hidden(self):
        # When we have a visible common integer that is referenced elsewhere,
        # check to see what happens when we rename and hide it in another
        # entry. This happens when we do something like
        #
        #   <reference name="bob" type="int8" expected="5" />
        #
        # which loads to
        #
        #   <sequence name="bob" value="${bob:}" expected="5" >
        #      <reference name="bob:" type="int8" />
        #   </sequence>
        #
        # We test that references to the renamed entry work correctly, and also
        # that references to the originally named entry work too.

        a = Field('a', length=8, format=Field.INTEGER)
        b = Sequence('b', [
            Sequence('c', [Child('a:', a)], value=parse('${a:}')),
            Sequence('d', [a, Sequence('d1', [], value=parse('${a}'))])])
        self.assertEqual('\x05\x07', encode(b, {'c' : 5, 'd':{'a':7, 'd1':7}}).bytes())
Beispiel #25
0
 def test_encode(self):
     sequenceof = sof.SequenceOf("blah", fld.Field("cat", 8, format=fld.Field.INTEGER), 3)
     data = [5, 9, 0xF6]
     data = encode(sequenceof, data)
     self.assertEqual("\x05\x09\xf6", data.bytes())
Beispiel #26
0
 def test_sometimes_referenced_hidden_field(self):
     # Test encoding a field that is sometimes referenced (but not always).
     a = Field('a:', length=8, format=Field.INTEGER)
     b = Sequence('b', [a], value=parse('${a:}'))
     c = Sequence('c', [a, b])
     self.assertEqual('\x00\x07', encode(c, {'b':7}).bytes())
Beispiel #27
0
 def test_param_from_hidden_entry_with_visible_child(self):
     a = Sequence('a', [
         Sequence('b:', [Field('c', length=8)])],
         value=parse('${b:.c}'))
     self.assertEqual('\x0a', encode(a, 10).bytes())
Beispiel #28
0
 def test_encode_hidden_sequence(self):
     # When encoding an item that is hidden, we should use null characters.
     a = Sequence('a', [Sequence('b:', [Field('c', length=8)])])
     self.assertEqual('\x00', encode(a, None).bytes())
Beispiel #29
0
 def test_hidden_sequence_with_value(self):
     # Test encoding a hidden sequence with an unknown value
     a = Sequence('a', [Sequence('b', [], value=parse('${constant}'))])
     c = Sequence('c', [Field('constant', length=8), Child('a:', a)])
     self.assertEqual('\x07', encode(c, {'constant':7}).bytes())
Beispiel #30
0
 def test_full_names(self):
     a = Sequence('a', [
         Sequence('b', [Field('length:', length=8)]),
         Sequence('c', [Field('data', length=parse('${b.length:} * 8'), format=Field.TEXT)])])
     self.assertEqual('\x03abc', encode(a, {'b':{}, 'c':{'data':'abc'}}).bytes())