Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1344)

Unified Diff: test/backend/platform_selector/parser_test.dart

Issue 997593003: Add a scanner and parser for platform selectors. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: A few more fixes from better future knowledge Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: test/backend/platform_selector/parser_test.dart
diff --git a/test/backend/platform_selector/parser_test.dart b/test/backend/platform_selector/parser_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0b8f38a85a1f6f4e5a778be36631695eee4714bd
--- /dev/null
+++ b/test/backend/platform_selector/parser_test.dart
@@ -0,0 +1,274 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/src/backend/platform_selector/ast.dart';
+import 'package:unittest/src/backend/platform_selector/parser.dart';
+
+/// A matcher that asserts that a value is a [ConditionalNode].
+Matcher _isConditionalNode =
+ new isInstanceOf<ConditionalNode>("ConditionalNode");
+
+/// A matcher that asserts that a value is an [OrNode].
+Matcher _isOrNode = new isInstanceOf<OrNode>("OrNode");
+
+/// A matcher that asserts that a value is an [AndNode].
+Matcher _isAndNode = new isInstanceOf<AndNode>("AndNode");
+
+/// A matcher that asserts that a value is a [NotNode].
+Matcher _isNotNode = new isInstanceOf<NotNode>("NotNode");
+
+void main() {
+ group("parses a conditional expression", () {
+ test("with identifiers", () {
+ var node = _parse(" a ? b : c ");
+ 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
+ expect(node.condition, _isVar("a"));
+ expect(node.branch1, _isVar("b"));
+ expect(node.branch2, _isVar("c"));
+
+ expect(node.span.text, equals("a ? b : c"));
+ expect(node.span.start.offset, equals(2));
+ expect(node.span.end.offset, equals(11));
+ });
+
+ test("with nested ors", () {
+ // Should parse as "(a || b) ? (c || d) : (e || f)".
+ // Should not parse as "a || (b ? (c || d) : (e || f))".
+ // Should not parse as "((a || b) ? (c || d) : e) || f".
+ // Should not parse as "a || (b ? (c || d) : e) || f".
+ var node = _parse("a || b ? c || d : e || f");
+ expect(node, _isConditionalNode);
+
+ expect(node.condition, _isOrNode);
+ expect(node.condition.branch1, _isVar("a"));
+ expect(node.condition.branch2, _isVar("b"));
+
+ expect(node.branch1, _isOrNode);
+ expect(node.branch1.branch1, _isVar("c"));
+ expect(node.branch1.branch2, _isVar("d"));
+
+ expect(node.branch2, _isOrNode);
+ expect(node.branch2.branch1, _isVar("e"));
+ expect(node.branch2.branch2, _isVar("f"));
+ });
+
+ test("with a conditional expression as branch 1", () {
+ // Should parse as "a ? (b ? c : d) : e".
+ var node = _parse("a ? b ? c : d : e");
+ expect(node, _isConditionalNode);
+ expect(node.condition, _isVar("a"));
+ expect(node.branch2, _isVar("e"));
+
+ expect(node.branch1, _isConditionalNode);
+ expect(node.branch1.condition, _isVar("b"));
+ expect(node.branch1.branch1, _isVar("c"));
+ expect(node.branch1.branch2, _isVar("d"));
+ });
+
+ test("with a conditional expression as branch 2", () {
+ // Should parse as "a ? b : (c ? d : e)".
+ // Should not parse as "(a ? b : c) ? d : e".
+ var node = _parse("a ? b : c ? d : e");
+ expect(node, _isConditionalNode);
+ expect(node.condition, _isVar("a"));
+ expect(node.branch1, _isVar("b"));
+
+ expect(node.branch2, _isConditionalNode);
+ expect(node.branch2.condition, _isVar("c"));
+ expect(node.branch2.branch1, _isVar("d"));
+ expect(node.branch2.branch2, _isVar("e"));
+ });
+
+ group("which must have", () {
+ test("an expression after the ?", () {
+ expect(() => _parse("a ?"), throwsFormatException);
+ expect(() => _parse("a ? && b"), throwsFormatException);
+ });
+
+ test("a :", () {
+ expect(() => _parse("a ? b"), throwsFormatException);
+ expect(() => _parse("a ? b && c"), throwsFormatException);
+ });
+
+ test("an expression after the :", () {
+ expect(() => _parse("a ? b :"), throwsFormatException);
+ expect(() => _parse("a ? b : && c"), throwsFormatException);
+ });
+ });
+ });
+
+ group("parses an or expression", () {
+ test("with identifiers", () {
+ var node = _parse(" a || b ");
+ expect(node, _isOrNode);
+ expect(node.branch1, _isVar("a"));
+ expect(node.branch2, _isVar("b"));
+
+ expect(node.span.text, equals("a || b"));
+ expect(node.span.start.offset, equals(2));
+ expect(node.span.end.offset, equals(8));
+ });
+
+ test("with nested ands", () {
+ // Should parse as "(a && b) || (c && d)".
+ // Should not parse as "a && (b || c) && d".
+ var node = _parse("a && b || c && d");
+ expect(node, _isOrNode);
+
+ expect(node.branch1, _isAndNode);
+ expect(node.branch1.branch1, _isVar("a"));
+ expect(node.branch1.branch2, _isVar("b"));
+
+ expect(node.branch2, _isAndNode);
+ expect(node.branch2.branch1, _isVar("c"));
+ expect(node.branch2.branch2, _isVar("d"));
+ });
+
+ test("with trailing ors", () {
+ // Should parse as "a || (b || (c || d))", although it doesn't affect the
+ // semantics.
+ var node = _parse("a || b || c || d");
+
+ for (var variable in ["a", "b", "c"]) {
+ expect(node, _isOrNode);
+ expect(node.branch1, _isVar(variable));
+ node = node.branch2;
+ }
+ expect(node, _isVar("d"));
+ });
+
+ test("which must have an expression after the ||", () {
+ expect(() => _parse("a ||"), throwsFormatException);
+ expect(() => _parse("a || && b"), throwsFormatException);
+ });
+ });
+
+ group("parses an and expression", () {
+ test("with identifiers", () {
+ var node = _parse(" a && b ");
+ expect(node, _isAndNode);
+ expect(node.branch1, _isVar("a"));
+ expect(node.branch2, _isVar("b"));
+
+ expect(node.span.text, equals("a && b"));
+ expect(node.span.start.offset, equals(2));
+ expect(node.span.end.offset, equals(8));
+ });
+
+ test("with nested nots", () {
+ // Should parse as "(!a) && (!b)", obviously.
+ // Should not parse as "!(a && (!b))".
+ var node = _parse("!a && !b");
+ expect(node, _isAndNode);
+
+ expect(node.branch1, _isNotNode);
+ expect(node.branch1.child, _isVar("a"));
+
+ expect(node.branch2, _isNotNode);
+ expect(node.branch2.child, _isVar("b"));
+ });
+
+ test("with trailing ands", () {
+ // Should parse as "a && (b && (c && d))", although it doesn't affect the
+ // semantics since .
+ var node = _parse("a && b && c && d");
+
+ for (var variable in ["a", "b", "c"]) {
+ expect(node, _isAndNode);
+ expect(node.branch1, _isVar(variable));
+ node = node.branch2;
+ }
+ expect(node, _isVar("d"));
+ });
+
+ test("which must have an expression after the &&", () {
+ expect(() => _parse("a &&"), throwsFormatException);
+ expect(() => _parse("a && && b"), throwsFormatException);
+ });
+ });
+
+ group("parses a not expression", () {
+ test("with an identifier", () {
+ var node = _parse(" ! a ");
+ expect(node, _isNotNode);
+ expect(node.child, _isVar("a"));
+
+ expect(node.span.text, equals("! a"));
+ expect(node.span.start.offset, equals(2));
+ expect(node.span.end.offset, equals(5));
+ });
+
+ test("with a parenthesized expression", () {
+ var node = _parse("!(a || b)");
+ expect(node, _isNotNode);
+
+ expect(node.child, _isOrNode);
+ expect(node.child.branch1, _isVar("a"));
+ expect(node.child.branch2, _isVar("b"));
+ });
+
+ test("with a nested not", () {
+ var node = _parse("!!a");
+ expect(node, _isNotNode);
+ expect(node.child, _isNotNode);
+ expect(node.child.child, _isVar("a"));
+ });
+
+ test("which must have an expression after the !", () {
+ expect(() => _parse("!"), throwsFormatException);
+ expect(() => _parse("! && a"), throwsFormatException);
+ });
+ });
+
+ group("parses a parenthesized expression", () {
+ test("with an identifier", () {
+ var node = _parse("(a)");
+ expect(node, _isVar("a"));
+ });
+
+ test("controls precedence", () {
+ // Without parentheses, this would parse as "(a || b) ? c : d".
+ var node = _parse("a || (b ? c : d)");
+
+ expect(node, _isOrNode);
+ expect(node.branch1, _isVar("a"));
+
+ expect(node.branch2, _isConditionalNode);
+ expect(node.branch2.condition, _isVar("b"));
+ expect(node.branch2.branch1, _isVar("c"));
+ expect(node.branch2.branch2, _isVar("d"));
+ });
+
+ group("which must have", () {
+ test("an expression within the ()", () {
+ expect(() => _parse("()"), throwsFormatException);
+ expect(() => _parse("( && a )"), throwsFormatException);
+ });
+
+ test("a matching )", () {
+ expect(() => _parse("( a"), throwsFormatException);
+ });
+ });
+ });
+
+ group("disallows", () {
+ test("an empty selector", () {
+ expect(() => _parse(""), throwsFormatException);
+ });
+
+ test("too many expressions", () {
+ expect(() => _parse("a b"), throwsFormatException);
+ });
+ });
+}
+
+/// Parses [selector] and returns its root node.
+Node _parse(String selector) => new Parser(selector).parse();
+
+/// A matcher that asserts that a value is a [VariableNode] with the given
+/// [name].
+Matcher _isVar(String name) => predicate(
+ (value) => value is VariableNode && value.name == name,
+ 'is a variable named "$name"');

Powered by Google App Engine
This is Rietveld 408576698