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