xref: /aosp_15_r20/external/emboss/compiler/util/ir_util_test.py (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Tests for util.ir_util."""
16
17import unittest
18from compiler.util import expression_parser
19from compiler.util import ir_data
20from compiler.util import ir_data_utils
21from compiler.util import ir_util
22
23
24def _parse_expression(text):
25  return expression_parser.parse(text)
26
27
28class IrUtilTest(unittest.TestCase):
29  """Tests for the miscellaneous utility functions in ir_util.py."""
30
31  def test_is_constant_integer(self):
32    self.assertTrue(ir_util.is_constant(_parse_expression("6")))
33    expression = _parse_expression("12")
34    # The type information should be ignored for constants like this one.
35    ir_data_utils.builder(expression).type.integer.CopyFrom(ir_data.IntegerType())
36    self.assertTrue(ir_util.is_constant(expression))
37
38  def test_is_constant_boolean(self):
39    self.assertTrue(ir_util.is_constant(_parse_expression("true")))
40    expression = _parse_expression("true")
41    # The type information should be ignored for constants like this one.
42    ir_data_utils.builder(expression).type.boolean.CopyFrom(ir_data.BooleanType())
43    self.assertTrue(ir_util.is_constant(expression))
44
45  def test_is_constant_enum(self):
46    self.assertTrue(ir_util.is_constant(ir_data.Expression(
47        constant_reference=ir_data.Reference(),
48        type=ir_data.ExpressionType(enumeration=ir_data.EnumType(value="12")))))
49
50  def test_is_constant_integer_type(self):
51    self.assertFalse(ir_util.is_constant_type(ir_data.ExpressionType(
52        integer=ir_data.IntegerType(
53            modulus="10",
54            modular_value="5",
55            minimum_value="-5",
56            maximum_value="15"))))
57    self.assertTrue(ir_util.is_constant_type(ir_data.ExpressionType(
58        integer=ir_data.IntegerType(
59            modulus="infinity",
60            modular_value="5",
61            minimum_value="5",
62            maximum_value="5"))))
63
64  def test_is_constant_boolean_type(self):
65    self.assertFalse(ir_util.is_constant_type(ir_data.ExpressionType(
66        boolean=ir_data.BooleanType())))
67    self.assertTrue(ir_util.is_constant_type(ir_data.ExpressionType(
68        boolean=ir_data.BooleanType(value=True))))
69    self.assertTrue(ir_util.is_constant_type(ir_data.ExpressionType(
70        boolean=ir_data.BooleanType(value=False))))
71
72  def test_is_constant_enumeration_type(self):
73    self.assertFalse(ir_util.is_constant_type(ir_data.ExpressionType(
74        enumeration=ir_data.EnumType())))
75    self.assertTrue(ir_util.is_constant_type(ir_data.ExpressionType(
76        enumeration=ir_data.EnumType(value="0"))))
77
78  def test_is_constant_opaque_type(self):
79    self.assertFalse(ir_util.is_constant_type(ir_data.ExpressionType(
80        opaque=ir_data.OpaqueType())))
81
82  def test_constant_value_of_integer(self):
83    self.assertEqual(6, ir_util.constant_value(_parse_expression("6")))
84
85  def test_constant_value_of_none(self):
86    self.assertIsNone(ir_util.constant_value(ir_data.Expression()))
87
88  def test_constant_value_of_addition(self):
89    self.assertEqual(6, ir_util.constant_value(_parse_expression("2+4")))
90
91  def test_constant_value_of_subtraction(self):
92    self.assertEqual(-2, ir_util.constant_value(_parse_expression("2-4")))
93
94  def test_constant_value_of_multiplication(self):
95    self.assertEqual(8, ir_util.constant_value(_parse_expression("2*4")))
96
97  def test_constant_value_of_equality(self):
98    self.assertFalse(ir_util.constant_value(_parse_expression("2 == 4")))
99
100  def test_constant_value_of_inequality(self):
101    self.assertTrue(ir_util.constant_value(_parse_expression("2 != 4")))
102
103  def test_constant_value_of_less(self):
104    self.assertTrue(ir_util.constant_value(_parse_expression("2 < 4")))
105
106  def test_constant_value_of_less_or_equal(self):
107    self.assertTrue(ir_util.constant_value(_parse_expression("2 <= 4")))
108
109  def test_constant_value_of_greater(self):
110    self.assertFalse(ir_util.constant_value(_parse_expression("2 > 4")))
111
112  def test_constant_value_of_greater_or_equal(self):
113    self.assertFalse(ir_util.constant_value(_parse_expression("2 >= 4")))
114
115  def test_constant_value_of_and(self):
116    self.assertFalse(ir_util.constant_value(_parse_expression("true && false")))
117    self.assertTrue(ir_util.constant_value(_parse_expression("true && true")))
118
119  def test_constant_value_of_or(self):
120    self.assertTrue(ir_util.constant_value(_parse_expression("true || false")))
121    self.assertFalse(
122        ir_util.constant_value(_parse_expression("false || false")))
123
124  def test_constant_value_of_choice(self):
125    self.assertEqual(
126        10, ir_util.constant_value(_parse_expression("false ? 20 : 10")))
127    self.assertEqual(
128        20, ir_util.constant_value(_parse_expression("true ? 20 : 10")))
129
130  def test_constant_value_of_choice_with_unknown_other_branch(self):
131    self.assertEqual(
132        10, ir_util.constant_value(_parse_expression("false ? foo : 10")))
133    self.assertEqual(
134        20, ir_util.constant_value(_parse_expression("true ? 20 : foo")))
135
136  def test_constant_value_of_maximum(self):
137    self.assertEqual(10,
138                     ir_util.constant_value(_parse_expression("$max(5, 10)")))
139    self.assertEqual(10,
140                     ir_util.constant_value(_parse_expression("$max(10)")))
141    self.assertEqual(
142        10,
143        ir_util.constant_value(_parse_expression("$max(5, 9, 7, 10, 6, -100)")))
144
145  def test_constant_value_of_boolean(self):
146    self.assertTrue(ir_util.constant_value(_parse_expression("true")))
147    self.assertFalse(ir_util.constant_value(_parse_expression("false")))
148
149  def test_constant_value_of_enum(self):
150    self.assertEqual(12, ir_util.constant_value(ir_data.Expression(
151        constant_reference=ir_data.Reference(),
152        type=ir_data.ExpressionType(enumeration=ir_data.EnumType(value="12")))))
153
154  def test_constant_value_of_integer_reference(self):
155    self.assertEqual(12, ir_util.constant_value(ir_data.Expression(
156        constant_reference=ir_data.Reference(),
157        type=ir_data.ExpressionType(
158            integer=ir_data.IntegerType(modulus="infinity",
159                                       modular_value="12")))))
160
161  def test_constant_value_of_boolean_reference(self):
162    self.assertTrue(ir_util.constant_value(ir_data.Expression(
163        constant_reference=ir_data.Reference(),
164        type=ir_data.ExpressionType(boolean=ir_data.BooleanType(value=True)))))
165
166  def test_constant_value_of_builtin_reference(self):
167    self.assertEqual(12, ir_util.constant_value(
168        ir_data.Expression(
169            builtin_reference=ir_data.Reference(
170                canonical_name=ir_data.CanonicalName(object_path=["$foo"]))),
171        {"$foo": 12}))
172
173  def test_constant_value_of_field_reference(self):
174    self.assertIsNone(ir_util.constant_value(_parse_expression("foo")))
175
176  def test_constant_value_of_missing_builtin_reference(self):
177    self.assertIsNone(ir_util.constant_value(
178        _parse_expression("$static_size_in_bits"), {"$bar": 12}))
179
180  def test_constant_value_of_present_builtin_reference(self):
181    self.assertEqual(12, ir_util.constant_value(
182        _parse_expression("$static_size_in_bits"),
183        {"$static_size_in_bits": 12}))
184
185  def test_constant_false_value_of_operator_and_with_missing_value(self):
186    self.assertIs(False, ir_util.constant_value(
187        _parse_expression("false && foo"), {"bar": 12}))
188    self.assertIs(False, ir_util.constant_value(
189        _parse_expression("foo && false"), {"bar": 12}))
190
191  def test_constant_false_value_of_operator_and_known_value(self):
192    self.assertTrue(ir_util.constant_value(
193        _parse_expression("true && $is_statically_sized"),
194        {"$is_statically_sized": True}))
195
196  def test_constant_none_value_of_operator_and_with_missing_value(self):
197    self.assertIsNone(ir_util.constant_value(
198        _parse_expression("true && foo"), {"bar": 12}))
199    self.assertIsNone(ir_util.constant_value(
200        _parse_expression("foo && true"), {"bar": 12}))
201
202  def test_constant_false_value_of_operator_or_with_missing_value(self):
203    self.assertTrue(ir_util.constant_value(
204        _parse_expression("true || foo"), {"bar": 12}))
205    self.assertTrue(ir_util.constant_value(
206        _parse_expression("foo || true"), {"bar": 12}))
207
208  def test_constant_none_value_of_operator_or_with_missing_value(self):
209    self.assertIsNone(ir_util.constant_value(
210        _parse_expression("foo || false"), {"bar": 12}))
211    self.assertIsNone(ir_util.constant_value(
212        _parse_expression("false || foo"), {"bar": 12}))
213
214  def test_constant_value_of_operator_plus_with_missing_value(self):
215    self.assertIsNone(ir_util.constant_value(
216        _parse_expression("12 + foo"), {"bar": 12}))
217
218  def test_is_array(self):
219    self.assertTrue(
220        ir_util.is_array(ir_data.Type(array_type=ir_data.ArrayType())))
221    self.assertFalse(
222        ir_util.is_array(ir_data.Type(atomic_type=ir_data.AtomicType())))
223
224  def test_get_attribute(self):
225    type_def = ir_data.TypeDefinition(attribute=[
226        ir_data.Attribute(
227            value=ir_data.AttributeValue(expression=ir_data.Expression()),
228            name=ir_data.Word(text="phil")),
229        ir_data.Attribute(
230            value=ir_data.AttributeValue(expression=_parse_expression("false")),
231            name=ir_data.Word(text="bob"),
232            is_default=True),
233        ir_data.Attribute(
234            value=ir_data.AttributeValue(expression=_parse_expression("true")),
235            name=ir_data.Word(text="bob")),
236        ir_data.Attribute(
237            value=ir_data.AttributeValue(expression=_parse_expression("false")),
238            name=ir_data.Word(text="bob2")),
239        ir_data.Attribute(
240            value=ir_data.AttributeValue(expression=_parse_expression("true")),
241            name=ir_data.Word(text="bob2"),
242            is_default=True),
243        ir_data.Attribute(
244            value=ir_data.AttributeValue(expression=_parse_expression("false")),
245            name=ir_data.Word(text="bob3"),
246            is_default=True),
247        ir_data.Attribute(
248            value=ir_data.AttributeValue(expression=_parse_expression("false")),
249            name=ir_data.Word()),
250    ])
251    self.assertEqual(
252        ir_data.AttributeValue(expression=_parse_expression("true")),
253        ir_util.get_attribute(type_def.attribute, "bob"))
254    self.assertEqual(
255        ir_data.AttributeValue(expression=_parse_expression("false")),
256        ir_util.get_attribute(type_def.attribute, "bob2"))
257    self.assertEqual(None, ir_util.get_attribute(type_def.attribute, "Bob"))
258    self.assertEqual(None, ir_util.get_attribute(type_def.attribute, "bob3"))
259
260  def test_get_boolean_attribute(self):
261    type_def = ir_data.TypeDefinition(attribute=[
262        ir_data.Attribute(
263            value=ir_data.AttributeValue(expression=ir_data.Expression()),
264            name=ir_data.Word(text="phil")),
265        ir_data.Attribute(
266            value=ir_data.AttributeValue(expression=_parse_expression("false")),
267            name=ir_data.Word(text="bob"),
268            is_default=True),
269        ir_data.Attribute(
270            value=ir_data.AttributeValue(expression=_parse_expression("true")),
271            name=ir_data.Word(text="bob")),
272        ir_data.Attribute(
273            value=ir_data.AttributeValue(expression=_parse_expression("false")),
274            name=ir_data.Word(text="bob2")),
275        ir_data.Attribute(
276            value=ir_data.AttributeValue(expression=_parse_expression("true")),
277            name=ir_data.Word(text="bob2"),
278            is_default=True),
279        ir_data.Attribute(
280            value=ir_data.AttributeValue(expression=_parse_expression("false")),
281            name=ir_data.Word(text="bob3"),
282            is_default=True),
283        ir_data.Attribute(
284            value=ir_data.AttributeValue(expression=_parse_expression("false")),
285            name=ir_data.Word()),
286    ])
287    self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute, "bob"))
288    self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute,
289                                                  "bob",
290                                                  default_value=False))
291    self.assertFalse(ir_util.get_boolean_attribute(type_def.attribute, "bob2"))
292    self.assertFalse(ir_util.get_boolean_attribute(type_def.attribute,
293                                                   "bob2",
294                                                   default_value=True))
295    self.assertIsNone(ir_util.get_boolean_attribute(type_def.attribute, "Bob"))
296    self.assertTrue(ir_util.get_boolean_attribute(type_def.attribute,
297                                                  "Bob",
298                                                  default_value=True))
299    self.assertIsNone(ir_util.get_boolean_attribute(type_def.attribute, "bob3"))
300
301  def test_get_integer_attribute(self):
302    type_def = ir_data.TypeDefinition(attribute=[
303        ir_data.Attribute(
304            value=ir_data.AttributeValue(
305                expression=ir_data.Expression(
306                    type=ir_data.ExpressionType(integer=ir_data.IntegerType()))),
307            name=ir_data.Word(text="phil")),
308        ir_data.Attribute(
309            value=ir_data.AttributeValue(
310                expression=ir_data.Expression(
311                    constant=ir_data.NumericConstant(value="20"),
312                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
313                        modular_value="20",
314                        modulus="infinity")))),
315            name=ir_data.Word(text="bob"),
316            is_default=True),
317        ir_data.Attribute(
318            value=ir_data.AttributeValue(
319                expression=ir_data.Expression(
320                    constant=ir_data.NumericConstant(value="10"),
321                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
322                        modular_value="10",
323                        modulus="infinity")))),
324            name=ir_data.Word(text="bob")),
325        ir_data.Attribute(
326            value=ir_data.AttributeValue(
327                expression=ir_data.Expression(
328                    constant=ir_data.NumericConstant(value="5"),
329                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
330                        modular_value="5",
331                        modulus="infinity")))),
332            name=ir_data.Word(text="bob2")),
333        ir_data.Attribute(
334            value=ir_data.AttributeValue(
335                expression=ir_data.Expression(
336                    constant=ir_data.NumericConstant(value="0"),
337                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
338                        modular_value="0",
339                        modulus="infinity")))),
340            name=ir_data.Word(text="bob2"),
341            is_default=True),
342        ir_data.Attribute(
343            value=ir_data.AttributeValue(
344                expression=ir_data.Expression(
345                    constant=ir_data.NumericConstant(value="30"),
346                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
347                        modular_value="30",
348                        modulus="infinity")))),
349            name=ir_data.Word(text="bob3"),
350            is_default=True),
351        ir_data.Attribute(
352            value=ir_data.AttributeValue(
353                expression=ir_data.Expression(
354                    function=ir_data.Function(
355                        function=ir_data.FunctionMapping.ADDITION,
356                        args=[
357                            ir_data.Expression(
358                                constant=ir_data.NumericConstant(value="100"),
359                                type=ir_data.ExpressionType(
360                                    integer=ir_data.IntegerType(
361                                        modular_value="100",
362                                        modulus="infinity"))),
363                            ir_data.Expression(
364                                constant=ir_data.NumericConstant(value="100"),
365                                type=ir_data.ExpressionType(
366                                    integer=ir_data.IntegerType(
367                                        modular_value="100",
368                                        modulus="infinity")))
369                        ]),
370                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
371                        modular_value="200",
372                        modulus="infinity")))),
373            name=ir_data.Word(text="bob4")),
374        ir_data.Attribute(
375            value=ir_data.AttributeValue(
376                expression=ir_data.Expression(
377                    constant=ir_data.NumericConstant(value="40"),
378                    type=ir_data.ExpressionType(integer=ir_data.IntegerType(
379                        modular_value="40",
380                        modulus="infinity")))),
381            name=ir_data.Word()),
382    ])
383    self.assertEqual(10,
384                     ir_util.get_integer_attribute(type_def.attribute, "bob"))
385    self.assertEqual(5,
386                     ir_util.get_integer_attribute(type_def.attribute, "bob2"))
387    self.assertIsNone(ir_util.get_integer_attribute(type_def.attribute, "Bob"))
388    self.assertEqual(10, ir_util.get_integer_attribute(type_def.attribute,
389                                                       "Bob",
390                                                       default_value=10))
391    self.assertIsNone(ir_util.get_integer_attribute(type_def.attribute, "bob3"))
392    self.assertEqual(200, ir_util.get_integer_attribute(type_def.attribute,
393                                                        "bob4"))
394
395  def test_get_duplicate_attribute(self):
396    type_def = ir_data.TypeDefinition(attribute=[
397        ir_data.Attribute(
398            value=ir_data.AttributeValue(expression=ir_data.Expression()),
399            name=ir_data.Word(text="phil")),
400        ir_data.Attribute(
401            value=ir_data.AttributeValue(expression=_parse_expression("true")),
402            name=ir_data.Word(text="bob")),
403        ir_data.Attribute(
404            value=ir_data.AttributeValue(expression=_parse_expression("false")),
405            name=ir_data.Word(text="bob")),
406        ir_data.Attribute(
407            value=ir_data.AttributeValue(expression=_parse_expression("false")),
408            name=ir_data.Word()),
409    ])
410    self.assertRaises(AssertionError, ir_util.get_attribute, type_def.attribute,
411                      "bob")
412
413  def test_find_object(self):
414    ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr,
415        """{
416          "module": [
417            {
418              "type": [
419                {
420                  "structure": {
421                    "field": [
422                      {
423                        "name": {
424                          "name": { "text": "field" },
425                          "canonical_name": {
426                            "module_file": "test.emb",
427                            "object_path": [ "Foo", "field" ]
428                          }
429                        }
430                      }
431                    ]
432                  },
433                  "name": {
434                    "name": { "text": "Foo" },
435                    "canonical_name": {
436                      "module_file": "test.emb",
437                      "object_path": [ "Foo" ]
438                    }
439                  },
440                  "runtime_parameter": [
441                    {
442                      "name": {
443                        "name": { "text": "parameter" },
444                        "canonical_name": {
445                          "module_file": "test.emb",
446                          "object_path": [ "Foo", "parameter" ]
447                        }
448                      }
449                    }
450                  ]
451                },
452                {
453                  "enumeration": {
454                    "value": [
455                      {
456                        "name": {
457                          "name": { "text": "QUX" },
458                          "canonical_name": {
459                            "module_file": "test.emb",
460                            "object_path": [ "Bar", "QUX" ]
461                          }
462                        }
463                      }
464                    ]
465                  },
466                  "name": {
467                    "name": { "text": "Bar" },
468                    "canonical_name": {
469                      "module_file": "test.emb",
470                      "object_path": [ "Bar" ]
471                    }
472                  }
473                }
474              ],
475              "source_file_name": "test.emb"
476            },
477            {
478              "type": [
479                {
480                  "external": {},
481                  "name": {
482                    "name": { "text": "UInt" },
483                    "canonical_name": {
484                      "module_file": "",
485                      "object_path": [ "UInt" ]
486                    }
487                  }
488                }
489              ],
490              "source_file_name": ""
491            }
492          ]
493        }""")
494
495    # Test that find_object works with any of its four "name" types.
496    canonical_name_of_foo = ir_data.CanonicalName(module_file="test.emb",
497                                                 object_path=["Foo"])
498    self.assertEqual(ir.module[0].type[0], ir_util.find_object(
499        ir_data.Reference(canonical_name=canonical_name_of_foo), ir))
500    self.assertEqual(ir.module[0].type[0], ir_util.find_object(
501        ir_data.NameDefinition(canonical_name=canonical_name_of_foo), ir))
502    self.assertEqual(ir.module[0].type[0],
503                     ir_util.find_object(canonical_name_of_foo, ir))
504    self.assertEqual(ir.module[0].type[0],
505                     ir_util.find_object(("test.emb", "Foo"), ir))
506
507    # Test that find_object works with objects other than structs.
508    self.assertEqual(ir.module[0].type[1],
509                     ir_util.find_object(("test.emb", "Bar"), ir))
510    self.assertEqual(ir.module[1].type[0],
511                     ir_util.find_object(("", "UInt"), ir))
512    self.assertEqual(ir.module[0].type[0].structure.field[0],
513                     ir_util.find_object(("test.emb", "Foo", "field"), ir))
514    self.assertEqual(ir.module[0].type[0].runtime_parameter[0],
515                     ir_util.find_object(("test.emb", "Foo", "parameter"), ir))
516    self.assertEqual(ir.module[0].type[1].enumeration.value[0],
517                     ir_util.find_object(("test.emb", "Bar", "QUX"), ir))
518    self.assertEqual(ir.module[0], ir_util.find_object(("test.emb",), ir))
519    self.assertEqual(ir.module[1], ir_util.find_object(("",), ir))
520
521    # Test searching for non-present objects.
522    self.assertIsNone(ir_util.find_object_or_none(("not_test.emb",), ir))
523    self.assertIsNone(ir_util.find_object_or_none(("test.emb", "NotFoo"), ir))
524    self.assertIsNone(
525        ir_util.find_object_or_none(("test.emb", "Foo", "not_field"), ir))
526    self.assertIsNone(
527        ir_util.find_object_or_none(("test.emb", "Foo", "field", "no_subfield"),
528                                    ir))
529    self.assertIsNone(
530        ir_util.find_object_or_none(("test.emb", "Bar", "NOT_QUX"), ir))
531    self.assertIsNone(
532        ir_util.find_object_or_none(("test.emb", "Bar", "QUX", "no_subenum"),
533                                    ir))
534
535    # Test that find_parent_object works with any of its four "name" types.
536    self.assertEqual(ir.module[0], ir_util.find_parent_object(
537        ir_data.Reference(canonical_name=canonical_name_of_foo), ir))
538    self.assertEqual(ir.module[0], ir_util.find_parent_object(
539        ir_data.NameDefinition(canonical_name=canonical_name_of_foo), ir))
540    self.assertEqual(ir.module[0],
541                     ir_util.find_parent_object(canonical_name_of_foo, ir))
542    self.assertEqual(ir.module[0],
543                     ir_util.find_parent_object(("test.emb", "Foo"), ir))
544
545    # Test that find_parent_object works with objects other than structs.
546    self.assertEqual(ir.module[0],
547                     ir_util.find_parent_object(("test.emb", "Bar"), ir))
548    self.assertEqual(ir.module[1], ir_util.find_parent_object(("", "UInt"), ir))
549    self.assertEqual(ir.module[0].type[0],
550                     ir_util.find_parent_object(("test.emb", "Foo", "field"),
551                                                ir))
552    self.assertEqual(ir.module[0].type[1],
553                     ir_util.find_parent_object(("test.emb", "Bar", "QUX"), ir))
554
555  def test_hashable_form_of_reference(self):
556    self.assertEqual(
557        ("t.emb", "Foo", "Bar"),
558        ir_util.hashable_form_of_reference(ir_data.Reference(
559            canonical_name=ir_data.CanonicalName(module_file="t.emb",
560                                                object_path=["Foo", "Bar"]))))
561    self.assertEqual(
562        ("t.emb", "Foo", "Bar"),
563        ir_util.hashable_form_of_reference(ir_data.NameDefinition(
564            canonical_name=ir_data.CanonicalName(module_file="t.emb",
565                                                object_path=["Foo", "Bar"]))))
566
567  def test_get_base_type(self):
568    array_type_ir = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
569        """{
570          "array_type": {
571            "element_count": { "constant": { "value": "20" } },
572            "base_type": {
573              "array_type": {
574                "element_count": { "constant": { "value": "10" } },
575                "base_type": {
576                  "atomic_type": {
577                    "reference": { },
578                    "source_location": { "start": { "line": 5 } }
579                  }
580                },
581                "source_location": { "start": { "line": 4 } }
582              }
583            },
584            "source_location": { "start": { "line": 3 } }
585          }
586        }""")
587    base_type_ir = array_type_ir.array_type.base_type.array_type.base_type
588    self.assertEqual(base_type_ir, ir_util.get_base_type(array_type_ir))
589    self.assertEqual(base_type_ir, ir_util.get_base_type(
590        array_type_ir.array_type.base_type))
591    self.assertEqual(base_type_ir, ir_util.get_base_type(base_type_ir))
592
593  def test_size_of_type_in_bits(self):
594    ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr,
595        """{
596          "module": [{
597            "type": [{
598              "name": {
599                "name": { "text": "Baz" },
600                "canonical_name": {
601                  "module_file": "s.emb",
602                  "object_path": ["Baz"]
603                }
604              }
605            }],
606            "source_file_name": "s.emb"
607          },
608          {
609            "type": [{
610              "name": {
611                "name": { "text": "UInt" },
612                "canonical_name": {
613                  "module_file": "",
614                  "object_path": ["UInt"]
615                }
616              }
617            },
618            {
619              "name": {
620                "name": { "text": "Byte" },
621                "canonical_name": {
622                  "module_file": "",
623                  "object_path": ["Byte"]
624                }
625              },
626              "attribute": [{
627                "name": { "text": "fixed_size_in_bits" },
628                "value": {
629                  "expression": {
630                    "constant": { "value": "8" },
631                    "type": {
632                      "integer": { "modular_value": "8", "modulus": "infinity" }
633                    }
634                  }
635                }
636              }]
637            }],
638            "source_file_name": ""
639          }]
640        }""")
641
642    fixed_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
643        """{
644          "atomic_type": {
645            "reference": {
646              "canonical_name": { "module_file": "", "object_path": ["Byte"] }
647             }
648          }
649        }""")
650    self.assertEqual(8, ir_util.fixed_size_of_type_in_bits(fixed_size_type, ir))
651
652    explicit_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
653        """{
654          "atomic_type": {
655            "reference": {
656              "canonical_name": { "module_file": "", "object_path": ["UInt"] }
657            }
658          },
659          "size_in_bits": {
660            "constant": { "value": "32" },
661            "type": {
662              "integer": { "modular_value": "32", "modulus": "infinity" }
663            }
664          }
665        }""")
666    self.assertEqual(32,
667                     ir_util.fixed_size_of_type_in_bits(explicit_size_type, ir))
668
669    fixed_size_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
670        """{
671          "array_type": {
672            "base_type": {
673              "atomic_type": {
674                "reference": {
675                  "canonical_name": { "module_file": "", "object_path": ["Byte"] }
676                }
677              }
678            },
679            "element_count": {
680              "constant": { "value": "5" },
681              "type": {
682                "integer": { "modular_value": "5", "modulus": "infinity" }
683              }
684            }
685          }
686        }""")
687    self.assertEqual(40,
688                     ir_util.fixed_size_of_type_in_bits(fixed_size_array, ir))
689
690    fixed_size_2d_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
691        """{
692          "array_type": {
693            "base_type": {
694              "array_type": {
695                "base_type": {
696                  "atomic_type": {
697                    "reference": {
698                      "canonical_name": {
699                        "module_file": "",
700                        "object_path": ["Byte"]
701                      }
702                    }
703                  }
704                },
705                "element_count": {
706                  "constant": { "value": "5" },
707                  "type": {
708                    "integer": { "modular_value": "5", "modulus": "infinity" }
709                  }
710                }
711              }
712            },
713            "element_count": {
714              "constant": { "value": "2" },
715              "type": {
716                "integer": { "modular_value": "2", "modulus": "infinity" }
717              }
718            }
719          }
720        }""")
721    self.assertEqual(
722        80, ir_util.fixed_size_of_type_in_bits(fixed_size_2d_array, ir))
723
724    automatic_size_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
725        """{
726          "array_type": {
727            "base_type": {
728              "array_type": {
729                "base_type": {
730                  "atomic_type": {
731                    "reference": {
732                      "canonical_name": {
733                        "module_file": "",
734                        "object_path": ["Byte"]
735                      }
736                    }
737                  }
738                },
739                "element_count": {
740                  "constant": { "value": "5" },
741                  "type": {
742                    "integer": { "modular_value": "5", "modulus": "infinity" }
743                  }
744                }
745              }
746            },
747            "automatic": { }
748          }
749      }""")
750    self.assertIsNone(
751        ir_util.fixed_size_of_type_in_bits(automatic_size_array, ir))
752
753    variable_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
754        """{
755          "atomic_type": {
756            "reference": {
757              "canonical_name": { "module_file": "", "object_path": ["UInt"] }
758            }
759          }
760        }""")
761    self.assertIsNone(
762        ir_util.fixed_size_of_type_in_bits(variable_size_type, ir))
763
764    no_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type,
765        """{
766          "atomic_type": {
767            "reference": {
768              "canonical_name": {
769                "module_file": "s.emb",
770                "object_path": ["Baz"]
771              }
772            }
773          }
774        }""")
775    self.assertIsNone(ir_util.fixed_size_of_type_in_bits(no_size_type, ir))
776
777  def test_field_is_virtual(self):
778    self.assertTrue(ir_util.field_is_virtual(ir_data.Field()))
779
780  def test_field_is_not_virtual(self):
781    self.assertFalse(ir_util.field_is_virtual(
782        ir_data.Field(location=ir_data.FieldLocation())))
783
784  def test_field_is_read_only(self):
785    self.assertTrue(ir_util.field_is_read_only(ir_data.Field(
786        write_method=ir_data.WriteMethod(read_only=True))))
787
788  def test_field_is_not_read_only(self):
789    self.assertFalse(ir_util.field_is_read_only(
790        ir_data.Field(location=ir_data.FieldLocation())))
791    self.assertFalse(ir_util.field_is_read_only(ir_data.Field(
792        write_method=ir_data.WriteMethod())))
793
794
795if __name__ == "__main__":
796  unittest.main()
797