OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'package:unittest/unittest.dart'; | |
6 import 'package:unittest/src/backend/platform_selector/ast.dart'; | |
7 import 'package:unittest/src/backend/platform_selector/parser.dart'; | |
8 | |
9 /// A matcher that asserts that a value is a [ConditionalNode]. | |
10 Matcher _isConditionalNode = | |
11 new isInstanceOf<ConditionalNode>("ConditionalNode"); | |
12 | |
13 /// A matcher that asserts that a value is an [OrNode]. | |
14 Matcher _isOrNode = new isInstanceOf<OrNode>("OrNode"); | |
15 | |
16 /// A matcher that asserts that a value is an [AndNode]. | |
17 Matcher _isAndNode = new isInstanceOf<AndNode>("AndNode"); | |
18 | |
19 /// A matcher that asserts that a value is a [NotNode]. | |
20 Matcher _isNotNode = new isInstanceOf<NotNode>("NotNode"); | |
21 | |
22 void main() { | |
23 group("parses a conditional expression", () { | |
24 test("with identifiers", () { | |
25 var node = _parse(" a ? b : c "); | |
26 expect(node, _isConditionalNode); | |
Bob Nystrom
2015/03/11 20:05:53
It's probably simpler just to test node.toString()
nweiz
2015/03/12 19:48:58
But the AST tests also rely on the parser to do th
| |
27 expect(node.condition, _isVar("a")); | |
28 expect(node.branch1, _isVar("b")); | |
29 expect(node.branch2, _isVar("c")); | |
30 | |
31 expect(node.span.text, equals("a ? b : c")); | |
32 expect(node.span.start.offset, equals(2)); | |
33 expect(node.span.end.offset, equals(11)); | |
34 }); | |
35 | |
36 test("with nested ors", () { | |
37 // Should parse as "(a || b) ? (c || d) : (e || f)". | |
38 // Should not parse as "a || (b ? (c || d) : (e || f))". | |
39 // Should not parse as "((a || b) ? (c || d) : e) || f". | |
40 // Should not parse as "a || (b ? (c || d) : e) || f". | |
41 var node = _parse("a || b ? c || d : e || f"); | |
42 expect(node, _isConditionalNode); | |
43 | |
44 expect(node.condition, _isOrNode); | |
45 expect(node.condition.branch1, _isVar("a")); | |
46 expect(node.condition.branch2, _isVar("b")); | |
47 | |
48 expect(node.branch1, _isOrNode); | |
49 expect(node.branch1.branch1, _isVar("c")); | |
50 expect(node.branch1.branch2, _isVar("d")); | |
51 | |
52 expect(node.branch2, _isOrNode); | |
53 expect(node.branch2.branch1, _isVar("e")); | |
54 expect(node.branch2.branch2, _isVar("f")); | |
55 }); | |
56 | |
57 test("with a conditional expression as branch 1", () { | |
58 // Should parse as "a ? (b ? c : d) : e". | |
59 var node = _parse("a ? b ? c : d : e"); | |
60 expect(node, _isConditionalNode); | |
61 expect(node.condition, _isVar("a")); | |
62 expect(node.branch2, _isVar("e")); | |
63 | |
64 expect(node.branch1, _isConditionalNode); | |
65 expect(node.branch1.condition, _isVar("b")); | |
66 expect(node.branch1.branch1, _isVar("c")); | |
67 expect(node.branch1.branch2, _isVar("d")); | |
68 }); | |
69 | |
70 test("with a conditional expression as branch 2", () { | |
71 // Should parse as "a ? b : (c ? d : e)". | |
72 // Should not parse as "(a ? b : c) ? d : e". | |
73 var node = _parse("a ? b : c ? d : e"); | |
74 expect(node, _isConditionalNode); | |
75 expect(node.condition, _isVar("a")); | |
76 expect(node.branch1, _isVar("b")); | |
77 | |
78 expect(node.branch2, _isConditionalNode); | |
79 expect(node.branch2.condition, _isVar("c")); | |
80 expect(node.branch2.branch1, _isVar("d")); | |
81 expect(node.branch2.branch2, _isVar("e")); | |
82 }); | |
83 | |
84 group("which must have", () { | |
85 test("an expression after the ?", () { | |
86 expect(() => _parse("a ?"), throwsFormatException); | |
87 expect(() => _parse("a ? && b"), throwsFormatException); | |
88 }); | |
89 | |
90 test("a :", () { | |
91 expect(() => _parse("a ? b"), throwsFormatException); | |
92 expect(() => _parse("a ? b && c"), throwsFormatException); | |
93 }); | |
94 | |
95 test("an expression after the :", () { | |
96 expect(() => _parse("a ? b :"), throwsFormatException); | |
97 expect(() => _parse("a ? b : && c"), throwsFormatException); | |
98 }); | |
99 }); | |
100 }); | |
101 | |
102 group("parses an or expression", () { | |
103 test("with identifiers", () { | |
104 var node = _parse(" a || b "); | |
105 expect(node, _isOrNode); | |
106 expect(node.branch1, _isVar("a")); | |
107 expect(node.branch2, _isVar("b")); | |
108 | |
109 expect(node.span.text, equals("a || b")); | |
110 expect(node.span.start.offset, equals(2)); | |
111 expect(node.span.end.offset, equals(8)); | |
112 }); | |
113 | |
114 test("with nested ands", () { | |
115 // Should parse as "(a && b) || (c && d)". | |
116 // Should not parse as "a && (b || c) && d". | |
117 var node = _parse("a && b || c && d"); | |
118 expect(node, _isOrNode); | |
119 | |
120 expect(node.branch1, _isAndNode); | |
121 expect(node.branch1.branch1, _isVar("a")); | |
122 expect(node.branch1.branch2, _isVar("b")); | |
123 | |
124 expect(node.branch2, _isAndNode); | |
125 expect(node.branch2.branch1, _isVar("c")); | |
126 expect(node.branch2.branch2, _isVar("d")); | |
127 }); | |
128 | |
129 test("with trailing ors", () { | |
130 // Should parse as "a || (b || (c || d))", although it doesn't affect the | |
131 // semantics. | |
132 var node = _parse("a || b || c || d"); | |
133 | |
134 for (var variable in ["a", "b", "c"]) { | |
135 expect(node, _isOrNode); | |
136 expect(node.branch1, _isVar(variable)); | |
137 node = node.branch2; | |
138 } | |
139 expect(node, _isVar("d")); | |
140 }); | |
141 | |
142 test("which must have an expression after the ||", () { | |
143 expect(() => _parse("a ||"), throwsFormatException); | |
144 expect(() => _parse("a || && b"), throwsFormatException); | |
145 }); | |
146 }); | |
147 | |
148 group("parses an and expression", () { | |
149 test("with identifiers", () { | |
150 var node = _parse(" a && b "); | |
151 expect(node, _isAndNode); | |
152 expect(node.branch1, _isVar("a")); | |
153 expect(node.branch2, _isVar("b")); | |
154 | |
155 expect(node.span.text, equals("a && b")); | |
156 expect(node.span.start.offset, equals(2)); | |
157 expect(node.span.end.offset, equals(8)); | |
158 }); | |
159 | |
160 test("with nested nots", () { | |
161 // Should parse as "(!a) && (!b)", obviously. | |
162 // Should not parse as "!(a && (!b))". | |
163 var node = _parse("!a && !b"); | |
164 expect(node, _isAndNode); | |
165 | |
166 expect(node.branch1, _isNotNode); | |
167 expect(node.branch1.child, _isVar("a")); | |
168 | |
169 expect(node.branch2, _isNotNode); | |
170 expect(node.branch2.child, _isVar("b")); | |
171 }); | |
172 | |
173 test("with trailing ands", () { | |
174 // Should parse as "a && (b && (c && d))", although it doesn't affect the | |
175 // semantics since . | |
176 var node = _parse("a && b && c && d"); | |
177 | |
178 for (var variable in ["a", "b", "c"]) { | |
179 expect(node, _isAndNode); | |
180 expect(node.branch1, _isVar(variable)); | |
181 node = node.branch2; | |
182 } | |
183 expect(node, _isVar("d")); | |
184 }); | |
185 | |
186 test("which must have an expression after the &&", () { | |
187 expect(() => _parse("a &&"), throwsFormatException); | |
188 expect(() => _parse("a && && b"), throwsFormatException); | |
189 }); | |
190 }); | |
191 | |
192 group("parses a not expression", () { | |
193 test("with an identifier", () { | |
194 var node = _parse(" ! a "); | |
195 expect(node, _isNotNode); | |
196 expect(node.child, _isVar("a")); | |
197 | |
198 expect(node.span.text, equals("! a")); | |
199 expect(node.span.start.offset, equals(2)); | |
200 expect(node.span.end.offset, equals(5)); | |
201 }); | |
202 | |
203 test("with a parenthesized expression", () { | |
204 var node = _parse("!(a || b)"); | |
205 expect(node, _isNotNode); | |
206 | |
207 expect(node.child, _isOrNode); | |
208 expect(node.child.branch1, _isVar("a")); | |
209 expect(node.child.branch2, _isVar("b")); | |
210 }); | |
211 | |
212 test("with a nested not", () { | |
213 var node = _parse("!!a"); | |
214 expect(node, _isNotNode); | |
215 expect(node.child, _isNotNode); | |
216 expect(node.child.child, _isVar("a")); | |
217 }); | |
218 | |
219 test("which must have an expression after the !", () { | |
220 expect(() => _parse("!"), throwsFormatException); | |
221 expect(() => _parse("! && a"), throwsFormatException); | |
222 }); | |
223 }); | |
224 | |
225 group("parses a parenthesized expression", () { | |
226 test("with an identifier", () { | |
227 var node = _parse("(a)"); | |
228 expect(node, _isVar("a")); | |
229 }); | |
230 | |
231 test("controls precedence", () { | |
232 // Without parentheses, this would parse as "(a || b) ? c : d". | |
233 var node = _parse("a || (b ? c : d)"); | |
234 | |
235 expect(node, _isOrNode); | |
236 expect(node.branch1, _isVar("a")); | |
237 | |
238 expect(node.branch2, _isConditionalNode); | |
239 expect(node.branch2.condition, _isVar("b")); | |
240 expect(node.branch2.branch1, _isVar("c")); | |
241 expect(node.branch2.branch2, _isVar("d")); | |
242 }); | |
243 | |
244 group("which must have", () { | |
245 test("an expression within the ()", () { | |
246 expect(() => _parse("()"), throwsFormatException); | |
247 expect(() => _parse("( && a )"), throwsFormatException); | |
248 }); | |
249 | |
250 test("a matching )", () { | |
251 expect(() => _parse("( a"), throwsFormatException); | |
252 }); | |
253 }); | |
254 }); | |
255 | |
256 group("disallows", () { | |
257 test("an empty selector", () { | |
258 expect(() => _parse(""), throwsFormatException); | |
259 }); | |
260 | |
261 test("too many expressions", () { | |
262 expect(() => _parse("a b"), throwsFormatException); | |
263 }); | |
264 }); | |
265 } | |
266 | |
267 /// Parses [selector] and returns its root node. | |
268 Node _parse(String selector) => new Parser(selector).parse(); | |
269 | |
270 /// A matcher that asserts that a value is a [VariableNode] with the given | |
271 /// [name]. | |
272 Matcher _isVar(String name) => predicate( | |
273 (value) => value is VariableNode && value.name == name, | |
274 'is a variable named "$name"'); | |
OLD | NEW |