def test_adds_correct_existence_condition(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar\n") self.assertEqual([], synthetics.desugar(ir)) bits_field = ir.module[0].type[0].structure.field[0] alias_field = ir.module[0].type[0].structure.field[1] self.assertEqual("bar", alias_field.name.name.text) self.assertEqual( bits_field.name.name.text, alias_field.existence_condition.function.args[0].function.args[0]. field_reference.path[0].source_name[-1].text) self.assertEqual( bits_field.name.name.text, alias_field.existence_condition.function.args[1].function.args[0]. field_reference.path[0].source_name[-1].text) self.assertEqual( "bar", alias_field.existence_condition.function.args[1].function. args[0].field_reference.path[1].source_name[-1].text) self.assertEqual( ir_pb2.Function.PRESENCE, alias_field.existence_condition.function.args[0].function.function) self.assertEqual( ir_pb2.Function.PRESENCE, alias_field.existence_condition.function.args[1].function.function) self.assertEqual(ir_pb2.Function.AND, alias_field.existence_condition.function.function)
def test_adds_text_output_skip_attribute_to_anonymous_bits(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar (b)\n") self.assertEqual([], synthetics.desugar(ir)) bits_field = ir.module[0].type[0].structure.field[0] text_output_attribute = self._find_attribute(bits_field, "text_output") self.assertEqual("Skip", text_output_attribute.value.string_constant.text)
def test_adds_correct_abbreviation(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar\n" " 4 [+4] UInt baz (qux)\n") self.assertEqual([], synthetics.desugar(ir)) bar_alias = ir.module[0].type[0].structure.field[1] baz_alias = ir.module[0].type[0].structure.field[2] self.assertFalse(bar_alias.HasField("abbreviation")) self.assertEqual("qux", baz_alias.abbreviation.text)
def test_next_in_size(self): ir = self._make_ir("struct Foo:\n" " 0 [+2] UInt:8[] a\n" " 1 [+$next] UInt b\n") struct = ir.module[0].type[0].structure self.assertEqual([[ error.error( "m.emb", struct.field[1].location.size.source_location, "`$next` may only be used in the start expression of a " + "physical field."), ]], synthetics.desugar(ir))
def test_next_in_first_field(self): ir = self._make_ir("struct Foo:\n" " $next [+2] UInt:8[] a\n" " $next [+4] UInt b\n") struct = ir.module[0].type[0].structure self.assertEqual([[ error.error( "m.emb", struct.field[0].location.start.source_location, "`$next` may not be used in the first physical field of " + "a structure; perhaps you meant `0`?"), ]], synthetics.desugar(ir))
def test_adds_text_output_skip_attribute_to_size_in_bytes(self): ir = self._make_ir("struct Foo:\n" " 1 [+l] UInt:8[] bytes\n" " 0 [+1] UInt length (l)\n") self.assertEqual([], synthetics.desugar(ir)) size_in_bytes_field = ir.module[0].type[0].structure.field[2] self.assertEqual("$size_in_bytes", size_in_bytes_field.name.name.text) text_output_attribute = self._find_attribute(size_in_bytes_field, "text_output") self.assertEqual("Skip", text_output_attribute.value.string_constant.text)
def test_skip_attribute_is_marked_as_synthetic(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar\n") self.assertEqual([], synthetics.desugar(ir)) bits_field = ir.module[0].type[0].structure.field[0] attribute = self._find_attribute(bits_field, "text_output") self.assertTrue(attribute.source_location.is_synthetic) self.assertTrue(attribute.name.source_location.is_synthetic) self.assertTrue(attribute.value.source_location.is_synthetic) self.assertTrue( attribute.value.string_constant.source_location.is_synthetic)
def test_adds_correct_read_transform(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar\n") self.assertEqual([], synthetics.desugar(ir)) bits_field = ir.module[0].type[0].structure.field[0] alias_field = ir.module[0].type[0].structure.field[1] self.assertEqual("bar", alias_field.name.name.text) self.assertEqual( bits_field.name.name.text, alias_field.read_transform. field_reference.path[0].source_name[-1].text) self.assertEqual( "bar", alias_field.read_transform.field_reference.path[1]. source_name[-1].text)
def test_replaces_next(self): ir = self._make_ir("struct Foo:\n" " 1 [+2] UInt:8[] a\n" " $next [+4] UInt b\n" " $next [+1] UInt c\n") self.assertEqual([], synthetics.desugar(ir)) offset_of_b = ir.module[0].type[0].structure.field[1].location.start self.assertTrue(offset_of_b.HasField("function")) self.assertEqual(offset_of_b.function.function, ir_pb2.Function.ADDITION) self.assertEqual(offset_of_b.function.args[0].constant.value, "1") self.assertEqual(offset_of_b.function.args[1].constant.value, "2") offset_of_c = ir.module[0].type[0].structure.field[2].location.start self.assertEqual( offset_of_c.function.args[0].function.args[0].constant.value, "1") self.assertEqual( offset_of_c.function.args[0].function.args[1].constant.value, "2") self.assertEqual(offset_of_c.function.args[1].constant.value, "4")
def test_adds_anonymous_bits_fields(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] Bar bar\n" " 4 [+4] UInt uint\n" " 1 [+1] bits:\n" " 0 [+4] Bits nested_bits\n" "enum Bar:\n" " BAR = 0\n" "bits Bits:\n" " 0 [+4] UInt uint\n") self.assertEqual([], synthetics.desugar(ir)) structure = ir.module[0].type[0].structure # The first field should be the anonymous bits structure. self.assertTrue(structure.field[0].HasField("location")) # Then the aliases generated for those structures. self.assertEqual("bar", structure.field[1].name.name.text) self.assertEqual("uint", structure.field[2].name.name.text) # Then the second anonymous bits. self.assertTrue(structure.field[3].HasField("location")) # Then the alias from the second anonymous bits. self.assertEqual("nested_bits", structure.field[4].name.name.text)
def test_adds_size_in_bits(self): ir = self._make_ir("bits Foo:\n" " 1 [+9] UInt hi\n" " 0 [+1] Flag lo\n") self.assertEqual([], synthetics.desugar(ir)) structure = ir.module[0].type[0].structure size_in_bits_field = structure.field[2] max_size_in_bits_field = structure.field[3] min_size_in_bits_field = structure.field[4] self.assertEqual("$size_in_bits", size_in_bits_field.name.name.text) self.assertEqual(ir_pb2.Function.MAXIMUM, size_in_bits_field.read_transform.function.function) self.assertEqual("$max_size_in_bits", max_size_in_bits_field.name.name.text) self.assertEqual( ir_pb2.Function.UPPER_BOUND, max_size_in_bits_field.read_transform.function.function) self.assertEqual("$min_size_in_bits", min_size_in_bits_field.name.name.text) self.assertEqual( ir_pb2.Function.LOWER_BOUND, min_size_in_bits_field.read_transform.function.function)
def test_anonymous_bits_sets_correct_is_synthetic(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] bits:\n" " 0 [+4] UInt bar (b)\n") self.assertEqual([], synthetics.desugar(ir)) bits_field = ir.module[0].type[0].subtype[0].structure.field[0] alias_field = ir.module[0].type[0].structure.field[1] self.assertFalse(alias_field.name.source_location.is_synthetic) self.assertTrue(alias_field.HasField("abbreviation")) self.assertFalse(alias_field.abbreviation.source_location.is_synthetic) self.assertTrue(alias_field.HasField("read_transform")) read_alias = alias_field.read_transform self.assertTrue(read_alias.source_location.is_synthetic) self.assertTrue( read_alias.field_reference.path[0].source_location.is_synthetic) alias_condition = alias_field.existence_condition self.assertTrue(alias_condition.source_location.is_synthetic) self.assertTrue( alias_condition.function.args[0].source_location.is_synthetic) self.assertTrue(bits_field.name.source_location.is_synthetic) self.assertTrue(bits_field.name.name.source_location.is_synthetic) self.assertTrue(bits_field.abbreviation.source_location.is_synthetic)
def test_nothing_to_do(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+1] UInt:8[] y\n") self.assertEqual([], synthetics.desugar(ir))