OLD | NEW |
| (Empty) |
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 | |
3 # found in the LICENSE file. | |
4 | |
5 import mojo_lexer | |
6 import mojo_parser | |
7 import unittest | |
8 | |
9 | |
10 class MojoParserTest(unittest.TestCase): | |
11 """Tests mojo_parser (in particular, Parse()).""" | |
12 | |
13 def testTrivialValidSource(self): | |
14 """Tests a trivial, but valid, .mojom source.""" | |
15 source = """\ | |
16 // This is a comment. | |
17 | |
18 module my_module { | |
19 } | |
20 """ | |
21 self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), | |
22 [("MODULE", "my_module", None)]) | |
23 | |
24 def testSourceWithCrLfs(self): | |
25 """Tests a .mojom source with CR-LFs instead of LFs.""" | |
26 source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n"; | |
27 self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), | |
28 [("MODULE", "my_module", None)]) | |
29 | |
30 def testUnexpectedEOF(self): | |
31 """Tests a "truncated" .mojom source.""" | |
32 source = """\ | |
33 // This is a comment. | |
34 | |
35 module my_module { | |
36 """ | |
37 with self.assertRaisesRegexp( | |
38 mojo_parser.ParseError, | |
39 r"^my_file\.mojom: Error: Unexpected end of file$"): | |
40 mojo_parser.Parse(source, "my_file.mojom") | |
41 | |
42 def testSimpleStruct(self): | |
43 """Tests a simple .mojom source that just defines a struct.""" | |
44 source ="""\ | |
45 module my_module { | |
46 | |
47 struct MyStruct { | |
48 int32 a; | |
49 double b; | |
50 }; | |
51 | |
52 } // module my_module | |
53 """ | |
54 # Note: Output as pretty-printed on failure by the test harness. | |
55 expected = \ | |
56 [('MODULE', | |
57 'my_module', | |
58 [('STRUCT', | |
59 'MyStruct', | |
60 None, | |
61 [('FIELD', 'int32', 'a', None, None), | |
62 ('FIELD', 'double', 'b', None, None)])])] | |
63 self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) | |
64 | |
65 def testEnumExpressions(self): | |
66 """Tests an enum with values calculated using simple expressions.""" | |
67 source = """\ | |
68 module my_module { | |
69 | |
70 enum MyEnum { | |
71 MY_ENUM_1 = 1, | |
72 MY_ENUM_2 = 1 + 1, | |
73 MY_ENUM_3 = 1 * 3, | |
74 MY_ENUM_4 = 2 * (1 + 1), | |
75 MY_ENUM_5 = 1 + 2 * 2, | |
76 MY_ENUM_6 = -6 / -2, | |
77 MY_ENUM_7 = 3 | (1 << 2), | |
78 MY_ENUM_8 = 16 >> 1, | |
79 MY_ENUM_9 = 1 ^ 15 & 8, | |
80 MY_ENUM_10 = 110 % 100, | |
81 MY_ENUM_MINUS_1 = ~0 | |
82 }; | |
83 | |
84 } // my_module | |
85 """ | |
86 expected = \ | |
87 [('MODULE', | |
88 'my_module', | |
89 [('ENUM', | |
90 'MyEnum', | |
91 [('ENUM_FIELD', 'MY_ENUM_1', ('EXPRESSION', ['1'])), | |
92 ('ENUM_FIELD', 'MY_ENUM_2', ('EXPRESSION', ['1', '+', '1'])), | |
93 ('ENUM_FIELD', 'MY_ENUM_3', ('EXPRESSION', ['1', '*', '3'])), | |
94 ('ENUM_FIELD', | |
95 'MY_ENUM_4', | |
96 ('EXPRESSION', | |
97 ['2', '*', '(', ('EXPRESSION', ['1', '+', '1']), ')'])), | |
98 ('ENUM_FIELD', | |
99 'MY_ENUM_5', | |
100 ('EXPRESSION', ['1', '+', '2', '*', '2'])), | |
101 ('ENUM_FIELD', | |
102 'MY_ENUM_6', | |
103 ('EXPRESSION', | |
104 ['-', ('EXPRESSION', ['6', '/', '-', ('EXPRESSION', ['2'])])])), | |
105 ('ENUM_FIELD', | |
106 'MY_ENUM_7', | |
107 ('EXPRESSION', | |
108 ['3', '|', '(', ('EXPRESSION', ['1', '<<', '2']), ')'])), | |
109 ('ENUM_FIELD', 'MY_ENUM_8', ('EXPRESSION', ['16', '>>', '1'])), | |
110 ('ENUM_FIELD', | |
111 'MY_ENUM_9', | |
112 ('EXPRESSION', ['1', '^', '15', '&', '8'])), | |
113 ('ENUM_FIELD', 'MY_ENUM_10', ('EXPRESSION', ['110', '%', '100'])), | |
114 ('ENUM_FIELD', | |
115 'MY_ENUM_MINUS_1', | |
116 ('EXPRESSION', ['~', ('EXPRESSION', ['0'])]))])])] | |
117 self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) | |
118 | |
119 def testNoConditionals(self): | |
120 """Tests that ?: is not allowed.""" | |
121 source = """\ | |
122 module my_module { | |
123 | |
124 enum MyEnum { | |
125 MY_ENUM_1 = 1 ? 2 : 3 | |
126 }; | |
127 | |
128 } // my_module | |
129 """ | |
130 with self.assertRaisesRegexp( | |
131 mojo_lexer.LexError, | |
132 r"^my_file\.mojom:4: Error: Illegal character '\?'$"): | |
133 mojo_parser.Parse(source, "my_file.mojom") | |
134 | |
135 def testSimpleOrdinals(self): | |
136 """Tests that (valid) ordinal values are scanned correctly.""" | |
137 source = """\ | |
138 module my_module { | |
139 | |
140 // This isn't actually valid .mojom, but the problem (missing ordinals) should | |
141 // be handled at a different level. | |
142 struct MyStruct { | |
143 int32 a0 @0; | |
144 int32 a1 @1; | |
145 int32 a2 @2; | |
146 int32 a9 @9; | |
147 int32 a10 @10; | |
148 int32 a11 @11; | |
149 int32 a29 @29; | |
150 int32 a1234567890 @1234567890; | |
151 }; | |
152 | |
153 } // module my_module | |
154 """ | |
155 expected = \ | |
156 [('MODULE', | |
157 'my_module', | |
158 [('STRUCT', | |
159 'MyStruct', | |
160 None, | |
161 [('FIELD', 'int32', 'a0', '@0', None), | |
162 ('FIELD', 'int32', 'a1', '@1', None), | |
163 ('FIELD', 'int32', 'a2', '@2', None), | |
164 ('FIELD', 'int32', 'a9', '@9', None), | |
165 ('FIELD', 'int32', 'a10', '@10', None), | |
166 ('FIELD', 'int32', 'a11', '@11', None), | |
167 ('FIELD', 'int32', 'a29', '@29', None), | |
168 ('FIELD', 'int32', 'a1234567890', '@1234567890', None)])])] | |
169 self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) | |
170 | |
171 def testInvalidOrdinals(self): | |
172 """Tests that (lexically) invalid ordinals are correctly detected.""" | |
173 source1 = """\ | |
174 module my_module { | |
175 | |
176 struct MyStruct { | |
177 int32 a_missing @; | |
178 }; | |
179 | |
180 } // module my_module | |
181 """ | |
182 with self.assertRaisesRegexp( | |
183 mojo_lexer.LexError, | |
184 r"^my_file\.mojom:4: Error: Missing ordinal value$"): | |
185 mojo_parser.Parse(source1, "my_file.mojom") | |
186 | |
187 source2 = """\ | |
188 module my_module { | |
189 | |
190 struct MyStruct { | |
191 int32 a_octal @01; | |
192 }; | |
193 | |
194 } // module my_module | |
195 """ | |
196 with self.assertRaisesRegexp( | |
197 mojo_lexer.LexError, | |
198 r"^my_file\.mojom:4: Error: " | |
199 r"Octal and hexadecimal ordinal values not allowed$"): | |
200 mojo_parser.Parse(source2, "my_file.mojom") | |
201 | |
202 source3 = """\ | |
203 module my_module { struct MyStruct { int32 a_invalid_octal @08; }; } | |
204 """ | |
205 with self.assertRaisesRegexp( | |
206 mojo_lexer.LexError, | |
207 r"^my_file\.mojom:1: Error: " | |
208 r"Octal and hexadecimal ordinal values not allowed$"): | |
209 mojo_parser.Parse(source3, "my_file.mojom") | |
210 | |
211 source4 = """\ | |
212 module my_module { struct MyStruct { int32 a_hex @0x1aB9; }; } | |
213 """ | |
214 with self.assertRaisesRegexp( | |
215 mojo_lexer.LexError, | |
216 r"^my_file\.mojom:1: Error: " | |
217 r"Octal and hexadecimal ordinal values not allowed$"): | |
218 mojo_parser.Parse(source4, "my_file.mojom") | |
219 | |
220 source5 = """\ | |
221 module my_module { struct MyStruct { int32 a_hex @0X0; }; } | |
222 """ | |
223 with self.assertRaisesRegexp( | |
224 mojo_lexer.LexError, | |
225 r"^my_file\.mojom:1: Error: " | |
226 r"Octal and hexadecimal ordinal values not allowed$"): | |
227 mojo_parser.Parse(source5, "my_file.mojom") | |
228 | |
229 | |
230 if __name__ == "__main__": | |
231 unittest.main() | |
OLD | NEW |