| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import imp | 5 import imp |
| 6 import os.path | 6 import os.path |
| 7 import sys | 7 import sys |
| 8 import unittest | 8 import unittest |
| 9 | 9 |
| 10 def _GetDirAbove(dirname): | 10 def _GetDirAbove(dirname): |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 | 28 |
| 29 class ParserTest(unittest.TestCase): | 29 class ParserTest(unittest.TestCase): |
| 30 """Tests |parser.Parse()|.""" | 30 """Tests |parser.Parse()|.""" |
| 31 | 31 |
| 32 def testTrivialValidSource(self): | 32 def testTrivialValidSource(self): |
| 33 """Tests a trivial, but valid, .mojom source.""" | 33 """Tests a trivial, but valid, .mojom source.""" |
| 34 | 34 |
| 35 source = """\ | 35 source = """\ |
| 36 // This is a comment. | 36 // This is a comment. |
| 37 | 37 |
| 38 module my_module { | 38 module my_module; |
| 39 } | |
| 40 """ | 39 """ |
| 41 expected = ast.Mojom( | 40 expected = ast.Mojom( |
| 42 ast.Module(('IDENTIFIER', 'my_module'), None), | 41 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 43 ast.ImportList(), | 42 ast.ImportList(), |
| 44 []) | 43 []) |
| 45 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 44 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 46 | 45 |
| 47 def testSourceWithCrLfs(self): | 46 def testSourceWithCrLfs(self): |
| 48 """Tests a .mojom source with CR-LFs instead of LFs.""" | 47 """Tests a .mojom source with CR-LFs instead of LFs.""" |
| 49 | 48 |
| 50 source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n" | 49 source = "// This is a comment.\r\n\r\nmodule my_module;\r\n" |
| 51 expected = ast.Mojom( | 50 expected = ast.Mojom( |
| 52 ast.Module(('IDENTIFIER', 'my_module'), None), | 51 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 53 ast.ImportList(), | 52 ast.ImportList(), |
| 54 []) | 53 []) |
| 55 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 54 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 56 | 55 |
| 57 def testUnexpectedEOF(self): | 56 def testUnexpectedEOF(self): |
| 58 """Tests a "truncated" .mojom source.""" | 57 """Tests a "truncated" .mojom source.""" |
| 59 | 58 |
| 60 source = """\ | 59 source = """\ |
| 61 // This is a comment. | 60 // This is a comment. |
| 62 | 61 |
| 63 module my_module { | 62 module my_module |
| 64 """ | 63 """ |
| 65 with self.assertRaisesRegexp( | 64 with self.assertRaisesRegexp( |
| 66 parser.ParseError, | 65 parser.ParseError, |
| 67 r"^my_file\.mojom: Error: Unexpected end of file$"): | 66 r"^my_file\.mojom: Error: Unexpected end of file$"): |
| 68 parser.Parse(source, "my_file.mojom") | 67 parser.Parse(source, "my_file.mojom") |
| 69 | 68 |
| 70 def testCommentLineNumbers(self): | 69 def testCommentLineNumbers(self): |
| 71 """Tests that line numbers are correctly tracked when comments are | 70 """Tests that line numbers are correctly tracked when comments are |
| 72 present.""" | 71 present.""" |
| 73 | 72 |
| 74 source1 = """\ | 73 source1 = """\ |
| 75 // Isolated C++-style comments. | 74 // Isolated C++-style comments. |
| 76 | 75 |
| 77 // Foo. | 76 // Foo. |
| 78 asdf1 | 77 asdf1 |
| 79 """ | 78 """ |
| 80 with self.assertRaisesRegexp( | 79 with self.assertRaisesRegexp( |
| 81 parser.ParseError, | 80 parser.ParseError, |
| 82 r"^my_file\.mojom:4: Error: Unexpected 'asdf1':\n *asdf1$"): | 81 r"^my_file\.mojom:4: Error: Unexpected 'asdf1':\n *asdf1$"): |
| 83 parser.Parse(source1, "my_file.mojom") | 82 parser.Parse(source1, "my_file.mojom") |
| 84 | 83 |
| 85 source2 = """\ | 84 source2 = """\ |
| 86 // Consecutive C++-style comments. | 85 // Consecutive C++-style comments. |
| 87 // Foo. | 86 // Foo. |
| 88 // Bar. | 87 // Bar. |
| 89 | 88 |
| 90 struct Yada { // Baz. | 89 struct Yada { // Baz. |
| 91 // Quux. | 90 // Quux. |
| 92 int32 x; | 91 int32 x; |
| 93 }; | 92 }; |
| 94 | 93 |
| 95 asdf2 | 94 asdf2 |
| 96 """ | 95 """ |
| 97 with self.assertRaisesRegexp( | 96 with self.assertRaisesRegexp( |
| 98 parser.ParseError, | 97 parser.ParseError, |
| 99 r"^my_file\.mojom:10: Error: Unexpected 'asdf2':\n *asdf2$"): | 98 r"^my_file\.mojom:10: Error: Unexpected 'asdf2':\n *asdf2$"): |
| 100 parser.Parse(source2, "my_file.mojom") | 99 parser.Parse(source2, "my_file.mojom") |
| 101 | 100 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 126 with self.assertRaisesRegexp( | 125 with self.assertRaisesRegexp( |
| 127 parser.ParseError, | 126 parser.ParseError, |
| 128 r"^my_file\.mojom:10: Error: Unexpected 'asdf4':\n *asdf4$"): | 127 r"^my_file\.mojom:10: Error: Unexpected 'asdf4':\n *asdf4$"): |
| 129 parser.Parse(source4, "my_file.mojom") | 128 parser.Parse(source4, "my_file.mojom") |
| 130 | 129 |
| 131 | 130 |
| 132 def testSimpleStruct(self): | 131 def testSimpleStruct(self): |
| 133 """Tests a simple .mojom source that just defines a struct.""" | 132 """Tests a simple .mojom source that just defines a struct.""" |
| 134 | 133 |
| 135 source = """\ | 134 source = """\ |
| 136 module my_module { | 135 module my_module; |
| 137 | 136 |
| 138 struct MyStruct { | 137 struct MyStruct { |
| 139 int32 a; | 138 int32 a; |
| 140 double b; | 139 double b; |
| 141 }; | 140 }; |
| 142 | |
| 143 } // module my_module | |
| 144 """ | 141 """ |
| 145 expected = ast.Mojom( | 142 expected = ast.Mojom( |
| 146 ast.Module(('IDENTIFIER', 'my_module'), None), | 143 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 147 ast.ImportList(), | 144 ast.ImportList(), |
| 148 [ast.Struct( | 145 [ast.Struct( |
| 149 'MyStruct', | 146 'MyStruct', |
| 150 None, | 147 None, |
| 151 ast.StructBody( | 148 ast.StructBody( |
| 152 [ast.StructField('a', None, 'int32', None), | 149 [ast.StructField('a', None, 'int32', None), |
| 153 ast.StructField('b', None, 'double', None)]))]) | 150 ast.StructField('b', None, 'double', None)]))]) |
| 154 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 151 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 155 | 152 |
| 156 def testSimpleStructWithoutModule(self): | 153 def testSimpleStructWithoutModule(self): |
| 157 """Tests a simple struct without an enclosing module.""" | 154 """Tests a simple struct without an explict module statement.""" |
| 158 | 155 |
| 159 source = """\ | 156 source = """\ |
| 160 struct MyStruct { | 157 struct MyStruct { |
| 161 int32 a; | 158 int32 a; |
| 162 double b; | 159 double b; |
| 163 }; | 160 }; |
| 164 """ | 161 """ |
| 165 expected = ast.Mojom( | 162 expected = ast.Mojom( |
| 166 None, | 163 None, |
| 167 ast.ImportList(), | 164 ast.ImportList(), |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 parser.ParseError, | 234 parser.ParseError, |
| 238 r"^my_file\.mojom:2: Error: Unexpected 'interface':\n" | 235 r"^my_file\.mojom:2: Error: Unexpected 'interface':\n" |
| 239 r" *interface MyInterface {$"): | 236 r" *interface MyInterface {$"): |
| 240 parser.Parse(source3, "my_file.mojom") | 237 parser.Parse(source3, "my_file.mojom") |
| 241 | 238 |
| 242 def testMissingModuleName(self): | 239 def testMissingModuleName(self): |
| 243 """Tests an (invalid) .mojom with a missing module name.""" | 240 """Tests an (invalid) .mojom with a missing module name.""" |
| 244 | 241 |
| 245 source1 = """\ | 242 source1 = """\ |
| 246 // Missing module name. | 243 // Missing module name. |
| 247 module { | 244 module ; |
| 248 struct MyStruct { | 245 struct MyStruct { |
| 249 int32 a; | 246 int32 a; |
| 250 }; | 247 }; |
| 251 } | |
| 252 """ | 248 """ |
| 253 with self.assertRaisesRegexp( | 249 with self.assertRaisesRegexp( |
| 254 parser.ParseError, | 250 parser.ParseError, |
| 255 r"^my_file\.mojom:2: Error: Unexpected '{':\n *module {$"): | 251 r"^my_file\.mojom:2: Error: Unexpected ';':\n *module ;$"): |
| 256 parser.Parse(source1, "my_file.mojom") | 252 parser.Parse(source1, "my_file.mojom") |
| 257 | 253 |
| 258 # Another similar case, but make sure that line-number tracking/reporting | 254 # Another similar case, but make sure that line-number tracking/reporting |
| 259 # is correct. | 255 # is correct. |
| 260 source2 = """\ | 256 source2 = """\ |
| 261 module | 257 module |
| 262 // This line intentionally left unblank. | 258 // This line intentionally left unblank. |
| 263 | 259 |
| 264 { | 260 struct MyStruct { |
| 265 } | 261 int32 a; |
| 262 }; |
| 266 """ | 263 """ |
| 267 with self.assertRaisesRegexp( | 264 with self.assertRaisesRegexp( |
| 268 parser.ParseError, | 265 parser.ParseError, |
| 269 r"^my_file\.mojom:4: Error: Unexpected '{':\n *{$"): | 266 r"^my_file\.mojom:4: Error: Unexpected 'struct':\n" |
| 267 r" *struct MyStruct {$"): |
| 270 parser.Parse(source2, "my_file.mojom") | 268 parser.Parse(source2, "my_file.mojom") |
| 271 | 269 |
| 270 def testMultipleModuleStatements(self): |
| 271 """Tests an (invalid) .mojom with multiple module statements.""" |
| 272 |
| 273 source = """\ |
| 274 module foo; |
| 275 module bar; |
| 276 """ |
| 277 with self.assertRaisesRegexp( |
| 278 parser.ParseError, |
| 279 r"^my_file\.mojom:2: Error: Multiple \"module\" statements not " |
| 280 r"allowed:\n *module bar;$"): |
| 281 parser.Parse(source, "my_file.mojom") |
| 282 |
| 283 def testModuleStatementAfterImport(self): |
| 284 """Tests an (invalid) .mojom with a module statement after an import.""" |
| 285 |
| 286 source = """\ |
| 287 import "foo.mojom"; |
| 288 module foo; |
| 289 """ |
| 290 with self.assertRaisesRegexp( |
| 291 parser.ParseError, |
| 292 r"^my_file\.mojom:2: Error: \"module\" statements must precede imports " |
| 293 r"and definitions:\n *module foo;$"): |
| 294 parser.Parse(source, "my_file.mojom") |
| 295 |
| 296 def testModuleStatementAfterDefinition(self): |
| 297 """Tests an (invalid) .mojom with a module statement after a definition.""" |
| 298 |
| 299 source = """\ |
| 300 struct MyStruct { |
| 301 int32 a; |
| 302 }; |
| 303 module foo; |
| 304 """ |
| 305 with self.assertRaisesRegexp( |
| 306 parser.ParseError, |
| 307 r"^my_file\.mojom:4: Error: \"module\" statements must precede imports " |
| 308 r"and definitions:\n *module foo;$"): |
| 309 parser.Parse(source, "my_file.mojom") |
| 310 |
| 311 def testImportStatementAfterDefinition(self): |
| 312 """Tests an (invalid) .mojom with an import statement after a definition.""" |
| 313 |
| 314 source = """\ |
| 315 struct MyStruct { |
| 316 int32 a; |
| 317 }; |
| 318 import "foo.mojom"; |
| 319 """ |
| 320 with self.assertRaisesRegexp( |
| 321 parser.ParseError, |
| 322 r"^my_file\.mojom:4: Error: \"import\" statements must precede " |
| 323 r"definitions:\n *import \"foo.mojom\";$"): |
| 324 parser.Parse(source, "my_file.mojom") |
| 325 |
| 272 def testEnums(self): | 326 def testEnums(self): |
| 273 """Tests that enum statements are correctly parsed.""" | 327 """Tests that enum statements are correctly parsed.""" |
| 274 | 328 |
| 275 source = """\ | 329 source = """\ |
| 276 module my_module { | 330 module my_module; |
| 277 enum MyEnum1 { VALUE1, VALUE2 }; // No trailing comma. | 331 enum MyEnum1 { VALUE1, VALUE2 }; // No trailing comma. |
| 278 enum MyEnum2 { | 332 enum MyEnum2 { |
| 279 VALUE1 = -1, | 333 VALUE1 = -1, |
| 280 VALUE2 = 0, | 334 VALUE2 = 0, |
| 281 VALUE3 = + 987, // Check that space is allowed. | 335 VALUE3 = + 987, // Check that space is allowed. |
| 282 VALUE4 = 0xAF12, | 336 VALUE4 = 0xAF12, |
| 283 VALUE5 = -0x09bcd, | 337 VALUE5 = -0x09bcd, |
| 284 VALUE6 = VALUE5, | 338 VALUE6 = VALUE5, |
| 285 VALUE7, // Leave trailing comma. | 339 VALUE7, // Leave trailing comma. |
| 286 }; | 340 }; |
| 287 } // my_module | |
| 288 """ | 341 """ |
| 289 expected = ast.Mojom( | 342 expected = ast.Mojom( |
| 290 ast.Module(('IDENTIFIER', 'my_module'), None), | 343 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 291 ast.ImportList(), | 344 ast.ImportList(), |
| 292 [ast.Enum( | 345 [ast.Enum( |
| 293 'MyEnum1', | 346 'MyEnum1', |
| 294 ast.EnumValueList([ast.EnumValue('VALUE1', None), | 347 ast.EnumValueList([ast.EnumValue('VALUE1', None), |
| 295 ast.EnumValue('VALUE2', None)])), | 348 ast.EnumValue('VALUE2', None)])), |
| 296 ast.Enum( | 349 ast.Enum( |
| 297 'MyEnum2', | 350 'MyEnum2', |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 with self.assertRaisesRegexp( | 385 with self.assertRaisesRegexp( |
| 333 parser.ParseError, | 386 parser.ParseError, |
| 334 r"^my_file\.mojom:1: Error: Unexpected 'true':\n" | 387 r"^my_file\.mojom:1: Error: Unexpected 'true':\n" |
| 335 r"enum MyEnum { VALUE = true };$"): | 388 r"enum MyEnum { VALUE = true };$"): |
| 336 parser.Parse(source2, "my_file.mojom") | 389 parser.Parse(source2, "my_file.mojom") |
| 337 | 390 |
| 338 def testConsts(self): | 391 def testConsts(self): |
| 339 """Tests some constants and struct members initialized with them.""" | 392 """Tests some constants and struct members initialized with them.""" |
| 340 | 393 |
| 341 source = """\ | 394 source = """\ |
| 342 module my_module { | 395 module my_module; |
| 343 | 396 |
| 344 struct MyStruct { | 397 struct MyStruct { |
| 345 const int8 kNumber = -1; | 398 const int8 kNumber = -1; |
| 346 int8 number@0 = kNumber; | 399 int8 number@0 = kNumber; |
| 347 }; | 400 }; |
| 348 | |
| 349 } // my_module | |
| 350 """ | 401 """ |
| 351 expected = ast.Mojom( | 402 expected = ast.Mojom( |
| 352 ast.Module(('IDENTIFIER', 'my_module'), None), | 403 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 353 ast.ImportList(), | 404 ast.ImportList(), |
| 354 [ast.Struct( | 405 [ast.Struct( |
| 355 'MyStruct', None, | 406 'MyStruct', None, |
| 356 ast.StructBody( | 407 ast.StructBody( |
| 357 [ast.Const('kNumber', 'int8', '-1'), | 408 [ast.Const('kNumber', 'int8', '-1'), |
| 358 ast.StructField('number', ast.Ordinal(0), 'int8', | 409 ast.StructField('number', ast.Ordinal(0), 'int8', |
| 359 ('IDENTIFIER', 'kNumber'))]))]) | 410 ('IDENTIFIER', 'kNumber'))]))]) |
| 360 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 411 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 361 | 412 |
| 362 def testNoConditionals(self): | 413 def testNoConditionals(self): |
| 363 """Tests that ?: is not allowed.""" | 414 """Tests that ?: is not allowed.""" |
| 364 | 415 |
| 365 source = """\ | 416 source = """\ |
| 366 module my_module { | 417 module my_module; |
| 367 | 418 |
| 368 enum MyEnum { | 419 enum MyEnum { |
| 369 MY_ENUM_1 = 1 ? 2 : 3 | 420 MY_ENUM_1 = 1 ? 2 : 3 |
| 370 }; | 421 }; |
| 371 | |
| 372 } // my_module | |
| 373 """ | 422 """ |
| 374 with self.assertRaisesRegexp( | 423 with self.assertRaisesRegexp( |
| 375 parser.ParseError, | 424 parser.ParseError, |
| 376 r"^my_file\.mojom:4: Error: Unexpected '\?':\n" | 425 r"^my_file\.mojom:4: Error: Unexpected '\?':\n" |
| 377 r" *MY_ENUM_1 = 1 \? 2 : 3$"): | 426 r" *MY_ENUM_1 = 1 \? 2 : 3$"): |
| 378 parser.Parse(source, "my_file.mojom") | 427 parser.Parse(source, "my_file.mojom") |
| 379 | 428 |
| 380 def testSimpleOrdinals(self): | 429 def testSimpleOrdinals(self): |
| 381 """Tests that (valid) ordinal values are scanned correctly.""" | 430 """Tests that (valid) ordinal values are scanned correctly.""" |
| 382 | 431 |
| 383 source = """\ | 432 source = """\ |
| 384 module my_module { | 433 module my_module; |
| 385 | 434 |
| 386 // This isn't actually valid .mojom, but the problem (missing ordinals) | 435 // This isn't actually valid .mojom, but the problem (missing ordinals) |
| 387 // should be handled at a different level. | 436 // should be handled at a different level. |
| 388 struct MyStruct { | 437 struct MyStruct { |
| 389 int32 a0@0; | 438 int32 a0@0; |
| 390 int32 a1@1; | 439 int32 a1@1; |
| 391 int32 a2@2; | 440 int32 a2@2; |
| 392 int32 a9@9; | 441 int32 a9@9; |
| 393 int32 a10 @10; | 442 int32 a10 @10; |
| 394 int32 a11 @11; | 443 int32 a11 @11; |
| 395 int32 a29 @29; | 444 int32 a29 @29; |
| 396 int32 a1234567890 @1234567890; | 445 int32 a1234567890 @1234567890; |
| 397 }; | 446 }; |
| 398 | |
| 399 } // module my_module | |
| 400 """ | 447 """ |
| 401 expected = ast.Mojom( | 448 expected = ast.Mojom( |
| 402 ast.Module(('IDENTIFIER', 'my_module'), None), | 449 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 403 ast.ImportList(), | 450 ast.ImportList(), |
| 404 [ast.Struct( | 451 [ast.Struct( |
| 405 'MyStruct', | 452 'MyStruct', |
| 406 None, | 453 None, |
| 407 ast.StructBody( | 454 ast.StructBody( |
| 408 [ast.StructField('a0', ast.Ordinal(0), 'int32', None), | 455 [ast.StructField('a0', ast.Ordinal(0), 'int32', None), |
| 409 ast.StructField('a1', ast.Ordinal(1), 'int32', None), | 456 ast.StructField('a1', ast.Ordinal(1), 'int32', None), |
| 410 ast.StructField('a2', ast.Ordinal(2), 'int32', None), | 457 ast.StructField('a2', ast.Ordinal(2), 'int32', None), |
| 411 ast.StructField('a9', ast.Ordinal(9), 'int32', None), | 458 ast.StructField('a9', ast.Ordinal(9), 'int32', None), |
| 412 ast.StructField('a10', ast.Ordinal(10), 'int32', None), | 459 ast.StructField('a10', ast.Ordinal(10), 'int32', None), |
| 413 ast.StructField('a11', ast.Ordinal(11), 'int32', None), | 460 ast.StructField('a11', ast.Ordinal(11), 'int32', None), |
| 414 ast.StructField('a29', ast.Ordinal(29), 'int32', None), | 461 ast.StructField('a29', ast.Ordinal(29), 'int32', None), |
| 415 ast.StructField('a1234567890', ast.Ordinal(1234567890), | 462 ast.StructField('a1234567890', ast.Ordinal(1234567890), |
| 416 'int32', None)]))]) | 463 'int32', None)]))]) |
| 417 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 464 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 418 | 465 |
| 419 def testInvalidOrdinals(self): | 466 def testInvalidOrdinals(self): |
| 420 """Tests that (lexically) invalid ordinals are correctly detected.""" | 467 """Tests that (lexically) invalid ordinals are correctly detected.""" |
| 421 | 468 |
| 422 source1 = """\ | 469 source1 = """\ |
| 423 module my_module { | 470 module my_module; |
| 424 | 471 |
| 425 struct MyStruct { | 472 struct MyStruct { |
| 426 int32 a_missing@; | 473 int32 a_missing@; |
| 427 }; | 474 }; |
| 428 | |
| 429 } // module my_module | |
| 430 """ | 475 """ |
| 431 with self.assertRaisesRegexp( | 476 with self.assertRaisesRegexp( |
| 432 lexer.LexError, | 477 lexer.LexError, |
| 433 r"^my_file\.mojom:4: Error: Missing ordinal value$"): | 478 r"^my_file\.mojom:4: Error: Missing ordinal value$"): |
| 434 parser.Parse(source1, "my_file.mojom") | 479 parser.Parse(source1, "my_file.mojom") |
| 435 | 480 |
| 436 source2 = """\ | 481 source2 = """\ |
| 437 module my_module { | 482 module my_module; |
| 438 | 483 |
| 439 struct MyStruct { | 484 struct MyStruct { |
| 440 int32 a_octal@01; | 485 int32 a_octal@01; |
| 441 }; | 486 }; |
| 442 | |
| 443 } // module my_module | |
| 444 """ | 487 """ |
| 445 with self.assertRaisesRegexp( | 488 with self.assertRaisesRegexp( |
| 446 lexer.LexError, | 489 lexer.LexError, |
| 447 r"^my_file\.mojom:4: Error: " | 490 r"^my_file\.mojom:4: Error: " |
| 448 r"Octal and hexadecimal ordinal values not allowed$"): | 491 r"Octal and hexadecimal ordinal values not allowed$"): |
| 449 parser.Parse(source2, "my_file.mojom") | 492 parser.Parse(source2, "my_file.mojom") |
| 450 | 493 |
| 451 source3 = """\ | 494 source3 = """\ |
| 452 module my_module { struct MyStruct { int32 a_invalid_octal@08; }; } | 495 module my_module; struct MyStruct { int32 a_invalid_octal@08; }; |
| 453 """ | 496 """ |
| 454 with self.assertRaisesRegexp( | 497 with self.assertRaisesRegexp( |
| 455 lexer.LexError, | 498 lexer.LexError, |
| 456 r"^my_file\.mojom:1: Error: " | 499 r"^my_file\.mojom:1: Error: " |
| 457 r"Octal and hexadecimal ordinal values not allowed$"): | 500 r"Octal and hexadecimal ordinal values not allowed$"): |
| 458 parser.Parse(source3, "my_file.mojom") | 501 parser.Parse(source3, "my_file.mojom") |
| 459 | 502 |
| 460 source4 = "module my_module { struct MyStruct { int32 a_hex@0x1aB9; }; }" | 503 source4 = "module my_module; struct MyStruct { int32 a_hex@0x1aB9; };" |
| 461 with self.assertRaisesRegexp( | 504 with self.assertRaisesRegexp( |
| 462 lexer.LexError, | 505 lexer.LexError, |
| 463 r"^my_file\.mojom:1: Error: " | 506 r"^my_file\.mojom:1: Error: " |
| 464 r"Octal and hexadecimal ordinal values not allowed$"): | 507 r"Octal and hexadecimal ordinal values not allowed$"): |
| 465 parser.Parse(source4, "my_file.mojom") | 508 parser.Parse(source4, "my_file.mojom") |
| 466 | 509 |
| 467 source5 = "module my_module { struct MyStruct { int32 a_hex@0X0; }; }" | 510 source5 = "module my_module; struct MyStruct { int32 a_hex@0X0; };" |
| 468 with self.assertRaisesRegexp( | 511 with self.assertRaisesRegexp( |
| 469 lexer.LexError, | 512 lexer.LexError, |
| 470 r"^my_file\.mojom:1: Error: " | 513 r"^my_file\.mojom:1: Error: " |
| 471 r"Octal and hexadecimal ordinal values not allowed$"): | 514 r"Octal and hexadecimal ordinal values not allowed$"): |
| 472 parser.Parse(source5, "my_file.mojom") | 515 parser.Parse(source5, "my_file.mojom") |
| 473 | 516 |
| 474 source6 = """\ | 517 source6 = """\ |
| 475 struct MyStruct { | 518 struct MyStruct { |
| 476 int32 a_too_big@999999999999; | 519 int32 a_too_big@999999999999; |
| 477 }; | 520 }; |
| 478 """ | 521 """ |
| 479 with self.assertRaisesRegexp( | 522 with self.assertRaisesRegexp( |
| 480 parser.ParseError, | 523 parser.ParseError, |
| 481 r"^my_file\.mojom:2: Error: " | 524 r"^my_file\.mojom:2: Error: " |
| 482 r"Ordinal value 999999999999 too large:\n" | 525 r"Ordinal value 999999999999 too large:\n" |
| 483 r" *int32 a_too_big@999999999999;$"): | 526 r" *int32 a_too_big@999999999999;$"): |
| 484 parser.Parse(source6, "my_file.mojom") | 527 parser.Parse(source6, "my_file.mojom") |
| 485 | 528 |
| 486 def testNestedNamespace(self): | 529 def testNestedNamespace(self): |
| 487 """Tests that "nested" namespaces work.""" | 530 """Tests that "nested" namespaces work.""" |
| 488 | 531 |
| 489 source = """\ | 532 source = """\ |
| 490 module my.mod { | 533 module my.mod; |
| 491 | 534 |
| 492 struct MyStruct { | 535 struct MyStruct { |
| 493 int32 a; | 536 int32 a; |
| 494 }; | 537 }; |
| 495 | |
| 496 } // module my.mod | |
| 497 """ | 538 """ |
| 498 expected = ast.Mojom( | 539 expected = ast.Mojom( |
| 499 ast.Module(('IDENTIFIER', 'my.mod'), None), | 540 ast.Module(('IDENTIFIER', 'my.mod'), None), |
| 500 ast.ImportList(), | 541 ast.ImportList(), |
| 501 [ast.Struct( | 542 [ast.Struct( |
| 502 'MyStruct', | 543 'MyStruct', |
| 503 None, | 544 None, |
| 504 ast.StructBody(ast.StructField('a', None, 'int32', None)))]) | 545 ast.StructBody(ast.StructField('a', None, 'int32', None)))]) |
| 505 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 546 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
| 506 | 547 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 def testInvalidFixedArraySize(self): | 694 def testInvalidFixedArraySize(self): |
| 654 """Tests that invalid fixed array bounds are correctly detected.""" | 695 """Tests that invalid fixed array bounds are correctly detected.""" |
| 655 | 696 |
| 656 source1 = """\ | 697 source1 = """\ |
| 657 struct MyStruct { | 698 struct MyStruct { |
| 658 array<int32, 0> zero_size_array; | 699 array<int32, 0> zero_size_array; |
| 659 }; | 700 }; |
| 660 """ | 701 """ |
| 661 with self.assertRaisesRegexp( | 702 with self.assertRaisesRegexp( |
| 662 parser.ParseError, | 703 parser.ParseError, |
| 663 r"^my_file\.mojom:2: Error: Fixed array size 0 invalid\n" | 704 r"^my_file\.mojom:2: Error: Fixed array size 0 invalid:\n" |
| 664 r" *array<int32, 0> zero_size_array;$"): | 705 r" *array<int32, 0> zero_size_array;$"): |
| 665 parser.Parse(source1, "my_file.mojom") | 706 parser.Parse(source1, "my_file.mojom") |
| 666 | 707 |
| 667 source2 = """\ | 708 source2 = """\ |
| 668 struct MyStruct { | 709 struct MyStruct { |
| 669 array<int32, 999999999999> too_big_array; | 710 array<int32, 999999999999> too_big_array; |
| 670 }; | 711 }; |
| 671 """ | 712 """ |
| 672 with self.assertRaisesRegexp( | 713 with self.assertRaisesRegexp( |
| 673 parser.ParseError, | 714 parser.ParseError, |
| 674 r"^my_file\.mojom:2: Error: Fixed array size 999999999999 invalid\n" | 715 r"^my_file\.mojom:2: Error: Fixed array size 999999999999 invalid:\n" |
| 675 r" *array<int32, 999999999999> too_big_array;$"): | 716 r" *array<int32, 999999999999> too_big_array;$"): |
| 676 parser.Parse(source2, "my_file.mojom") | 717 parser.Parse(source2, "my_file.mojom") |
| 677 | 718 |
| 678 source3 = """\ | 719 source3 = """\ |
| 679 struct MyStruct { | 720 struct MyStruct { |
| 680 array<int32, abcdefg> not_a_number; | 721 array<int32, abcdefg> not_a_number; |
| 681 }; | 722 }; |
| 682 """ | 723 """ |
| 683 with self.assertRaisesRegexp( | 724 with self.assertRaisesRegexp( |
| 684 parser.ParseError, | 725 parser.ParseError, |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 """ | 1016 """ |
| 976 expected2 = ast.Mojom( | 1017 expected2 = ast.Mojom( |
| 977 None, | 1018 None, |
| 978 ast.ImportList([ast.Import("somedir/my1.mojom"), | 1019 ast.ImportList([ast.Import("somedir/my1.mojom"), |
| 979 ast.Import("somedir/my2.mojom")]), | 1020 ast.Import("somedir/my2.mojom")]), |
| 980 []) | 1021 []) |
| 981 self.assertEquals(parser.Parse(source2, "my_file.mojom"), expected2) | 1022 self.assertEquals(parser.Parse(source2, "my_file.mojom"), expected2) |
| 982 | 1023 |
| 983 # Imports with module statement. | 1024 # Imports with module statement. |
| 984 source3 = """\ | 1025 source3 = """\ |
| 1026 module my_module; |
| 985 import "somedir/my1.mojom"; | 1027 import "somedir/my1.mojom"; |
| 986 import "somedir/my2.mojom"; | 1028 import "somedir/my2.mojom"; |
| 987 module my_module {} | |
| 988 """ | 1029 """ |
| 989 expected3 = ast.Mojom( | 1030 expected3 = ast.Mojom( |
| 990 ast.Module(('IDENTIFIER', 'my_module'), None), | 1031 ast.Module(('IDENTIFIER', 'my_module'), None), |
| 991 ast.ImportList([ast.Import("somedir/my1.mojom"), | 1032 ast.ImportList([ast.Import("somedir/my1.mojom"), |
| 992 ast.Import("somedir/my2.mojom")]), | 1033 ast.Import("somedir/my2.mojom")]), |
| 993 []) | 1034 []) |
| 994 self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3) | 1035 self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3) |
| 995 | 1036 |
| 996 def testInvalidImports(self): | 1037 def testInvalidImports(self): |
| 997 """Tests that invalid import statements are correctly detected.""" | 1038 """Tests that invalid import statements are correctly detected.""" |
| 998 | 1039 |
| 999 source1 = """\ | 1040 source1 = """\ |
| 1000 // Make the error occur on line 2. | 1041 // Make the error occur on line 2. |
| 1001 import invalid | 1042 import invalid |
| 1002 """ | 1043 """ |
| 1003 with self.assertRaisesRegexp( | 1044 with self.assertRaisesRegexp( |
| 1004 parser.ParseError, | 1045 parser.ParseError, |
| 1005 r"^my_file\.mojom:2: Error: Unexpected 'invalid':\n" | 1046 r"^my_file\.mojom:2: Error: Unexpected 'invalid':\n" |
| 1006 r" *import invalid$"): | 1047 r" *import invalid$"): |
| 1007 parser.Parse(source1, "my_file.mojom") | 1048 parser.Parse(source1, "my_file.mojom") |
| 1008 | 1049 |
| 1009 source2 = """\ | 1050 source2 = """\ |
| 1010 import // Missing string. | 1051 import // Missing string. |
| 1011 module {} | 1052 struct MyStruct { |
| 1053 int32 a; |
| 1054 }; |
| 1012 """ | 1055 """ |
| 1013 with self.assertRaisesRegexp( | 1056 with self.assertRaisesRegexp( |
| 1014 parser.ParseError, | 1057 parser.ParseError, |
| 1015 r"^my_file\.mojom:2: Error: Unexpected 'module':\n" | 1058 r"^my_file\.mojom:2: Error: Unexpected 'struct':\n" |
| 1016 r" *module {}$"): | 1059 r" *struct MyStruct {$"): |
| 1017 parser.Parse(source2, "my_file.mojom") | 1060 parser.Parse(source2, "my_file.mojom") |
| 1018 | 1061 |
| 1019 source3 = """\ | 1062 source3 = """\ |
| 1020 import "foo.mojom" // Missing semicolon. | 1063 import "foo.mojom" // Missing semicolon. |
| 1021 module {} | 1064 struct MyStruct { |
| 1065 int32 a; |
| 1066 }; |
| 1022 """ | 1067 """ |
| 1023 with self.assertRaisesRegexp( | 1068 with self.assertRaisesRegexp( |
| 1024 parser.ParseError, | 1069 parser.ParseError, |
| 1025 r"^my_file\.mojom:2: Error: Unexpected 'module':\n" | 1070 r"^my_file\.mojom:2: Error: Unexpected 'struct':\n" |
| 1026 r" *module {}$"): | 1071 r" *struct MyStruct {$"): |
| 1027 parser.Parse(source3, "my_file.mojom") | 1072 parser.Parse(source3, "my_file.mojom") |
| 1028 | 1073 |
| 1029 def testValidNullableTypes(self): | 1074 def testValidNullableTypes(self): |
| 1030 """Tests parsing nullable types.""" | 1075 """Tests parsing nullable types.""" |
| 1031 | 1076 |
| 1032 source = """\ | 1077 source = """\ |
| 1033 struct MyStruct { | 1078 struct MyStruct { |
| 1034 int32? a; // This is actually invalid, but handled at a different | 1079 int32? a; // This is actually invalid, but handled at a different |
| 1035 // level. | 1080 // level. |
| 1036 string? b; | 1081 string? b; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 }; | 1148 }; |
| 1104 """ | 1149 """ |
| 1105 with self.assertRaisesRegexp( | 1150 with self.assertRaisesRegexp( |
| 1106 parser.ParseError, | 1151 parser.ParseError, |
| 1107 r"^my_file\.mojom:2: Error: Unexpected '&':\n" | 1152 r"^my_file\.mojom:2: Error: Unexpected '&':\n" |
| 1108 r" *some_interface\?& a;$"): | 1153 r" *some_interface\?& a;$"): |
| 1109 parser.Parse(source3, "my_file.mojom") | 1154 parser.Parse(source3, "my_file.mojom") |
| 1110 | 1155 |
| 1111 if __name__ == "__main__": | 1156 if __name__ == "__main__": |
| 1112 unittest.main() | 1157 unittest.main() |
| OLD | NEW |