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 |