| # Copyright 2019 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Tests for util.ir_util.""" |
| |
| import unittest |
| from compiler.util import ir_pb2 |
| from compiler.util import expression_parser |
| from compiler.util import ir_util |
| |
| |
| def _parse_expression(text): |
| return expression_parser.parse(text) |
| |
| |
| class IrUtilTest(unittest.TestCase): |
| """Tests for the miscellaneous utility functions in ir_util.py.""" |
| |
| def test_is_constant_integer(self): |
| self.assertTrue(ir_util.is_constant(_parse_expression("6"))) |
| expression = _parse_expression("12") |
| # The type information should be ignored for constants like this one. |
| expression.type.integer.CopyFrom(ir_pb2.IntegerType()) |
| self.assertTrue(ir_util.is_constant(expression)) |
| |
| def test_is_constant_boolean(self): |
| self.assertTrue(ir_util.is_constant(_parse_expression("true"))) |
| expression = _parse_expression("true") |
| # The type information should be ignored for constants like this one. |
| expression.type.boolean.CopyFrom(ir_pb2.BooleanType()) |
| self.assertTrue(ir_util.is_constant(expression)) |
| |
| def test_is_constant_enum(self): |
| self.assertTrue(ir_util.is_constant(ir_pb2.Expression( |
| constant_reference=ir_pb2.Reference(), |
| type=ir_pb2.ExpressionType(enumeration=ir_pb2.EnumType(value="12"))))) |
| |
| def test_is_constant_integer_type(self): |
| self.assertFalse(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| integer=ir_pb2.IntegerType( |
| modulus="10", |
| modular_value="5", |
| minimum_value="-5", |
| maximum_value="15")))) |
| self.assertTrue(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| integer=ir_pb2.IntegerType( |
| modulus="infinity", |
| modular_value="5", |
| minimum_value="5", |
| maximum_value="5")))) |
| |
| def test_is_constant_boolean_type(self): |
| self.assertFalse(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| boolean=ir_pb2.BooleanType()))) |
| self.assertTrue(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| boolean=ir_pb2.BooleanType(value=True)))) |
| self.assertTrue(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| boolean=ir_pb2.BooleanType(value=False)))) |
| |
| def test_is_constant_enumeration_type(self): |
| self.assertFalse(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| enumeration=ir_pb2.EnumType()))) |
| self.assertTrue(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| enumeration=ir_pb2.EnumType(value="0")))) |
| |
| def test_is_constant_opaque_type(self): |
| self.assertFalse(ir_util.is_constant_type(ir_pb2.ExpressionType( |
| opaque=ir_pb2.OpaqueType()))) |
| |
| def test_constant_value_of_integer(self): |
| self.assertEqual(6, ir_util.constant_value(_parse_expression("6"))) |
| |
| def test_constant_value_of_none(self): |
| self.assertIsNone(ir_util.constant_value(ir_pb2.Expression())) |
| |
| def test_constant_value_of_addition(self): |
| self.assertEqual(6, ir_util.constant_value(_parse_expression("2+4"))) |
| |
| def test_constant_value_of_subtraction(self): |
| self.assertEqual(-2, ir_util.constant_value(_parse_expression("2-4"))) |
| |
| def test_constant_value_of_multiplication(self): |
| self.assertEqual(8, ir_util.constant_value(_parse_expression("2*4"))) |
| |
| def test_constant_value_of_equality(self): |
| self.assertFalse(ir_util.constant_value(_parse_expression("2 == 4"))) |
| |
| def test_constant_value_of_inequality(self): |
| self.assertTrue(ir_util.constant_value(_parse_expression("2 != 4"))) |
| |
| def test_constant_value_of_less(self): |
| self.assertTrue(ir_util.constant_value(_parse_expression("2 < 4"))) |
| |
| def test_constant_value_of_less_or_equal(self): |
| self.assertTrue(ir_util.constant_value(_parse_expression("2 <= 4"))) |
| |
| def test_constant_value_of_greater(self): |
| self.assertFalse(ir_util.constant_value(_parse_expression("2 > 4"))) |
| |
| def test_constant_value_of_greater_or_equal(self): |
| self.assertFalse(ir_util.constant_value(_parse_expression("2 >= 4"))) |
| |
| def test_constant_value_of_and(self): |
| self.assertFalse(ir_util.constant_value(_parse_expression("true && false"))) |
| self.assertTrue(ir_util.constant_value(_parse_expression("true && true"))) |
| |
| def test_constant_value_of_or(self): |
| self.assertTrue(ir_util.constant_value(_parse_expression("true || false"))) |
| self.assertFalse( |
| ir_util.constant_value(_parse_expression("false || false"))) |
| |
| def test_constant_value_of_choice(self): |
| self.assertEqual( |
| 10, ir_util.constant_value(_parse_expression("false ? 20 : 10"))) |
| self.assertEqual( |
| 20, ir_util.constant_value(_parse_expression("true ? 20 : 10"))) |
| |
| def test_constant_value_of_choice_with_unknown_other_branch(self): |
| self.assertEqual( |
| 10, ir_util.constant_value(_parse_expression("false ? foo : 10"))) |
| self.assertEqual( |
| 20, ir_util.constant_value(_parse_expression("true ? 20 : foo"))) |
| |
| def test_constant_value_of_maximum(self): |
| self.assertEqual(10, |
| ir_util.constant_value(_parse_expression("$max(5, 10)"))) |
| self.assertEqual(10, |
| ir_util.constant_value(_parse_expression("$max(10)"))) |
| self.assertEqual( |
| 10, |
| ir_util.constant_value(_parse_expression("$max(5, 9, 7, 10, 6, -100)"))) |
| |
| def test_constant_value_of_boolean(self): |
| self.assertTrue(ir_util.constant_value(_parse_expression("true"))) |
| self.assertFalse(ir_util.constant_value(_parse_expression("false"))) |
| |
| def test_constant_value_of_enum(self): |
| self.assertEqual(12, ir_util.constant_value(ir_pb2.Expression( |
| constant_reference=ir_pb2.Reference(), |
| type=ir_pb2.ExpressionType(enumeration=ir_pb2.EnumType(value="12"))))) |
| |
| def test_constant_value_of_integer_reference(self): |
| self.assertEqual(12, ir_util.constant_value(ir_pb2.Expression( |
| constant_reference=ir_pb2.Reference(), |
| type=ir_pb2.ExpressionType( |
| integer=ir_pb2.IntegerType(modulus="infinity", |
| modular_value="12"))))) |
| |
| def test_constant_value_of_boolean_reference(self): |
| self.assertTrue(ir_util.constant_value(ir_pb2.Expression( |
| constant_reference=ir_pb2.Reference(), |
| type=ir_pb2.ExpressionType(boolean=ir_pb2.BooleanType(value=True))))) |
| |
| def test_constant_value_of_builtin_reference(self): |
| self.assertEqual(12, ir_util.constant_value( |
| ir_pb2.Expression( |
| builtin_reference=ir_pb2.Reference( |
| canonical_name=ir_pb2.CanonicalName(object_path=["$foo"]))), |
| {"$foo": 12})) |
| |
| def test_constant_value_of_field_reference(self): |
| self.assertIsNone(ir_util.constant_value(_parse_expression("foo"))) |
| |
| def test_constant_value_of_missing_builtin_reference(self): |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("$static_size_in_bits"), {"$bar": 12})) |
| |
| def test_constant_value_of_present_builtin_reference(self): |
| self.assertEqual(12, ir_util.constant_value( |
| _parse_expression("$static_size_in_bits"), |
| {"$static_size_in_bits": 12})) |
| |
| def test_constant_false_value_of_operator_and_with_missing_value(self): |
| self.assertIs(False, ir_util.constant_value( |
| _parse_expression("false && foo"), {"bar": 12})) |
| self.assertIs(False, ir_util.constant_value( |
| _parse_expression("foo && false"), {"bar": 12})) |
| |
| def test_constant_false_value_of_operator_and_known_value(self): |
| self.assertTrue(ir_util.constant_value( |
| _parse_expression("true && $is_statically_sized"), |
| {"$is_statically_sized": True})) |
| |
| def test_constant_none_value_of_operator_and_with_missing_value(self): |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("true && foo"), {"bar": 12})) |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("foo && true"), {"bar": 12})) |
| |
| def test_constant_false_value_of_operator_or_with_missing_value(self): |
| self.assertTrue(ir_util.constant_value( |
| _parse_expression("true || foo"), {"bar": 12})) |
| self.assertTrue(ir_util.constant_value( |
| _parse_expression("foo || true"), {"bar": 12})) |
| |
| def test_constant_none_value_of_operator_or_with_missing_value(self): |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("foo || false"), {"bar": 12})) |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("false || foo"), {"bar": 12})) |
| |
| def test_constant_value_of_operator_plus_with_missing_value(self): |
| self.assertIsNone(ir_util.constant_value( |
| _parse_expression("12 + foo"), {"bar": 12})) |
| |
| def test_is_array(self): |
| self.assertTrue( |
| ir_util.is_array(ir_pb2.Type(array_type=ir_pb2.ArrayType()))) |
| self.assertFalse( |
| ir_util.is_array(ir_pb2.Type(atomic_type=ir_pb2.AtomicType()))) |
| |
| def test_get_attribute(self): |
| type_def = ir_pb2.TypeDefinition(attribute=[ |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=ir_pb2.Expression()), |
| name=ir_pb2.Word(text="phil")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| name=ir_pb2.Word(text="bob")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob2")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| name=ir_pb2.Word(text="bob2"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob3"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word()), |
| ]) |
| self.assertEqual( |
| ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| ir_util.get_attribute(type_def.attribute, "bob")) |
| self.assertEqual( |
| ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| ir_util.get_attribute(type_def.attribute, "bob2")) |
| self.assertEqual(None, ir_util.get_attribute(type_def.attribute, "Bob")) |
| self.assertEqual(None, ir_util.get_attribute(type_def.attribute, "bob3")) |
| |
| def test_get_boolean_attribute(self): |
| type_def = ir_pb2.TypeDefinition(attribute=[ |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=ir_pb2.Expression()), |
| name=ir_pb2.Word(text="phil")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| name=ir_pb2.Word(text="bob")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob2")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| name=ir_pb2.Word(text="bob2"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob3"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word()), |
| ]) |
| self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute, "bob")) |
| self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute, |
| "bob", |
| default_value=False)) |
| self.assertFalse(ir_util.get_boolean_attribute(type_def.attribute, "bob2")) |
| self.assertFalse(ir_util.get_boolean_attribute(type_def.attribute, |
| "bob2", |
| default_value=True)) |
| self.assertIsNone(ir_util.get_boolean_attribute(type_def.attribute, "Bob")) |
| self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute, |
| "Bob", |
| default_value=True)) |
| self.assertIsNone(ir_util.get_boolean_attribute(type_def.attribute, "bob3")) |
| |
| def test_get_integer_attribute(self): |
| type_def = ir_pb2.TypeDefinition(attribute=[ |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType()))), |
| name=ir_pb2.Word(text="phil")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="20"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="20", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="10"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="10", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="5"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="5", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob2")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="0"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="0", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob2"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="30"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="30", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob3"), |
| is_default=True), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| function=ir_pb2.Function( |
| function=ir_pb2.Function.ADDITION, |
| args=[ |
| ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="100"), |
| type=ir_pb2.ExpressionType( |
| integer=ir_pb2.IntegerType( |
| modular_value="100", |
| modulus="infinity"))), |
| ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="100"), |
| type=ir_pb2.ExpressionType( |
| integer=ir_pb2.IntegerType( |
| modular_value="100", |
| modulus="infinity"))) |
| ]), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="200", |
| modulus="infinity")))), |
| name=ir_pb2.Word(text="bob4")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue( |
| expression=ir_pb2.Expression( |
| constant=ir_pb2.NumericConstant(value="40"), |
| type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType( |
| modular_value="40", |
| modulus="infinity")))), |
| name=ir_pb2.Word()), |
| ]) |
| self.assertEqual(10, |
| ir_util.get_integer_attribute(type_def.attribute, "bob")) |
| self.assertEqual(5, |
| ir_util.get_integer_attribute(type_def.attribute, "bob2")) |
| self.assertIsNone(ir_util.get_integer_attribute(type_def.attribute, "Bob")) |
| self.assertEqual(10, ir_util.get_integer_attribute(type_def.attribute, |
| "Bob", |
| default_value=10)) |
| self.assertIsNone(ir_util.get_integer_attribute(type_def.attribute, "bob3")) |
| self.assertEqual(200, ir_util.get_integer_attribute(type_def.attribute, |
| "bob4")) |
| |
| def test_get_duplicate_attribute(self): |
| type_def = ir_pb2.TypeDefinition(attribute=[ |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=ir_pb2.Expression()), |
| name=ir_pb2.Word(text="phil")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("true")), |
| name=ir_pb2.Word(text="bob")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word(text="bob")), |
| ir_pb2.Attribute( |
| value=ir_pb2.AttributeValue(expression=_parse_expression("false")), |
| name=ir_pb2.Word()), |
| ]) |
| self.assertRaises(AssertionError, ir_util.get_attribute, type_def.attribute, |
| "bob") |
| |
| def test_find_object(self): |
| ir = ir_pb2.EmbossIr.from_json( |
| """{ |
| "module": [ |
| { |
| "type": [ |
| { |
| "structure": { |
| "field": [ |
| { |
| "name": { |
| "name": { "text": "field" }, |
| "canonical_name": { |
| "module_file": "test.emb", |
| "object_path": [ "Foo", "field" ] |
| } |
| } |
| } |
| ] |
| }, |
| "name": { |
| "name": { "text": "Foo" }, |
| "canonical_name": { |
| "module_file": "test.emb", |
| "object_path": [ "Foo" ] |
| } |
| }, |
| "runtime_parameter": [ |
| { |
| "name": { |
| "name": { "text": "parameter" }, |
| "canonical_name": { |
| "module_file": "test.emb", |
| "object_path": [ "Foo", "parameter" ] |
| } |
| } |
| } |
| ] |
| }, |
| { |
| "enumeration": { |
| "value": [ |
| { |
| "name": { |
| "name": { "text": "QUX" }, |
| "canonical_name": { |
| "module_file": "test.emb", |
| "object_path": [ "Bar", "QUX" ] |
| } |
| } |
| } |
| ] |
| }, |
| "name": { |
| "name": { "text": "Bar" }, |
| "canonical_name": { |
| "module_file": "test.emb", |
| "object_path": [ "Bar" ] |
| } |
| } |
| } |
| ], |
| "source_file_name": "test.emb" |
| }, |
| { |
| "type": [ |
| { |
| "external": {}, |
| "name": { |
| "name": { "text": "UInt" }, |
| "canonical_name": { |
| "module_file": "", |
| "object_path": [ "UInt" ] |
| } |
| } |
| } |
| ], |
| "source_file_name": "" |
| } |
| ] |
| }""") |
| |
| # Test that find_object works with any of its four "name" types. |
| canonical_name_of_foo = ir_pb2.CanonicalName(module_file="test.emb", |
| object_path=["Foo"]) |
| self.assertEqual(ir.module[0].type[0], ir_util.find_object( |
| ir_pb2.Reference(canonical_name=canonical_name_of_foo), ir)) |
| self.assertEqual(ir.module[0].type[0], ir_util.find_object( |
| ir_pb2.NameDefinition(canonical_name=canonical_name_of_foo), ir)) |
| self.assertEqual(ir.module[0].type[0], |
| ir_util.find_object(canonical_name_of_foo, ir)) |
| self.assertEqual(ir.module[0].type[0], |
| ir_util.find_object(("test.emb", "Foo"), ir)) |
| |
| # Test that find_object works with objects other than structs. |
| self.assertEqual(ir.module[0].type[1], |
| ir_util.find_object(("test.emb", "Bar"), ir)) |
| self.assertEqual(ir.module[1].type[0], |
| ir_util.find_object(("", "UInt"), ir)) |
| self.assertEqual(ir.module[0].type[0].structure.field[0], |
| ir_util.find_object(("test.emb", "Foo", "field"), ir)) |
| self.assertEqual(ir.module[0].type[0].runtime_parameter[0], |
| ir_util.find_object(("test.emb", "Foo", "parameter"), ir)) |
| self.assertEqual(ir.module[0].type[1].enumeration.value[0], |
| ir_util.find_object(("test.emb", "Bar", "QUX"), ir)) |
| self.assertEqual(ir.module[0], ir_util.find_object(("test.emb",), ir)) |
| self.assertEqual(ir.module[1], ir_util.find_object(("",), ir)) |
| |
| # Test searching for non-present objects. |
| self.assertIsNone(ir_util.find_object_or_none(("not_test.emb",), ir)) |
| self.assertIsNone(ir_util.find_object_or_none(("test.emb", "NotFoo"), ir)) |
| self.assertIsNone( |
| ir_util.find_object_or_none(("test.emb", "Foo", "not_field"), ir)) |
| self.assertIsNone( |
| ir_util.find_object_or_none(("test.emb", "Foo", "field", "no_subfield"), |
| ir)) |
| self.assertIsNone( |
| ir_util.find_object_or_none(("test.emb", "Bar", "NOT_QUX"), ir)) |
| self.assertIsNone( |
| ir_util.find_object_or_none(("test.emb", "Bar", "QUX", "no_subenum"), |
| ir)) |
| |
| # Test that find_parent_object works with any of its four "name" types. |
| self.assertEqual(ir.module[0], ir_util.find_parent_object( |
| ir_pb2.Reference(canonical_name=canonical_name_of_foo), ir)) |
| self.assertEqual(ir.module[0], ir_util.find_parent_object( |
| ir_pb2.NameDefinition(canonical_name=canonical_name_of_foo), ir)) |
| self.assertEqual(ir.module[0], |
| ir_util.find_parent_object(canonical_name_of_foo, ir)) |
| self.assertEqual(ir.module[0], |
| ir_util.find_parent_object(("test.emb", "Foo"), ir)) |
| |
| # Test that find_parent_object works with objects other than structs. |
| self.assertEqual(ir.module[0], |
| ir_util.find_parent_object(("test.emb", "Bar"), ir)) |
| self.assertEqual(ir.module[1], ir_util.find_parent_object(("", "UInt"), ir)) |
| self.assertEqual(ir.module[0].type[0], |
| ir_util.find_parent_object(("test.emb", "Foo", "field"), |
| ir)) |
| self.assertEqual(ir.module[0].type[1], |
| ir_util.find_parent_object(("test.emb", "Bar", "QUX"), ir)) |
| |
| def test_hashable_form_of_reference(self): |
| self.assertEqual( |
| ("t.emb", "Foo", "Bar"), |
| ir_util.hashable_form_of_reference(ir_pb2.Reference( |
| canonical_name=ir_pb2.CanonicalName(module_file="t.emb", |
| object_path=["Foo", "Bar"])))) |
| self.assertEqual( |
| ("t.emb", "Foo", "Bar"), |
| ir_util.hashable_form_of_reference(ir_pb2.NameDefinition( |
| canonical_name=ir_pb2.CanonicalName(module_file="t.emb", |
| object_path=["Foo", "Bar"])))) |
| |
| def test_get_base_type(self): |
| array_type_ir = ir_pb2.Type.from_json( |
| """{ |
| "array_type": { |
| "element_count": { "constant": { "value": "20" } }, |
| "base_type": { |
| "array_type": { |
| "element_count": { "constant": { "value": "10" } }, |
| "base_type": { |
| "atomic_type": { |
| "reference": { }, |
| "source_location": { "start": { "line": 5 } } |
| } |
| }, |
| "source_location": { "start": { "line": 4 } } |
| } |
| }, |
| "source_location": { "start": { "line": 3 } } |
| } |
| }""") |
| base_type_ir = array_type_ir.array_type.base_type.array_type.base_type |
| self.assertEqual(base_type_ir, ir_util.get_base_type(array_type_ir)) |
| self.assertEqual(base_type_ir, ir_util.get_base_type( |
| array_type_ir.array_type.base_type)) |
| self.assertEqual(base_type_ir, ir_util.get_base_type(base_type_ir)) |
| |
| def test_size_of_type_in_bits(self): |
| ir = ir_pb2.EmbossIr.from_json( |
| """{ |
| "module": [{ |
| "type": [{ |
| "name": { |
| "name": { "text": "Baz" }, |
| "canonical_name": { |
| "module_file": "s.emb", |
| "object_path": ["Baz"] |
| } |
| } |
| }], |
| "source_file_name": "s.emb" |
| }, |
| { |
| "type": [{ |
| "name": { |
| "name": { "text": "UInt" }, |
| "canonical_name": { |
| "module_file": "", |
| "object_path": ["UInt"] |
| } |
| } |
| }, |
| { |
| "name": { |
| "name": { "text": "Byte" }, |
| "canonical_name": { |
| "module_file": "", |
| "object_path": ["Byte"] |
| } |
| }, |
| "attribute": [{ |
| "name": { "text": "fixed_size_in_bits" }, |
| "value": { |
| "expression": { |
| "constant": { "value": "8" }, |
| "type": { |
| "integer": { "modular_value": "8", "modulus": "infinity" } |
| } |
| } |
| } |
| }] |
| }], |
| "source_file_name": "" |
| }] |
| }""") |
| |
| fixed_size_type = ir_pb2.Type.from_json( |
| """{ |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { "module_file": "", "object_path": ["Byte"] } |
| } |
| } |
| }""") |
| self.assertEqual(8, ir_util.fixed_size_of_type_in_bits(fixed_size_type, ir)) |
| |
| explicit_size_type = ir_pb2.Type.from_json( |
| """{ |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { "module_file": "", "object_path": ["UInt"] } |
| } |
| }, |
| "size_in_bits": { |
| "constant": { "value": "32" }, |
| "type": { |
| "integer": { "modular_value": "32", "modulus": "infinity" } |
| } |
| } |
| }""") |
| self.assertEqual(32, |
| ir_util.fixed_size_of_type_in_bits(explicit_size_type, ir)) |
| |
| fixed_size_array = ir_pb2.Type.from_json( |
| """{ |
| "array_type": { |
| "base_type": { |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { "module_file": "", "object_path": ["Byte"] } |
| } |
| } |
| }, |
| "element_count": { |
| "constant": { "value": "5" }, |
| "type": { |
| "integer": { "modular_value": "5", "modulus": "infinity" } |
| } |
| } |
| } |
| }""") |
| self.assertEqual(40, |
| ir_util.fixed_size_of_type_in_bits(fixed_size_array, ir)) |
| |
| fixed_size_2d_array = ir_pb2.Type.from_json( |
| """{ |
| "array_type": { |
| "base_type": { |
| "array_type": { |
| "base_type": { |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { |
| "module_file": "", |
| "object_path": ["Byte"] |
| } |
| } |
| } |
| }, |
| "element_count": { |
| "constant": { "value": "5" }, |
| "type": { |
| "integer": { "modular_value": "5", "modulus": "infinity" } |
| } |
| } |
| } |
| }, |
| "element_count": { |
| "constant": { "value": "2" }, |
| "type": { |
| "integer": { "modular_value": "2", "modulus": "infinity" } |
| } |
| } |
| } |
| }""") |
| self.assertEqual( |
| 80, ir_util.fixed_size_of_type_in_bits(fixed_size_2d_array, ir)) |
| |
| automatic_size_array = ir_pb2.Type.from_json( |
| """{ |
| "array_type": { |
| "base_type": { |
| "array_type": { |
| "base_type": { |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { |
| "module_file": "", |
| "object_path": ["Byte"] |
| } |
| } |
| } |
| }, |
| "element_count": { |
| "constant": { "value": "5" }, |
| "type": { |
| "integer": { "modular_value": "5", "modulus": "infinity" } |
| } |
| } |
| } |
| }, |
| "automatic": { } |
| } |
| }""") |
| self.assertIsNone( |
| ir_util.fixed_size_of_type_in_bits(automatic_size_array, ir)) |
| |
| variable_size_type = ir_pb2.Type.from_json( |
| """{ |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { "module_file": "", "object_path": ["UInt"] } |
| } |
| } |
| }""") |
| self.assertIsNone( |
| ir_util.fixed_size_of_type_in_bits(variable_size_type, ir)) |
| |
| no_size_type = ir_pb2.Type.from_json( |
| """{ |
| "atomic_type": { |
| "reference": { |
| "canonical_name": { |
| "module_file": "s.emb", |
| "object_path": ["Baz"] |
| } |
| } |
| } |
| }""") |
| self.assertIsNone(ir_util.fixed_size_of_type_in_bits(no_size_type, ir)) |
| |
| def test_field_is_virtual(self): |
| self.assertTrue(ir_util.field_is_virtual(ir_pb2.Field())) |
| |
| def test_field_is_not_virtual(self): |
| self.assertFalse(ir_util.field_is_virtual( |
| ir_pb2.Field(location=ir_pb2.FieldLocation()))) |
| |
| def test_field_is_read_only(self): |
| self.assertTrue(ir_util.field_is_read_only(ir_pb2.Field( |
| write_method=ir_pb2.WriteMethod(read_only=True)))) |
| |
| def test_field_is_not_read_only(self): |
| self.assertFalse(ir_util.field_is_read_only( |
| ir_pb2.Field(location=ir_pb2.FieldLocation()))) |
| self.assertFalse(ir_util.field_is_read_only(ir_pb2.Field( |
| write_method=ir_pb2.WriteMethod()))) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |