def test_unused_parameters(self): # Test detection of re-use of a common entry, where not all output parameters are used. length = Field('length', 8) shared = Sequence('shared', [length]) length_value = ValueResult('shared.length') # Now we'll reference that common component twice, but only once # referencing an actual value. In 'b' we use it twice, to detect that # it only turns up in the locals list once. a = Sequence('a', [shared, Field('a data', length_value)]) b = Sequence('b', [shared, shared]) spec = Sequence('spec', [a,b]) vars = ExpressionParameters([spec]) self.assertEqual([], list(vars.get_params(spec))) self.assertTrue(vars.is_value_referenced(length)) self.assertFalse(vars.is_value_referenced(shared)) self.assertEqual([], vars.get_locals(spec)) # Test that the 'length' and 'shared' entries pass out their value self.assertEqual([Param('length', Param.OUT, _Integer())], list(vars.get_params(length))) self.assertEqual([Param('length', Param.OUT, _Integer())], vars.get_params(shared)) # First validate the passing of the length value within entry 'a' self.assertEqual([], vars.get_params(a)) self.assertEqual([Local('shared.length', _Integer())], vars.get_locals(a)) self.assertEqual([Param('shared.length', Param.OUT, _Integer())], list(vars.get_passed_variables(a, a.children[0]))) self.assertEqual([Param('shared.length', Param.IN, _Integer())], list(vars.get_passed_variables(a, a.children[1]))) self.assertEqual([], list(vars.get_passed_variables(spec, spec.children[0]))) # Now test the passing out (and ignoring) of the length value within 'b' self.assertEqual([], vars.get_params(b)) self.assertEqual([Local('unused length', _Integer())], vars.get_locals(b)) self.assertEqual([Param('unused length', Param.OUT, _Integer())], list(vars.get_passed_variables(b, b.children[0]))) self.assertEqual([], list(vars.get_passed_variables(spec, spec.children[0])))
def test_sequence_value(self): # Define an integer with a custom byte ordering lower = Field('lower byte', 8) lower_value = ValueResult('lower byte') ignored = Field('ignored', 8) upper = Field('upper byte', 8) upper_value = ValueResult('upper byte') value = ArithmeticExpression(operator.__add__, ArithmeticExpression(operator.__mul__, upper_value, Constant(256)), lower_value) length = Sequence('length', [lower, ignored, upper], value) header = Sequence('header', [length]) int_value = ValueResult('length') data = Field('data', int_value) spec = Sequence('blah', [length, data]) vars = ExpressionParameters([spec]) self.assertEquals([], vars.get_params(spec)) self.assertTrue(vars.is_value_referenced(lower)) self.assertFalse(vars.is_value_referenced(ignored)) self.assertTrue(vars.is_value_referenced(upper)) self.assertEqual([Local('lower byte', _Integer()), Local('upper byte', _Integer())], vars.get_locals(length)) self.assertEqual([Param('lower byte', Param.OUT, _Integer())], vars.get_params(lower)) self.assertEqual([Param('upper byte', Param.OUT, _Integer())], vars.get_params(upper)) self.assertEqual([Param('length', Param.OUT, _Integer())], vars.get_params(length)) self.assertEqual([Local('length', _Integer())], vars.get_locals(spec)) self.assertEqual([Param('length', Param.IN, _Integer())], vars.get_params(data))
def test_direct_children(self): a = Field('a', 8) value = ValueResult('a') b = Field('b', value) spec = Sequence('blah', [a,b]) vars = ExpressionParameters([spec]) self.assertEqual([Local('a', _Integer())], vars.get_locals(spec)) self.assertTrue(vars.is_value_referenced(a)) self.assertFalse(vars.is_value_referenced(b)) self.assertEqual([], vars.get_locals(a))
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])))
def test_reference_outside_of_choice(self): """ Test passing in a parameter into choice options. """ # Note that the 'integer' option has a fixed length... length = Field('length:', 8) length_value = ValueResult('length:') text = Sequence('text', [ Field('id:', 8, constraints=[Equals(Data('\x00'))]), Field('value', length_value, Field.TEXT)]) integer = Sequence('integer', [ Field('id:', 8, constraints=[Equals(Data('\x01'))]), Field('value', 16, Field.INTEGER)]) spec = Sequence('spec', [length, Choice('data', [text, integer])]) vars = ExpressionParameters([spec]) self.assertTrue(vars.is_value_referenced(length)) self.assertEqual([], vars.get_params(spec)) self.assertEqual([Local('length:', _Integer())], vars.get_locals(spec)) self.assertEqual([Param('length:', Param.OUT, _Integer())], vars.get_params(length)) self.assertEqual([Param('length:', Param.OUT, _Integer())], list(vars.get_passed_variables(spec, spec.children[0]))) self.assertEqual([Param('length:', Param.IN, _Integer())], vars.get_params(spec.children[1].entry)) self.assertEqual([Param('length:', Param.IN, _Integer())], list(vars.get_passed_variables(spec, spec.children[1]))) self.assertEqual([Param('length:', Param.IN, _Integer())], vars.get_params(text)) self.assertEqual([Param('length:', Param.IN, _Integer())], list(vars.get_passed_variables(spec.children[1].entry, spec.children[1].entry.children[0]))) self.assertEqual([Param('length:', Param.IN, _Integer())], vars.get_params(text.children[1].entry)) self.assertEqual([], vars.get_params(integer)) self.assertEqual([], list(vars.get_passed_variables(spec.children[1].entry, spec.children[1].entry.children[1])))
def test_name_ends_in_length(self): a = Field('data length', 8, Field.INTEGER) b = Field('data', parse('${data length} * 8')) c = Sequence('c', [a, b]) params = ExpressionParameters([c]) self.assertEqual([Local('data length', _Integer())], params.get_locals(c)) self.assertEqual([], params.get_params(c)) self.assertEqual([Param('data length', Param.OUT, _Integer())], params.get_params(a)) self.assertEqual([Param('data length', Param.IN, _Integer())], params.get_params(b)) self.assertEqual(True, params.is_value_referenced(a)) self.assertEqual(False, params.is_length_referenced(a))
def test_choice_reference(self): """ Test the parameter names when we have items selected under a choice. """ byte = Sequence('8 bit:', [Field('id', 8, constraints=[Equals(Data('\x00'))]), Field('length', 8)]) word = Sequence('16 bit:', [Field('id', 8, constraints=[Equals(Data('\x01'))]), Field('length', 16)]) length = Choice('variable integer', [byte, word]) length_value = ValueResult('variable integer.length') data = Field('data', length_value) spec = Sequence('spec', [length, data]) vars = ExpressionParameters([spec]) self.assertFalse(vars.is_value_referenced(byte)) self.assertTrue(vars.is_value_referenced(byte.children[1].entry)) self.assertFalse(vars.is_value_referenced(word)) self.assertTrue(vars.is_value_referenced(word.children[1].entry)) self.assertEqual([Param('length', Param.OUT, _Integer())], vars.get_params(byte)) self.assertEqual([Param('length', Param.OUT, _Integer())], vars.get_params(word)) self.assertEqual([Param('length', Param.OUT, _Integer())], vars.get_params(length)) self.assertEqual([], vars.get_locals(length)) self.assertEqual([Param('length', Param.OUT, _Integer())], list(vars.get_passed_variables(length, length.children[0]))) self.assertEqual([Local('variable integer.length', _Integer())], vars.get_locals(spec)) self.assertEqual([Param('variable integer.length', Param.IN, _Integer())], vars.get_params(data))