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 # Disable lint check for finding modules: | 10 # Disable lint check for finding modules: |
(...skipping 16 matching lines...) Expand all Loading... |
27 import mojom.parse.ast as ast | 27 import mojom.parse.ast as ast |
28 import mojom.parse.lexer as lexer | 28 import mojom.parse.lexer as lexer |
29 import mojom.parse.parser as parser | 29 import mojom.parse.parser as parser |
30 | 30 |
31 | 31 |
32 class ParserTest(unittest.TestCase): | 32 class ParserTest(unittest.TestCase): |
33 """Tests |parser.Parse()|.""" | 33 """Tests |parser.Parse()|.""" |
34 | 34 |
35 def testTrivialValidSource(self): | 35 def testTrivialValidSource(self): |
36 """Tests a trivial, but valid, .mojom source.""" | 36 """Tests a trivial, but valid, .mojom source.""" |
| 37 |
37 source = """\ | 38 source = """\ |
38 // This is a comment. | 39 // This is a comment. |
39 | 40 |
40 module my_module { | 41 module my_module { |
41 } | 42 } |
42 """ | 43 """ |
43 self.assertEquals(parser.Parse(source, "my_file.mojom"), | 44 self.assertEquals(parser.Parse(source, "my_file.mojom"), |
44 [("MODULE", "my_module", None, None)]) | 45 [("MODULE", "my_module", None, None)]) |
45 | 46 |
46 def testSourceWithCrLfs(self): | 47 def testSourceWithCrLfs(self): |
47 """Tests a .mojom source with CR-LFs instead of LFs.""" | 48 """Tests a .mojom source with CR-LFs instead of LFs.""" |
| 49 |
48 source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n" | 50 source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n" |
49 self.assertEquals(parser.Parse(source, "my_file.mojom"), | 51 self.assertEquals(parser.Parse(source, "my_file.mojom"), |
50 [("MODULE", "my_module", None, None)]) | 52 [("MODULE", "my_module", None, None)]) |
51 | 53 |
52 def testUnexpectedEOF(self): | 54 def testUnexpectedEOF(self): |
53 """Tests a "truncated" .mojom source.""" | 55 """Tests a "truncated" .mojom source.""" |
| 56 |
54 source = """\ | 57 source = """\ |
55 // This is a comment. | 58 // This is a comment. |
56 | 59 |
57 module my_module { | 60 module my_module { |
58 """ | 61 """ |
59 with self.assertRaisesRegexp( | 62 with self.assertRaisesRegexp( |
60 parser.ParseError, | 63 parser.ParseError, |
61 r"^my_file\.mojom: Error: Unexpected end of file$"): | 64 r"^my_file\.mojom: Error: Unexpected end of file$"): |
62 parser.Parse(source, "my_file.mojom") | 65 parser.Parse(source, "my_file.mojom") |
63 | 66 |
64 def testCommentLineNumbers(self): | 67 def testCommentLineNumbers(self): |
65 """Tests that line numbers are correctly tracked when comments are | 68 """Tests that line numbers are correctly tracked when comments are |
66 present.""" | 69 present.""" |
| 70 |
67 source1 = """\ | 71 source1 = """\ |
68 // Isolated C++-style comments. | 72 // Isolated C++-style comments. |
69 | 73 |
70 // Foo. | 74 // Foo. |
71 asdf1 | 75 asdf1 |
72 """ | 76 """ |
73 with self.assertRaisesRegexp( | 77 with self.assertRaisesRegexp( |
74 parser.ParseError, | 78 parser.ParseError, |
75 r"^my_file\.mojom:4: Error: Unexpected 'asdf1':\nasdf1$"): | 79 r"^my_file\.mojom:4: Error: Unexpected 'asdf1':\n *asdf1$"): |
76 parser.Parse(source1, "my_file.mojom") | 80 parser.Parse(source1, "my_file.mojom") |
77 | 81 |
78 source2 = """\ | 82 source2 = """\ |
79 // Consecutive C++-style comments. | 83 // Consecutive C++-style comments. |
80 // Foo. | 84 // Foo. |
81 // Bar. | 85 // Bar. |
82 | 86 |
83 struct Yada { // Baz. | 87 struct Yada { // Baz. |
84 // Quux. | 88 // Quux. |
85 int32 x; | 89 int32 x; |
86 }; | 90 }; |
87 | 91 |
88 asdf2 | 92 asdf2 |
89 """ | 93 """ |
90 with self.assertRaisesRegexp( | 94 with self.assertRaisesRegexp( |
91 parser.ParseError, | 95 parser.ParseError, |
92 r"^my_file\.mojom:10: Error: Unexpected 'asdf2':\nasdf2$"): | 96 r"^my_file\.mojom:10: Error: Unexpected 'asdf2':\n *asdf2$"): |
93 parser.Parse(source2, "my_file.mojom") | 97 parser.Parse(source2, "my_file.mojom") |
94 | 98 |
95 source3 = """\ | 99 source3 = """\ |
96 /* Single-line C-style comments. */ | 100 /* Single-line C-style comments. */ |
97 /* Foobar. */ | 101 /* Foobar. */ |
98 | 102 |
99 /* Baz. */ | 103 /* Baz. */ |
100 asdf3 | 104 asdf3 |
101 """ | 105 """ |
102 with self.assertRaisesRegexp( | 106 with self.assertRaisesRegexp( |
103 parser.ParseError, | 107 parser.ParseError, |
104 r"^my_file\.mojom:5: Error: Unexpected 'asdf3':\nasdf3$"): | 108 r"^my_file\.mojom:5: Error: Unexpected 'asdf3':\n *asdf3$"): |
105 parser.Parse(source3, "my_file.mojom") | 109 parser.Parse(source3, "my_file.mojom") |
106 | 110 |
107 source4 = """\ | 111 source4 = """\ |
108 /* Multi-line C-style comments. | 112 /* Multi-line C-style comments. |
109 */ | 113 */ |
110 /* | 114 /* |
111 Foo. | 115 Foo. |
112 Bar. | 116 Bar. |
113 */ | 117 */ |
114 | 118 |
115 /* Baz | 119 /* Baz |
116 Quux. */ | 120 Quux. */ |
117 asdf4 | 121 asdf4 |
118 """ | 122 """ |
119 with self.assertRaisesRegexp( | 123 with self.assertRaisesRegexp( |
120 parser.ParseError, | 124 parser.ParseError, |
121 r"^my_file\.mojom:10: Error: Unexpected 'asdf4':\nasdf4$"): | 125 r"^my_file\.mojom:10: Error: Unexpected 'asdf4':\n *asdf4$"): |
122 parser.Parse(source4, "my_file.mojom") | 126 parser.Parse(source4, "my_file.mojom") |
123 | 127 |
124 | 128 |
125 def testSimpleStruct(self): | 129 def testSimpleStruct(self): |
126 """Tests a simple .mojom source that just defines a struct.""" | 130 """Tests a simple .mojom source that just defines a struct.""" |
127 source = """\ | 131 |
128 module my_module { | 132 source = """\ |
129 | 133 module my_module { |
130 struct MyStruct { | 134 |
131 int32 a; | 135 struct MyStruct { |
132 double b; | 136 int32 a; |
133 }; | 137 double b; |
134 | 138 }; |
135 } // module my_module | 139 |
136 """ | 140 } // module my_module |
137 expected = \ | 141 """ |
138 [('MODULE', | 142 expected = \ |
139 'my_module', | 143 [('MODULE', |
140 None, | 144 'my_module', |
141 [('STRUCT', | 145 None, |
142 'MyStruct', | 146 [('STRUCT', |
143 None, | 147 'MyStruct', |
144 [('FIELD', 'int32', 'a', ast.Ordinal(None), None), | 148 None, |
145 ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] | 149 [('FIELD', 'int32', 'a', ast.Ordinal(None), None), |
| 150 ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] |
146 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 151 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
147 | 152 |
148 def testSimpleStructWithoutModule(self): | 153 def testSimpleStructWithoutModule(self): |
149 """Tests a simple struct without an enclosing module.""" | 154 """Tests a simple struct without an enclosing module.""" |
150 source = """\ | 155 |
151 struct MyStruct { | 156 source = """\ |
152 int32 a; | 157 struct MyStruct { |
153 double b; | 158 int32 a; |
154 }; | 159 double b; |
155 """ | 160 }; |
156 expected = \ | 161 """ |
157 [('MODULE', | 162 expected = \ |
158 '', | 163 [('MODULE', |
159 None, | 164 '', |
160 [('STRUCT', | 165 None, |
161 'MyStruct', | 166 [('STRUCT', |
162 None, | 167 'MyStruct', |
163 [('FIELD', 'int32', 'a', ast.Ordinal(None), None), | 168 None, |
164 ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] | 169 [('FIELD', 'int32', 'a', ast.Ordinal(None), None), |
| 170 ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] |
165 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 171 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
166 | 172 |
167 def testMissingModuleName(self): | 173 def testMissingModuleName(self): |
168 """Tests an (invalid) .mojom with a missing module name.""" | 174 """Tests an (invalid) .mojom with a missing module name.""" |
| 175 |
169 source1 = """\ | 176 source1 = """\ |
170 // Missing module name. | 177 // Missing module name. |
171 module { | 178 module { |
172 struct MyStruct { | 179 struct MyStruct { |
173 int32 a; | 180 int32 a; |
174 }; | 181 }; |
175 } | 182 } |
176 """ | 183 """ |
177 with self.assertRaisesRegexp( | 184 with self.assertRaisesRegexp( |
178 parser.ParseError, | 185 parser.ParseError, |
179 r"^my_file\.mojom:2: Error: Unexpected '{':\nmodule {$"): | 186 r"^my_file\.mojom:2: Error: Unexpected '{':\n *module {$"): |
180 parser.Parse(source1, "my_file.mojom") | 187 parser.Parse(source1, "my_file.mojom") |
181 | 188 |
182 # Another similar case, but make sure that line-number tracking/reporting | 189 # Another similar case, but make sure that line-number tracking/reporting |
183 # is correct. | 190 # is correct. |
184 source2 = """\ | 191 source2 = """\ |
185 module | 192 module |
186 // This line intentionally left unblank. | 193 // This line intentionally left unblank. |
187 | 194 |
188 { | 195 { |
189 } | 196 } |
190 """ | 197 """ |
191 with self.assertRaisesRegexp( | 198 with self.assertRaisesRegexp( |
192 parser.ParseError, | 199 parser.ParseError, |
193 r"^my_file\.mojom:4: Error: Unexpected '{':\n{$"): | 200 r"^my_file\.mojom:4: Error: Unexpected '{':\n *{$"): |
194 parser.Parse(source2, "my_file.mojom") | 201 parser.Parse(source2, "my_file.mojom") |
195 | 202 |
196 def testEnumInitializers(self): | 203 def testEnumInitializers(self): |
197 """Tests an enum with simple initialized values.""" | 204 """Tests an enum with simple initialized values.""" |
198 source = """\ | 205 |
199 module my_module { | 206 source = """\ |
200 | 207 module my_module { |
201 enum MyEnum { | 208 |
202 MY_ENUM_NEG1 = -1, | 209 enum MyEnum { |
203 MY_ENUM_ZERO = 0, | 210 MY_ENUM_NEG1 = -1, |
204 MY_ENUM_1 = +1, | 211 MY_ENUM_ZERO = 0, |
205 MY_ENUM_2, | 212 MY_ENUM_1 = +1, |
206 }; | 213 MY_ENUM_2, |
207 | 214 }; |
208 } // my_module | 215 |
209 """ | 216 } // my_module |
210 expected = \ | 217 """ |
211 [('MODULE', | 218 expected = \ |
212 'my_module', | 219 [('MODULE', |
213 None, | 220 'my_module', |
214 [('ENUM', | 221 None, |
215 'MyEnum', | 222 [('ENUM', |
216 [('ENUM_FIELD', 'MY_ENUM_NEG1', '-1'), | 223 'MyEnum', |
217 ('ENUM_FIELD', 'MY_ENUM_ZERO', '0'), | 224 [('ENUM_FIELD', 'MY_ENUM_NEG1', '-1'), |
218 ('ENUM_FIELD', 'MY_ENUM_1', '+1'), | 225 ('ENUM_FIELD', 'MY_ENUM_ZERO', '0'), |
219 ('ENUM_FIELD', 'MY_ENUM_2', None)])])] | 226 ('ENUM_FIELD', 'MY_ENUM_1', '+1'), |
| 227 ('ENUM_FIELD', 'MY_ENUM_2', None)])])] |
220 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 228 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
221 | 229 |
222 def testConst(self): | 230 def testConst(self): |
223 """Tests some constants and struct memebers initialized with them.""" | 231 """Tests some constants and struct memebers initialized with them.""" |
224 source = """\ | 232 |
225 module my_module { | 233 source = """\ |
226 | 234 module my_module { |
227 struct MyStruct { | 235 |
228 const int8 kNumber = -1; | 236 struct MyStruct { |
229 int8 number@0 = kNumber; | 237 const int8 kNumber = -1; |
230 }; | 238 int8 number@0 = kNumber; |
231 | 239 }; |
232 } // my_module | 240 |
233 """ | 241 } // my_module |
234 expected = \ | 242 """ |
235 [('MODULE', | 243 expected = \ |
236 'my_module', | 244 [('MODULE', |
237 None, | 245 'my_module', |
238 [('STRUCT', | 246 None, |
239 'MyStruct', None, | 247 [('STRUCT', |
240 [('CONST', 'int8', 'kNumber', '-1'), | 248 'MyStruct', None, |
241 ('FIELD', 'int8', 'number', | 249 [('CONST', 'int8', 'kNumber', '-1'), |
242 ast.Ordinal(0), ('IDENTIFIER', 'kNumber'))])])] | 250 ('FIELD', 'int8', 'number', |
| 251 ast.Ordinal(0), ('IDENTIFIER', 'kNumber'))])])] |
243 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 252 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
244 | 253 |
245 def testNoConditionals(self): | 254 def testNoConditionals(self): |
246 """Tests that ?: is not allowed.""" | 255 """Tests that ?: is not allowed.""" |
247 source = """\ | 256 |
248 module my_module { | 257 source = """\ |
249 | 258 module my_module { |
250 enum MyEnum { | 259 |
251 MY_ENUM_1 = 1 ? 2 : 3 | 260 enum MyEnum { |
252 }; | 261 MY_ENUM_1 = 1 ? 2 : 3 |
253 | 262 }; |
254 } // my_module | 263 |
255 """ | 264 } // my_module |
| 265 """ |
256 with self.assertRaisesRegexp( | 266 with self.assertRaisesRegexp( |
257 lexer.LexError, | 267 lexer.LexError, |
258 r"^my_file\.mojom:4: Error: Illegal character '\?'$"): | 268 r"^my_file\.mojom:4: Error: Illegal character '\?'$"): |
259 parser.Parse(source, "my_file.mojom") | 269 parser.Parse(source, "my_file.mojom") |
260 | 270 |
261 def testSimpleOrdinals(self): | 271 def testSimpleOrdinals(self): |
262 """Tests that (valid) ordinal values are scanned correctly.""" | 272 """Tests that (valid) ordinal values are scanned correctly.""" |
| 273 |
263 source = """\ | 274 source = """\ |
264 module my_module { | 275 module my_module { |
265 | 276 |
266 // This isn't actually valid .mojom, but the problem (missing ordinals) should | 277 // This isn't actually valid .mojom, but the problem (missing ordinals) |
267 // be handled at a different level. | 278 // should be handled at a different level. |
268 struct MyStruct { | 279 struct MyStruct { |
269 int32 a0@0; | 280 int32 a0@0; |
270 int32 a1@1; | 281 int32 a1@1; |
271 int32 a2@2; | 282 int32 a2@2; |
272 int32 a9@9; | 283 int32 a9@9; |
273 int32 a10 @10; | 284 int32 a10 @10; |
274 int32 a11 @11; | 285 int32 a11 @11; |
275 int32 a29 @29; | 286 int32 a29 @29; |
276 int32 a1234567890 @1234567890; | 287 int32 a1234567890 @1234567890; |
277 }; | 288 }; |
278 | 289 |
279 } // module my_module | 290 } // module my_module |
280 """ | 291 """ |
281 expected = \ | 292 expected = \ |
282 [('MODULE', | 293 [('MODULE', |
283 'my_module', | 294 'my_module', |
284 None, | 295 None, |
285 [('STRUCT', | 296 [('STRUCT', |
286 'MyStruct', | 297 'MyStruct', |
287 None, | 298 None, |
288 [('FIELD', 'int32', 'a0', ast.Ordinal(0), None), | 299 [('FIELD', 'int32', 'a0', ast.Ordinal(0), None), |
289 ('FIELD', 'int32', 'a1', ast.Ordinal(1), None), | 300 ('FIELD', 'int32', 'a1', ast.Ordinal(1), None), |
290 ('FIELD', 'int32', 'a2', ast.Ordinal(2), None), | 301 ('FIELD', 'int32', 'a2', ast.Ordinal(2), None), |
291 ('FIELD', 'int32', 'a9', ast.Ordinal(9), None), | 302 ('FIELD', 'int32', 'a9', ast.Ordinal(9), None), |
292 ('FIELD', 'int32', 'a10', ast.Ordinal(10), None), | 303 ('FIELD', 'int32', 'a10', ast.Ordinal(10), None), |
293 ('FIELD', 'int32', 'a11', ast.Ordinal(11), None), | 304 ('FIELD', 'int32', 'a11', ast.Ordinal(11), None), |
294 ('FIELD', 'int32', 'a29', ast.Ordinal(29), None), | 305 ('FIELD', 'int32', 'a29', ast.Ordinal(29), None), |
295 ('FIELD', 'int32', 'a1234567890', ast.Ordinal(1234567890), None)])])] | 306 ('FIELD', 'int32', 'a1234567890', ast.Ordinal(1234567890), |
| 307 None)])])] |
296 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 308 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
297 | 309 |
298 def testInvalidOrdinals(self): | 310 def testInvalidOrdinals(self): |
299 """Tests that (lexically) invalid ordinals are correctly detected.""" | 311 """Tests that (lexically) invalid ordinals are correctly detected.""" |
| 312 |
300 source1 = """\ | 313 source1 = """\ |
301 module my_module { | 314 module my_module { |
302 | 315 |
303 struct MyStruct { | 316 struct MyStruct { |
304 int32 a_missing@; | 317 int32 a_missing@; |
305 }; | 318 }; |
306 | 319 |
307 } // module my_module | 320 } // module my_module |
308 """ | 321 """ |
309 with self.assertRaisesRegexp( | 322 with self.assertRaisesRegexp( |
310 lexer.LexError, | 323 lexer.LexError, |
311 r"^my_file\.mojom:4: Error: Missing ordinal value$"): | 324 r"^my_file\.mojom:4: Error: Missing ordinal value$"): |
312 parser.Parse(source1, "my_file.mojom") | 325 parser.Parse(source1, "my_file.mojom") |
313 | 326 |
314 source2 = """\ | 327 source2 = """\ |
315 module my_module { | 328 module my_module { |
316 | 329 |
317 struct MyStruct { | 330 struct MyStruct { |
318 int32 a_octal@01; | 331 int32 a_octal@01; |
319 }; | 332 }; |
320 | 333 |
321 } // module my_module | 334 } // module my_module |
322 """ | 335 """ |
323 with self.assertRaisesRegexp( | 336 with self.assertRaisesRegexp( |
324 lexer.LexError, | 337 lexer.LexError, |
325 r"^my_file\.mojom:4: Error: " | 338 r"^my_file\.mojom:4: Error: " |
326 r"Octal and hexadecimal ordinal values not allowed$"): | 339 r"Octal and hexadecimal ordinal values not allowed$"): |
327 parser.Parse(source2, "my_file.mojom") | 340 parser.Parse(source2, "my_file.mojom") |
328 | 341 |
329 source3 = """\ | 342 source3 = """\ |
330 module my_module { struct MyStruct { int32 a_invalid_octal@08; }; } | 343 module my_module { struct MyStruct { int32 a_invalid_octal@08; }; } |
331 """ | 344 """ |
332 with self.assertRaisesRegexp( | 345 with self.assertRaisesRegexp( |
333 lexer.LexError, | 346 lexer.LexError, |
334 r"^my_file\.mojom:1: Error: " | 347 r"^my_file\.mojom:1: Error: " |
335 r"Octal and hexadecimal ordinal values not allowed$"): | 348 r"Octal and hexadecimal ordinal values not allowed$"): |
336 parser.Parse(source3, "my_file.mojom") | 349 parser.Parse(source3, "my_file.mojom") |
337 | 350 |
338 source4 = """\ | 351 source4 = "module my_module { struct MyStruct { int32 a_hex@0x1aB9; }; }" |
339 module my_module { struct MyStruct { int32 a_hex@0x1aB9; }; } | |
340 """ | |
341 with self.assertRaisesRegexp( | 352 with self.assertRaisesRegexp( |
342 lexer.LexError, | 353 lexer.LexError, |
343 r"^my_file\.mojom:1: Error: " | 354 r"^my_file\.mojom:1: Error: " |
344 r"Octal and hexadecimal ordinal values not allowed$"): | 355 r"Octal and hexadecimal ordinal values not allowed$"): |
345 parser.Parse(source4, "my_file.mojom") | 356 parser.Parse(source4, "my_file.mojom") |
346 | 357 |
347 source5 = """\ | 358 source5 = "module my_module { struct MyStruct { int32 a_hex@0X0; }; }" |
348 module my_module { struct MyStruct { int32 a_hex@0X0; }; } | |
349 """ | |
350 with self.assertRaisesRegexp( | 359 with self.assertRaisesRegexp( |
351 lexer.LexError, | 360 lexer.LexError, |
352 r"^my_file\.mojom:1: Error: " | 361 r"^my_file\.mojom:1: Error: " |
353 r"Octal and hexadecimal ordinal values not allowed$"): | 362 r"Octal and hexadecimal ordinal values not allowed$"): |
354 parser.Parse(source5, "my_file.mojom") | 363 parser.Parse(source5, "my_file.mojom") |
355 | 364 |
356 source6 = """\ | 365 source6 = """\ |
357 struct MyStruct { | 366 struct MyStruct { |
358 int32 a_too_big@999999999999; | 367 int32 a_too_big@999999999999; |
359 }; | 368 }; |
360 """ | 369 """ |
361 with self.assertRaisesRegexp( | 370 with self.assertRaisesRegexp( |
362 parser.ParseError, | 371 parser.ParseError, |
363 r"^my_file\.mojom:2: Error: " | 372 r"^my_file\.mojom:2: Error: " |
364 r"Ordinal value 999999999999 too large:\n" | 373 r"Ordinal value 999999999999 too large:\n" |
365 r" int32 a_too_big@999999999999;$"): | 374 r" *int32 a_too_big@999999999999;$"): |
366 parser.Parse(source6, "my_file.mojom") | 375 parser.Parse(source6, "my_file.mojom") |
367 | 376 |
368 def testNestedNamespace(self): | 377 def testNestedNamespace(self): |
369 """Tests that "nested" namespaces work.""" | 378 """Tests that "nested" namespaces work.""" |
370 source = """\ | 379 |
371 module my.mod { | 380 source = """\ |
372 | 381 module my.mod { |
373 struct MyStruct { | 382 |
374 int32 a; | 383 struct MyStruct { |
375 }; | 384 int32 a; |
376 | 385 }; |
377 } // module my.mod | 386 |
378 """ | 387 } // module my.mod |
379 expected = \ | 388 """ |
380 [('MODULE', | 389 expected = \ |
381 'my.mod', | 390 [('MODULE', |
382 None, | 391 'my.mod', |
383 [('STRUCT', | 392 None, |
384 'MyStruct', | 393 [('STRUCT', |
385 None, | 394 'MyStruct', |
386 [('FIELD', 'int32', 'a', ast.Ordinal(None), None)])])] | 395 None, |
| 396 [('FIELD', 'int32', 'a', ast.Ordinal(None), None)])])] |
387 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 397 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
388 | 398 |
389 def testValidHandleTypes(self): | 399 def testValidHandleTypes(self): |
390 """Tests (valid) handle types.""" | 400 """Tests (valid) handle types.""" |
391 source = """\ | 401 |
392 struct MyStruct { | 402 source = """\ |
393 handle a; | 403 struct MyStruct { |
394 handle<data_pipe_consumer> b; | 404 handle a; |
395 handle <data_pipe_producer> c; | 405 handle<data_pipe_consumer> b; |
396 handle < message_pipe > d; | 406 handle <data_pipe_producer> c; |
397 handle | 407 handle < message_pipe > d; |
398 < shared_buffer | 408 handle |
399 > e; | 409 < shared_buffer |
400 }; | 410 > e; |
401 """ | 411 }; |
402 expected = \ | 412 """ |
403 [('MODULE', | 413 expected = \ |
404 '', | 414 [('MODULE', |
405 None, | 415 '', |
406 [('STRUCT', | 416 None, |
407 'MyStruct', | 417 [('STRUCT', |
408 None, | 418 'MyStruct', |
409 [('FIELD', 'handle', 'a', ast.Ordinal(None), None), | 419 None, |
410 ('FIELD', 'handle<data_pipe_consumer>', 'b', ast.Ordinal(None), None), | 420 [('FIELD', 'handle', 'a', ast.Ordinal(None), None), |
411 ('FIELD', 'handle<data_pipe_producer>', 'c', ast.Ordinal(None), None), | 421 ('FIELD', 'handle<data_pipe_consumer>', 'b', ast.Ordinal(None), |
412 ('FIELD', 'handle<message_pipe>', 'd', ast.Ordinal(None), None), | 422 None), |
413 ('FIELD', 'handle<shared_buffer>', 'e', ast.Ordinal(None), None)])])] | 423 ('FIELD', 'handle<data_pipe_producer>', 'c', ast.Ordinal(None), |
| 424 None), |
| 425 ('FIELD', 'handle<message_pipe>', 'd', ast.Ordinal(None), None), |
| 426 ('FIELD', 'handle<shared_buffer>', 'e', ast.Ordinal(None), |
| 427 None)])])] |
414 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 428 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
415 | 429 |
416 def testInvalidHandleType(self): | 430 def testInvalidHandleType(self): |
417 """Tests an invalid (unknown) handle type.""" | 431 """Tests an invalid (unknown) handle type.""" |
418 source = """\ | 432 |
419 struct MyStruct { | 433 source = """\ |
420 handle<wtf_is_this> foo; | 434 struct MyStruct { |
421 }; | 435 handle<wtf_is_this> foo; |
422 """ | 436 }; |
| 437 """ |
423 with self.assertRaisesRegexp( | 438 with self.assertRaisesRegexp( |
424 parser.ParseError, | 439 parser.ParseError, |
425 r"^my_file\.mojom:2: Error: " | 440 r"^my_file\.mojom:2: Error: " |
426 r"Invalid handle type 'wtf_is_this':\n" | 441 r"Invalid handle type 'wtf_is_this':\n" |
427 r" handle<wtf_is_this> foo;$"): | 442 r" *handle<wtf_is_this> foo;$"): |
428 parser.Parse(source, "my_file.mojom") | 443 parser.Parse(source, "my_file.mojom") |
429 | 444 |
430 def testValidDefaultValues(self): | 445 def testValidDefaultValues(self): |
431 """Tests default values that are valid (to the parser).""" | 446 """Tests default values that are valid (to the parser).""" |
432 source = """\ | 447 |
433 struct MyStruct { | 448 source = """\ |
434 int16 a0 = 0; | 449 struct MyStruct { |
435 uint16 a1 = 0x0; | 450 int16 a0 = 0; |
436 uint16 a2 = 0x00; | 451 uint16 a1 = 0x0; |
437 uint16 a3 = 0x01; | 452 uint16 a2 = 0x00; |
438 uint16 a4 = 0xcd; | 453 uint16 a3 = 0x01; |
439 int32 a5 = 12345; | 454 uint16 a4 = 0xcd; |
440 int64 a6 = -12345; | 455 int32 a5 = 12345; |
441 int64 a7 = +12345; | 456 int64 a6 = -12345; |
442 uint32 a8 = 0x12cd3; | 457 int64 a7 = +12345; |
443 uint32 a9 = -0x12cD3; | 458 uint32 a8 = 0x12cd3; |
444 uint32 a10 = +0x12CD3; | 459 uint32 a9 = -0x12cD3; |
445 bool a11 = true; | 460 uint32 a10 = +0x12CD3; |
446 bool a12 = false; | 461 bool a11 = true; |
447 float a13 = 1.2345; | 462 bool a12 = false; |
448 float a14 = -1.2345; | 463 float a13 = 1.2345; |
449 float a15 = +1.2345; | 464 float a14 = -1.2345; |
450 float a16 = 123.; | 465 float a15 = +1.2345; |
451 float a17 = .123; | 466 float a16 = 123.; |
452 double a18 = 1.23E10; | 467 float a17 = .123; |
453 double a19 = 1.E-10; | 468 double a18 = 1.23E10; |
454 double a20 = .5E+10; | 469 double a19 = 1.E-10; |
455 double a21 = -1.23E10; | 470 double a20 = .5E+10; |
456 double a22 = +.123E10; | 471 double a21 = -1.23E10; |
457 }; | 472 double a22 = +.123E10; |
458 """ | 473 }; |
459 expected = \ | 474 """ |
460 [('MODULE', | 475 expected = \ |
461 '', | 476 [('MODULE', |
462 None, | 477 '', |
463 [('STRUCT', | 478 None, |
464 'MyStruct', | 479 [('STRUCT', |
465 None, | 480 'MyStruct', |
466 [('FIELD', 'int16', 'a0', ast.Ordinal(None), '0'), | 481 None, |
467 ('FIELD', 'uint16', 'a1', ast.Ordinal(None), '0x0'), | 482 [('FIELD', 'int16', 'a0', ast.Ordinal(None), '0'), |
468 ('FIELD', 'uint16', 'a2', ast.Ordinal(None), '0x00'), | 483 ('FIELD', 'uint16', 'a1', ast.Ordinal(None), '0x0'), |
469 ('FIELD', 'uint16', 'a3', ast.Ordinal(None), '0x01'), | 484 ('FIELD', 'uint16', 'a2', ast.Ordinal(None), '0x00'), |
470 ('FIELD', 'uint16', 'a4', ast.Ordinal(None), '0xcd'), | 485 ('FIELD', 'uint16', 'a3', ast.Ordinal(None), '0x01'), |
471 ('FIELD', 'int32', 'a5' , ast.Ordinal(None), '12345'), | 486 ('FIELD', 'uint16', 'a4', ast.Ordinal(None), '0xcd'), |
472 ('FIELD', 'int64', 'a6', ast.Ordinal(None), '-12345'), | 487 ('FIELD', 'int32', 'a5' , ast.Ordinal(None), '12345'), |
473 ('FIELD', 'int64', 'a7', ast.Ordinal(None), '+12345'), | 488 ('FIELD', 'int64', 'a6', ast.Ordinal(None), '-12345'), |
474 ('FIELD', 'uint32', 'a8', ast.Ordinal(None), '0x12cd3'), | 489 ('FIELD', 'int64', 'a7', ast.Ordinal(None), '+12345'), |
475 ('FIELD', 'uint32', 'a9', ast.Ordinal(None), '-0x12cD3'), | 490 ('FIELD', 'uint32', 'a8', ast.Ordinal(None), '0x12cd3'), |
476 ('FIELD', 'uint32', 'a10', ast.Ordinal(None), '+0x12CD3'), | 491 ('FIELD', 'uint32', 'a9', ast.Ordinal(None), '-0x12cD3'), |
477 ('FIELD', 'bool', 'a11', ast.Ordinal(None), 'true'), | 492 ('FIELD', 'uint32', 'a10', ast.Ordinal(None), '+0x12CD3'), |
478 ('FIELD', 'bool', 'a12', ast.Ordinal(None), 'false'), | 493 ('FIELD', 'bool', 'a11', ast.Ordinal(None), 'true'), |
479 ('FIELD', 'float', 'a13', ast.Ordinal(None), '1.2345'), | 494 ('FIELD', 'bool', 'a12', ast.Ordinal(None), 'false'), |
480 ('FIELD', 'float', 'a14', ast.Ordinal(None), '-1.2345'), | 495 ('FIELD', 'float', 'a13', ast.Ordinal(None), '1.2345'), |
481 ('FIELD', 'float', 'a15', ast.Ordinal(None), '+1.2345'), | 496 ('FIELD', 'float', 'a14', ast.Ordinal(None), '-1.2345'), |
482 ('FIELD', 'float', 'a16', ast.Ordinal(None), '123.'), | 497 ('FIELD', 'float', 'a15', ast.Ordinal(None), '+1.2345'), |
483 ('FIELD', 'float', 'a17', ast.Ordinal(None), '.123'), | 498 ('FIELD', 'float', 'a16', ast.Ordinal(None), '123.'), |
484 ('FIELD', 'double', 'a18', ast.Ordinal(None), '1.23E10'), | 499 ('FIELD', 'float', 'a17', ast.Ordinal(None), '.123'), |
485 ('FIELD', 'double', 'a19', ast.Ordinal(None), '1.E-10'), | 500 ('FIELD', 'double', 'a18', ast.Ordinal(None), '1.23E10'), |
486 ('FIELD', 'double', 'a20', ast.Ordinal(None), '.5E+10'), | 501 ('FIELD', 'double', 'a19', ast.Ordinal(None), '1.E-10'), |
487 ('FIELD', 'double', 'a21', ast.Ordinal(None), '-1.23E10'), | 502 ('FIELD', 'double', 'a20', ast.Ordinal(None), '.5E+10'), |
488 ('FIELD', 'double', 'a22', ast.Ordinal(None), '+.123E10')])])] | 503 ('FIELD', 'double', 'a21', ast.Ordinal(None), '-1.23E10'), |
| 504 ('FIELD', 'double', 'a22', ast.Ordinal(None), '+.123E10')])])] |
489 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 505 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
490 | 506 |
491 def testValidFixedSizeArray(self): | 507 def testValidFixedSizeArray(self): |
492 """Tests parsing a fixed size array.""" | 508 """Tests parsing a fixed size array.""" |
493 source = """\ | 509 |
494 struct MyStruct { | 510 source = """\ |
495 int32[] normal_array; | 511 struct MyStruct { |
496 int32[1] fixed_size_array_one_entry; | 512 int32[] normal_array; |
497 int32[10] fixed_size_array_ten_entries; | 513 int32[1] fixed_size_array_one_entry; |
498 }; | 514 int32[10] fixed_size_array_ten_entries; |
499 """ | 515 }; |
500 expected = \ | 516 """ |
501 [('MODULE', | 517 expected = \ |
502 '', | 518 [('MODULE', |
503 None, | 519 '', |
504 [('STRUCT', | 520 None, |
505 'MyStruct', | 521 [('STRUCT', |
506 None, | 522 'MyStruct', |
507 [('FIELD', 'int32[]', 'normal_array', ast.Ordinal(None), None), | 523 None, |
508 ('FIELD', 'int32[1]', 'fixed_size_array_one_entry', | 524 [('FIELD', 'int32[]', 'normal_array', ast.Ordinal(None), None), |
509 ast.Ordinal(None), None), | 525 ('FIELD', 'int32[1]', 'fixed_size_array_one_entry', |
510 ('FIELD', 'int32[10]', 'fixed_size_array_ten_entries', | 526 ast.Ordinal(None), None), |
511 ast.Ordinal(None), None)])])] | 527 ('FIELD', 'int32[10]', 'fixed_size_array_ten_entries', |
| 528 ast.Ordinal(None), None)])])] |
512 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 529 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
513 | 530 |
514 def testValidNestedArray(self): | 531 def testValidNestedArray(self): |
515 """Tests parsing a nested array.""" | 532 """Tests parsing a nested array.""" |
516 source = """\ | 533 |
517 struct MyStruct { | 534 source = "struct MyStruct { int32[][] nested_array; };" |
518 int32[][] nested_array; | 535 expected = \ |
519 }; | 536 [('MODULE', |
520 """ | 537 '', |
521 expected = \ | 538 None, |
522 [('MODULE', | 539 [('STRUCT', |
523 '', | 540 'MyStruct', |
524 None, | 541 None, |
525 [('STRUCT', | 542 [('FIELD', 'int32[][]', 'nested_array', ast.Ordinal(None), |
526 'MyStruct', | 543 None)])])] |
527 None, | |
528 [('FIELD', 'int32[][]', 'nested_array', ast.Ordinal(None), None)])])] | |
529 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) | 544 self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) |
530 | 545 |
531 def testInvalidFixedArraySize(self): | 546 def testInvalidFixedArraySize(self): |
532 """Tests that invalid fixed array bounds are correctly detected.""" | 547 """Tests that invalid fixed array bounds are correctly detected.""" |
| 548 |
533 source1 = """\ | 549 source1 = """\ |
534 struct MyStruct { | 550 struct MyStruct { |
535 int32[0] zero_size_array; | 551 int32[0] zero_size_array; |
536 }; | 552 }; |
537 """ | 553 """ |
538 with self.assertRaisesRegexp( | 554 with self.assertRaisesRegexp( |
539 parser.ParseError, | 555 parser.ParseError, |
540 r"^my_file\.mojom: Error: Fixed array size 0 invalid$"): | 556 r"^my_file\.mojom:2: Error: Fixed array size 0 invalid\n" |
| 557 r" *int32\[0\] zero_size_array;$"): |
541 parser.Parse(source1, "my_file.mojom") | 558 parser.Parse(source1, "my_file.mojom") |
542 | 559 |
543 source2 = """\ | 560 source2 = """\ |
544 struct MyStruct { | 561 struct MyStruct { |
545 int32[999999999999] too_big_array; | 562 int32[999999999999] too_big_array; |
546 }; | 563 }; |
547 """ | 564 """ |
548 with self.assertRaisesRegexp( | 565 with self.assertRaisesRegexp( |
549 parser.ParseError, | 566 parser.ParseError, |
550 r"^my_file\.mojom: Error: Fixed array size 999999999999 invalid$"): | 567 r"^my_file\.mojom:2: Error: Fixed array size 999999999999 invalid\n" |
| 568 r" *int32\[999999999999\] too_big_array;$"): |
551 parser.Parse(source2, "my_file.mojom") | 569 parser.Parse(source2, "my_file.mojom") |
552 | 570 |
553 source3 = """\ | 571 source3 = """\ |
554 struct MyStruct { | 572 struct MyStruct { |
555 int32[abcdefg] not_a_number; | 573 int32[abcdefg] not_a_number; |
556 }; | 574 }; |
557 """ | 575 """ |
558 with self.assertRaisesRegexp( | 576 with self.assertRaisesRegexp( |
559 parser.ParseError, | 577 parser.ParseError, |
560 r"^my_file\.mojom:2: Error: Unexpected 'abcdefg':"): | 578 r"^my_file\.mojom:2: Error: Unexpected 'abcdefg':\n" |
| 579 r" *int32\[abcdefg\] not_a_number;"): |
561 parser.Parse(source3, "my_file.mojom") | 580 parser.Parse(source3, "my_file.mojom") |
562 | 581 |
563 def testValidMethod(self): | 582 def testValidMethod(self): |
564 """Tests parsing method declarations.""" | 583 """Tests parsing method declarations.""" |
565 source1 = """\ | 584 |
566 interface MyInterface { | 585 source1 = "interface MyInterface { MyMethod(int32 a); };" |
567 MyMethod(int32 a); | |
568 }; | |
569 """ | |
570 expected1 = \ | 586 expected1 = \ |
571 [('MODULE', | 587 [('MODULE', |
572 '', | 588 '', |
573 None, | 589 None, |
574 [('INTERFACE', | 590 [('INTERFACE', |
575 'MyInterface', | 591 'MyInterface', |
576 None, | 592 None, |
577 [('METHOD', | 593 [('METHOD', |
578 'MyMethod', | 594 'MyMethod', |
579 [ast.Parameter('int32', 'a', ast.Ordinal(None))], | 595 [ast.Parameter('int32', 'a', ast.Ordinal(None))], |
580 ast.Ordinal(None), | 596 ast.Ordinal(None), |
581 None)])])] | 597 None)])])] |
582 self.assertEquals(parser.Parse(source1, "my_file.mojom"), expected1) | 598 self.assertEquals(parser.Parse(source1, "my_file.mojom"), expected1) |
583 | 599 |
584 source2 = """\ | 600 source2 = """\ |
585 interface MyInterface { | 601 interface MyInterface { |
586 MyMethod1@0(int32 a@0, int64 b@1); | 602 MyMethod1@0(int32 a@0, int64 b@1); |
587 MyMethod2@1() => (); | 603 MyMethod2@1() => (); |
588 }; | 604 }; |
589 """ | 605 """ |
590 expected2 = \ | 606 expected2 = \ |
591 [('MODULE', | 607 [('MODULE', |
592 '', | 608 '', |
593 None, | 609 None, |
594 [('INTERFACE', | 610 [('INTERFACE', |
595 'MyInterface', | 611 'MyInterface', |
596 None, | 612 None, |
597 [('METHOD', | 613 [('METHOD', |
598 'MyMethod1', | 614 'MyMethod1', |
599 [ast.Parameter('int32', 'a', ast.Ordinal(0)), | 615 [ast.Parameter('int32', 'a', ast.Ordinal(0)), |
600 ast.Parameter('int64', 'b', ast.Ordinal(1))], | 616 ast.Parameter('int64', 'b', ast.Ordinal(1))], |
601 ast.Ordinal(0), | 617 ast.Ordinal(0), |
602 None), | 618 None), |
603 ('METHOD', | 619 ('METHOD', |
604 'MyMethod2', | 620 'MyMethod2', |
605 [], | 621 [], |
606 ast.Ordinal(1), | 622 ast.Ordinal(1), |
607 [])])])] | 623 [])])])] |
608 self.assertEquals(parser.Parse(source2, "my_file.mojom"), expected2) | 624 self.assertEquals(parser.Parse(source2, "my_file.mojom"), expected2) |
609 | 625 |
610 source3 = """\ | 626 source3 = """\ |
611 interface MyInterface { | 627 interface MyInterface { |
612 MyMethod(string a) => (int32 a, bool b); | 628 MyMethod(string a) => (int32 a, bool b); |
613 }; | 629 }; |
614 """ | 630 """ |
615 expected3 = \ | 631 expected3 = \ |
616 [('MODULE', | 632 [('MODULE', |
617 '', | 633 '', |
618 None, | 634 None, |
619 [('INTERFACE', | 635 [('INTERFACE', |
620 'MyInterface', | 636 'MyInterface', |
621 None, | 637 None, |
622 [('METHOD', | 638 [('METHOD', |
623 'MyMethod', | 639 'MyMethod', |
624 [ast.Parameter('string', 'a', ast.Ordinal(None))], | 640 [ast.Parameter('string', 'a', ast.Ordinal(None))], |
625 ast.Ordinal(None), | 641 ast.Ordinal(None), |
626 [ast.Parameter('int32', 'a', ast.Ordinal(None)), | 642 [ast.Parameter('int32', 'a', ast.Ordinal(None)), |
627 ast.Parameter('bool', 'b', ast.Ordinal(None))])])])] | 643 ast.Parameter('bool', 'b', ast.Ordinal(None))])])])] |
628 self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3) | 644 self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3) |
629 | 645 |
630 if __name__ == "__main__": | 646 if __name__ == "__main__": |
631 unittest.main() | 647 unittest.main() |
OLD | NEW |