Ejemplo n.º 1
0
    def test_length_and_value_reference(self):
        # Test a length reference and a value reference to the same entry.
        a = Field('a', length=8)
        c = Field('c', length=parse('len{a}'))
        d = Field('d', length=parse('${a}'))
        b = Sequence('b', [a, c, d])

        # Lets just try a quick decode to make sure we've specified it ok...
        #list(b.decode(Data('\x08cd')))

        # Now test the parameters being passed around.
        lookup = ExpressionParameters([b])
        self.assertEqual([Param('a', Param.OUT, _Integer()),
            Param('a length', Param.OUT, _Integer())],
                lookup.get_params(a))
        self.assertEqual([Param('a', Param.OUT, _Integer()),
            Param('a length', Param.OUT, _Integer())],
                list(lookup.get_passed_variables(b, b.children[0])))
        self.assertEqual([Param('a length', Param.IN, _Integer())],
                list(lookup.get_passed_variables(b, b.children[1])))
        self.assertEqual([Param('a length', Param.IN, _Integer())],
                lookup.get_params(c))
        self.assertEqual([Local('a', _Integer()), Local('a length', _Integer())],
                lookup.get_locals(b))
        self.assertTrue(lookup.is_length_referenced(a))
Ejemplo n.º 2
0
    def test_in_and_out_parameters(self):
        # Test what happens when we have a parameter that is to be passed out
        # of an entry, but also into a child (issue122).
        #
        #        ___ e ___
        #   __c__         d(len=a)
        #  a   b(len=a)
        a = Field('a', length=8)
        b = Field('b', length=parse('${a}'))
        c = Sequence('c', [a, b])
        d = Field('d', length=parse('${c.a}'))
        e = Sequence('e', [c, d])

        lookup = ExpressionParameters([e])
        self.assertEqual([], lookup.get_params(e))
        self.assertEqual([Param('a', Param.OUT, _Integer())], lookup.get_params(a))
        self.assertEqual([Param('a', Param.OUT, _Integer())], lookup.get_params(c))
        self.assertEqual([Param('a', Param.IN, _Integer())], lookup.get_params(b))
        self.assertEqual([Param('c.a', Param.IN, _Integer())], lookup.get_params(d))
        self.assertEqual([Local('c.a', _Integer())], lookup.get_locals(e))
        self.assertEqual([], lookup.get_locals(c))

        self.assertTrue(lookup.is_value_referenced(a))

        self.assertEqual([Param('a', Param.IN, _Integer())],
                list(lookup.get_passed_variables(c, c.children[1])))
        self.assertEqual([Param('c.a', Param.IN, _Integer())],
                list(lookup.get_passed_variables(e, e.children[1])))
Ejemplo n.º 3
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())
Ejemplo n.º 4
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())
Ejemplo n.º 5
0
 def test_two_digits(self):
     # Tests a common case of representing text digits
     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:}'))
     self.assertEqual({'${digit 1:}':6, '${digit 2:}' : 7},
             _solve(two_digits, None, 67))
Ejemplo n.º 6
0
 def test_subtract(self):
     a = Sequence('a', [
         Field('total length:', length=8),
         Field('partial length:', length=8),
         Field('data:', length=parse('${partial length:} * 8')),
         Sequence('unused', [], value=parse('${total length:} * 8 - len{data:}')),
         ])
     self.assertEqual({'len{data:}': 800}, _solve(a, 3, 0, {'total length:':100}))
Ejemplo n.º 7
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())
Ejemplo n.º 8
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())
Ejemplo n.º 9
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())
Ejemplo n.º 10
0
 def test_sequence_with_referenced_value(self):
     a = Field('a', length=8)
     b = Sequence('b', [Child('b:', a)], value=parse('${b:}'))
     c = Field('c', length=parse('${b} * 8'))
     d = Sequence('d', [a, b, c])
     lookup = ExpressionParameters([a, d])
     self.assertEqual([Local('b:', _Integer())], lookup.get_locals(b))
     self.assertEqual([Param('a', Param.OUT, _Integer())], lookup.get_params(a))
     self.assertEqual([Param('b', Param.OUT, _Integer())], lookup.get_params(b))
     self.assertEqual([Param('b', Param.IN, _Integer())], lookup.get_params(c))
     self.assertEqual([], lookup.get_params(d))
Ejemplo n.º 11
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())
Ejemplo n.º 12
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())
Ejemplo n.º 13
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())
Ejemplo n.º 14
0
    def test_renamed_common_reference(self):
        text_digit = Field('text digit', 8, constraints=[Minimum(48), Maximum(58)])

        digit = Sequence('digit', [text_digit],
            value=parse("${text digit} - 48"))
        b = Sequence('b', [
            Child('length', digit),
            Field('data', length=parse("${length} * 8"))])
        lookup = ExpressionParameters([b])
        self.assertEqual([], lookup.get_params(b))
        self.assertEqual([Param('digit', Param.OUT, _Integer())],
                lookup.get_params(digit))
        self.assertEqual([Param('length', Param.OUT, _Integer())],
                list(lookup.get_passed_variables(b, b.children[0])))
Ejemplo n.º 15
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())
Ejemplo n.º 16
0
 def test_single_value_multiply(self):
     # Test when the expression is the value of an entry multipled by something
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('${b} * 2')),
         ])
     self.assertEqual({'${b}':4}, _solve(a, 1, 8))
Ejemplo n.º 17
0
 def test_single_value(self):
     # Test when the expression is the value of an entry
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('${b}')),
         ])
     self.assertEqual({'${b}':5}, _solve(a, 1, 5))
Ejemplo n.º 18
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())
Ejemplo n.º 19
0
 def test_length_reference(self):
     a = Sequence('a', [
         Field('data length:', length=8),
         Field('b', length=16),
         Sequence('footer length', [], value=parse('${data length:} * 8 - len{b}'))])
     # We now try to solve 'data length:' given that we know the value for 'b length'
     self.assertEqual({'${data length:}' : 5}, _solve(a, 2, 24, {'b length':16}))
Ejemplo n.º 20
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())
Ejemplo n.º 21
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())
Ejemplo n.º 22
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())
Ejemplo n.º 23
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())
Ejemplo n.º 24
0
 def test_referenced_field_length(self):
     a = Field('a', length=4)
     b = Sequence('b', [], value=parse('len{a} * 8 + 4'))
     c = Sequence('c', [a, b])
     params = ExpressionParameters([c])
     range = EntryValueType(b).range(params)
     self.assertEqual(36, range.min)
     self.assertEqual(36, range.max)
Ejemplo n.º 25
0
    def test_recursive_type(self):
        variable_length_integer = Choice('variable length integer', [])
        variable_length_integer.children = [
            Sequence('final byte:', [
                Field(None, length=1, constraints=[Equals(0)]),
                Field('value:', length=7)],
                value=parse('${value:}')),
            Sequence('intermediate byte:', [
                Field(None, length=1, constraints=[Equals(1)]),
                Field('value:', length=7),
                Child('next:', variable_length_integer)],
                value=parse('(${value:} << 7) + ${next:}'))]

        params = ExpressionParameters([variable_length_integer])
        range = EntryValueType(variable_length_integer).range(params)
        self.assertEqual(None, range.min)
        self.assertEqual(None, range.max)
Ejemplo n.º 26
0
 def test_little_endian(self):
     # Test that we can break apart a little endian style number
     a = Sequence('a', [
         Field('b1', length=8),
         Field('b2', length=8),
         Sequence('c', [], value=parse('(${b2} << 8) + ${b1} ')),
         ])
     self.assertEqual({'${b1}':0x34, '${b2}':0x12}, _solve(a, 2, 0x1234))
Ejemplo n.º 27
0
 def test_single_value_bimdas(self):
     # Test that we correctly resolve the value when there are addition
     # and multiplication involved.
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('(${b} + 3) * 8')),
         ])
     self.assertEqual({'${b}':5}, _solve(a, 1, 64))
Ejemplo n.º 28
0
 def test_single_value_addition(self):
     # Test that we correctly resolve the correct value when there is an
     # addition involved
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('${b} + 3')),
         ])
     self.assertEqual({'${b}':7}, _solve(a, 1, 10))
Ejemplo n.º 29
0
 def test_divide(self):
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('${b} / 2')),
         ])
     # TODO: What should we do in this case? This is a lossy conversion... See issue246.
     #self.assertEqual({'${b}':20}, _solve(a, 1, 10))
     self.assertRaises(SolverError, _solve, a, 1, 10)
Ejemplo n.º 30
0
 def test_same_reference_multiple_times(self):
     a = Sequence('a', [
         Field('b', length=8),
         Sequence('c', [], value=parse('${b} + ${b}')),
         ])
     # TODO: We should correctly be able to invert 'c = b + b'. See issue245.
     #self.assertEqual({'${b}':7}, _solve(a, 1, 14))
     self.assertRaises(SolverError, _solve, a, 1, 14)