Index: tests/language/assert_lexical_scope_test.dart |
diff --git a/tests/language/assert_lexical_scope_test.dart b/tests/language/assert_lexical_scope_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..cc3388a84276fb6719902b7a94dab2f4b6a9d442 |
--- /dev/null |
+++ b/tests/language/assert_lexical_scope_test.dart |
@@ -0,0 +1,225 @@ |
+// Copyright (c) 2012, 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. |
+ |
+/** A function that accepts 0..2 arguments and records calls. */ |
+void poly([a, b]) { |
+ polyCount++; |
+ polyArg = a; |
+} |
+ |
+/** First argument of most recent call to [poly]. */ |
+var polyArg = 0; |
+ |
+/** Number of calls to [poly]. */ |
+var polyCount = 0; |
+ |
+// Four (Super)classes that declare an "assert" member. |
+ |
+class SuperGet { |
+ /** Declare "assert" as a getter. */ |
+ get assert => poly; |
+ |
+ /** |
+ * A method that shold see an 'assert' declaration in scope and not |
+ * not act as an assertion. |
+ */ |
+ void lexicalAssert(x) { |
+ assert(x); |
+ } |
+} |
+ |
+class SuperMethod { |
+ /** Declare "assert" as a method. */ |
+ assert([a, b]) => poly(a, b); |
+ |
+ void lexicalAssert(x) { |
+ assert(x); |
+ } |
+} |
+ |
+class SuperField { |
+ /** Declare "assert" as a field. */ |
+ var assert; |
+ SuperField() : assert = poly; |
+ |
+ void lexicalAssert(x) { |
+ assert(x); |
+ } |
+} |
+ |
+class SuperNon { |
+ /** Implementation of "assert" calls on this. */ |
+ noSuchMethod(x, y) { |
+ switch (y.length) { |
+ case 0: return poly(); |
+ case 1: return poly(y[0]); |
+ case 2: return poly(y[0], y[1]); |
+ } |
+ } |
+ |
+ void lexicalAssert(x) { |
+ // Hack, since there is no lexically enclosing 'assert' declaration here, |
+ // so just act as if there was to avoid special casing it in the test. |
+ poly(x); |
+ } |
+} |
+ |
+// Corresponding sub-classes that read/call "assert" in different ways. |
+// In every case except "assert(exp);" (in the "assert1" methods) this should |
+// access the superclass member. |
+ |
+class SubGet extends SuperGet { |
+ /** Read assert as a variable. */ |
+ void getAssert(x) { |
+ assert; |
+ } |
+ /** Call "assert" with zero arguments. */ |
+ void assert0(x) { |
+ assert(); |
+ } |
+ /** Make an actual assertion. */ |
+ void assert1(x) { |
+ assert(x); |
+ } |
+ /** Call "assert" with one argument in expression context. */ |
+ void assertExp(x) { |
+ var z = assert(x); |
+ } |
+ /** Call "assert" with two arguments. */ |
+ void assert2(x) { |
+ assert(x, x); |
+ } |
+} |
+ |
+class SubMethod extends SuperMethod { |
+ void getAssert(x) { |
+ assert; |
+ } |
+ void assert0(x) { |
+ assert(); |
+ } |
+ void assert1(x) { |
+ assert(x); |
+ } |
+ void assertExp(x) { |
+ var z = assert(x); |
+ } |
+ void assert2(x) { |
+ assert(x, x); |
+ } |
+} |
+ |
+class SubField extends SuperField { |
+ void getAssert(x) { |
+ assert; |
+ } |
+ void assert0(x) { |
+ assert(); |
+ } |
+ void assert1(x) { |
+ assert(x); |
+ } |
+ void assertExp(x) { |
+ var z = assert(x); |
+ } |
+ void assert2(x) { |
+ assert(x, x); |
+ } |
+} |
+ |
+class SubNon extends SuperNon { |
+ void getAssert(x) { |
+ assert; |
+ } |
+ assert0(x) { |
+ assert(); |
+ } |
+ void assert1(x) { |
+ assert(x); |
+ } |
+ void assertExp(x) { |
+ var z = assert(x); |
+ } |
+ void assert2(x) { |
+ assert(x, x); |
+ } |
+} |
+ |
+ |
+testAssertDeclared() { |
+ var get = new SubGet(); |
+ var method = new SubMethod(); |
+ var field = new SubField(); |
+ var non = new SubNon(); |
+ |
+ void expectCallsPoly(code, [bool noArgument = false]) { |
+ int oldPolyCount = polyCount; |
+ int newPolyArg = polyArg + 1; |
+ int expectedPolyArg = noArgument ? null : newPolyArg; |
+ code(newPolyArg); |
+ Expect.equals(oldPolyCount + 1, polyCount); |
+ Expect.equals(expectedPolyArg, polyArg); |
+ if (noArgument) polyArg = newPolyArg; |
+ } |
+ |
+ void expectAssert(code) { |
+ int oldPolyCount = polyCount; |
+ // Detect whether asserts are enabled. |
+ bool assertsEnabled = false; |
+ assert(assertsEnabled = true); |
+ try { |
+ code(polyArg + 1); |
+ // If asserts are enabled, we should not get here. |
+ // If they are not, the call does nothing. |
+ if (assertsEnabled) { |
+ Expect.fail("Didn't call assert with asserts enabled."); |
+ } |
+ } on AssertionError catch (e) { |
+ if (!assertsEnabled) Expect.fail("Called assert with asserts disabled?"); |
+ } |
+ Expect.equals(oldPolyCount, polyCount); |
+ } |
+ |
+ // Sanity check. |
+ expectCallsPoly(poly); |
+ |
+ // Doesn't fail to read "assert". |
+ get.getAssert(0); |
+ method.getAssert(0); |
+ field.getAssert(0); |
+ expectCallsPoly(non.getAssert, true); // Hits 'noSuchMethod' for the getter. |
+ |
+ // Check when 'assert' is a superclass member declaration (or, simulated with |
+ // noSuchMethod). |
+ void testSuperAssert(object) { |
+ expectCallsPoly(object.assert0, true); |
+ expectAssert(object.assert1); |
+ expectCallsPoly(object.assertExp); |
+ expectCallsPoly(object.assert2); |
+ expectCallsPoly(object.lexicalAssert); |
+ } |
+ |
+ testSuperAssert(get); |
+ testSuperAssert(method); |
+ testSuperAssert(field); |
+ testSuperAssert(non); |
+ |
+ // A local declaration will inhibit assert-behavior. |
+ |
+ expectCallsPoly((x) { |
+ // Declare "assert" as a local variable. |
+ var assert = poly; |
+ assert(x); |
+ }); |
+ |
+ expectCallsPoly((x) { |
+ // Declare "assert" as a local function. |
+ void assert(x) => poly(x); |
+ assert(x); |
+ }); |
+} |
+ |
+main() { |
+ testAssertDeclared(); |
+} |