| 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 |