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