diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart index df8bffa7791..954a653ac21 100644 --- a/pkg/expect/lib/expect.dart +++ b/pkg/expect/lib/expect.dart @@ -85,12 +85,12 @@ class Expect { * This finds the first point where two strings differ, and returns * a text describing the difference. * - * For small strings (length less than 20) nothing is done, and null is + * For small strings (length less than 20) nothing is done, and "" is * returned. Small strings can be compared visually, but for longer strings * only a slice containing the first difference will be shown. */ static String _stringDifference(String expected, String actual) { - if (expected.length < 20 && actual.length < 20) return null; + if (expected.length < 20 && actual.length < 20) return ""; for (int i = 0; i < expected.length && i < actual.length; i++) { if (expected.codeUnitAt(i) != actual.codeUnitAt(i)) { int start = i; @@ -106,18 +106,18 @@ class Expect { "Found: <$truncActual>"; } } - return null; + return ""; } /** * Checks whether the expected and actual values are equal (using `==`). */ - static void equals(var expected, var actual, [String reason = null]) { + static void equals(var expected, var actual, [String reason = ""]) { if (expected == actual) return; String msg = _getMessage(reason); if (expected is String && actual is String) { String stringDifference = _stringDifference(expected, actual); - if (stringDifference != null) { + if (stringDifference.isNotEmpty) { _fail("Expect.equals($stringDifference$msg) fails."); } _fail("Expect.equals(expected: <${_escapeString(expected)}>" @@ -129,7 +129,7 @@ class Expect { /** * Checks whether the actual value is a bool and its value is true. */ - static void isTrue(var actual, [String reason = null]) { + static void isTrue(var actual, [String reason = ""]) { if (_identical(actual, true)) return; String msg = _getMessage(reason); _fail("Expect.isTrue($actual$msg) fails."); @@ -138,7 +138,7 @@ class Expect { /** * Checks whether the actual value is a bool and its value is false. */ - static void isFalse(var actual, [String reason = null]) { + static void isFalse(var actual, [String reason = ""]) { if (_identical(actual, false)) return; String msg = _getMessage(reason); _fail("Expect.isFalse($actual$msg) fails."); @@ -147,7 +147,7 @@ class Expect { /** * Checks whether [actual] is null. */ - static void isNull(actual, [String reason = null]) { + static void isNull(actual, [String reason = ""]) { if (null == actual) return; String msg = _getMessage(reason); _fail("Expect.isNull(actual: <$actual>$msg) fails."); @@ -156,7 +156,7 @@ class Expect { /** * Checks whether [actual] is not null. */ - static void isNotNull(actual, [String reason = null]) { + static void isNotNull(actual, [String reason = ""]) { if (null != actual) return; String msg = _getMessage(reason); _fail("Expect.isNotNull(actual: <$actual>$msg) fails."); @@ -166,7 +166,7 @@ class Expect { * Checks whether the expected and actual values are identical * (using `identical`). */ - static void identical(var expected, var actual, [String reason = null]) { + static void identical(var expected, var actual, [String reason = ""]) { if (_identical(expected, actual)) return; String msg = _getMessage(reason); if (expected is String && actual is String) { @@ -187,17 +187,20 @@ class Expect { * That is, `objects[i]` is identical to objects with indices in * `_findEquivalences(objects)[i]`. * - * Uses `null` for objects that are only identical to themselves. + * Uses `[]` for objects that are only identical to themselves. */ static List> _findEquivalences(List objects) { - var equivalences = new List>(objects.length); + var equivalences = new List>.generate(objects.length, (_) => []); for (int i = 0; i < objects.length; i++) { - if (equivalences[i] != null) continue; + if (equivalences[i].isNotEmpty) continue; var o = objects[i]; for (int j = i + 1; j < objects.length; j++) { - if (equivalences[j] != null) continue; + if (equivalences[j].isNotEmpty) continue; if (_identical(o, objects[j])) { - equivalences[j] = (equivalences[i] ??= [i])..add(j); + if (equivalences[i].isEmpty) { + equivalences[i].add(i); + } + equivalences[j] = equivalences[i]..add(j); } } } @@ -211,7 +214,7 @@ class Expect { buffer.write(separator); separator = ","; var equivalence = equivalences[i]; - if (equivalence == null) { + if (equivalence.isEmpty) { buffer.write('_'); } else { int first = equivalence[0]; @@ -223,12 +226,12 @@ class Expect { } } - static void allIdentical(Iterable objects, [String reason]) { + static void allIdentical(List objects, [String reason = ""]) { if (objects.length <= 1) return; String msg = _getMessage(reason); var equivalences = _findEquivalences(objects); var first = equivalences[0]; - if (first != null && first.length == objects.length) return; + if (first.isNotEmpty && first.length == objects.length) return; var buffer = new StringBuffer("Expect.allIdentical(["); _writeEquivalences(objects, equivalences, buffer); buffer..write("]")..write(msg)..write(")"); @@ -239,7 +242,7 @@ class Expect { * Checks whether the expected and actual values are *not* identical * (using `identical`). */ - static void notIdentical(var unexpected, var actual, [String reason = null]) { + static void notIdentical(var unexpected, var actual, [String reason = ""]) { if (!_identical(unexpected, actual)) return; String msg = _getMessage(reason); _fail("Expect.notIdentical(expected and actual: <$actual>$msg) fails."); @@ -248,13 +251,13 @@ class Expect { /** * Checks that no two [objects] are `identical`. */ - static void allDistinct(List objects, [String reason = null]) { + static void allDistinct(List objects, [String reason = ""]) { String msg = _getMessage(reason); var equivalences = _findEquivalences(objects); bool hasEquivalence = false; for (int i = 0; i < equivalences.length; i++) { - if (equivalences[i] != null) { + if (equivalences[i].isNotEmpty) { hasEquivalence = true; break; } @@ -278,8 +281,8 @@ class Expect { * value 4 significant digits smaller than the value given for expected. */ static void approxEquals(num expected, num actual, - [num tolerance = null, String reason = null]) { - if (tolerance == null) { + [num tolerance = -1, String reason = ""]) { + if (tolerance < 0) { tolerance = (expected / 1e4).abs(); } // Note: use !( <= ) rather than > so we fail on NaNs @@ -290,7 +293,7 @@ class Expect { 'tolerance:<$tolerance>$msg) fails'); } - static void notEquals(unexpected, actual, [String reason = null]) { + static void notEquals(unexpected, actual, [String reason = ""]) { if (unexpected != actual) return; String msg = _getMessage(reason); _fail("Expect.notEquals(unexpected: <$unexpected>, actual:<$actual>$msg) " @@ -303,7 +306,7 @@ class Expect { * used by the standard list implementation. It should also produce nicer * error messages than just calling `Expect.equals(expected, actual)`. */ - static void listEquals(List expected, List actual, [String reason = null]) { + static void listEquals(List expected, List actual, [String reason = ""]) { String msg = _getMessage(reason); int n = (expected.length < actual.length) ? expected.length : actual.length; for (int i = 0; i < n; i++) { @@ -327,7 +330,7 @@ class Expect { * the semantics of [Map.containsKey] to determine what "same" means. For * each key, checks that the values in both maps are equal using `==`. */ - static void mapEquals(Map expected, Map actual, [String reason = null]) { + static void mapEquals(Map expected, Map actual, [String reason = ""]) { String msg = _getMessage(reason); // Make sure all of the values are present in both, and they match. @@ -352,7 +355,7 @@ class Expect { * this method shows where the mismatch starts and ends. */ static void stringEquals(String expected, String actual, - [String reason = null]) { + [String reason = ""]) { if (expected == actual) return; String msg = _getMessage(reason); @@ -435,7 +438,7 @@ class Expect { * every element of [actual] is also in [expected]. */ static void setEquals(Iterable expected, Iterable actual, - [String reason = null]) { + [String reason = ""]) { final missingSet = new Set.from(expected); missingSet.removeAll(actual); final extraSet = new Set.from(actual); @@ -517,6 +520,8 @@ class Expect { } } + static bool _defaultCheck([dynamic e]) => true; + /** * Calls the function [f] and verifies that it throws a `T`. * The optional [check] function can provide additional validation @@ -533,8 +538,13 @@ class Expect { * exception is not caught by [Expect.throws]. The test is still considered * failing. */ - static void throws(void f(), [bool check(T error), String reason]) { - String msg = reason == null ? "" : "($reason)"; + static void throws(void f(), + [bool check(T error) = _defaultCheck, String reason = ""]) { + // TODO(vsm): Make check nullable. Existing tests pass null to set + // a reason. + check = check ?? _defaultCheck; + reason = reason ?? ""; + String msg = reason.isEmpty ? "" : "($reason)"; if (f is! Function()) { // Only throws from executing the function body should count as throwing. // The failure to even call `f` should throw outside the try/catch. @@ -545,7 +555,7 @@ class Expect { } on Object catch (e, s) { // A test failure doesn't count as throwing. if (e is ExpectException) rethrow; - if (e is T && (check == null || check(e))) return; + if (e is T && check(e as dynamic)) return; // Throws something unexpected. String type = ""; if (T != dynamic && T != Object) { @@ -557,45 +567,44 @@ class Expect { _fail('Expect.throws$msg fails: Did not throw'); } - static void throwsArgumentError(void f(), [String reason]) { - Expect.throws( - f, (error) => error is ArgumentError, reason ?? "ArgumentError"); + static void throwsArgumentError(void f(), [String reason = "ArgumentError"]) { + Expect.throws(f, (error) => error is ArgumentError, reason); } - static void throwsAssertionError(void f(), [String reason]) { - Expect.throws( - f, (error) => error is AssertionError, reason ?? "AssertionError"); + static void throwsAssertionError(void f(), + [String reason = "AssertionError"]) { + Expect.throws(f, (error) => error is AssertionError, reason); } - static void throwsCastError(void f(), [String reason]) { - Expect.throws(f, (error) => error is CastError, reason ?? "CastError"); + static void throwsCastError(void f(), [String reason = "CastError"]) { + Expect.throws(f, (error) => error is CastError, reason); } - static void throwsFormatException(void f(), [String reason]) { - Expect.throws( - f, (error) => error is FormatException, reason ?? "FormatException"); + static void throwsFormatException(void f(), + [String reason = "FormatException"]) { + Expect.throws(f, (error) => error is FormatException, reason); } - static void throwsNoSuchMethodError(void f(), [String reason]) { - Expect.throws(f, (error) => error is NoSuchMethodError, - reason ?? "NoSuchMethodError"); + static void throwsNoSuchMethodError(void f(), + [String reason = "NoSuchMethodError"]) { + Expect.throws(f, (error) => error is NoSuchMethodError, reason); } - static void throwsRangeError(void f(), [String reason]) { - Expect.throws(f, (error) => error is RangeError, reason ?? "RangeError"); + static void throwsRangeError(void f(), [String reason = "RangeError"]) { + Expect.throws(f, (error) => error is RangeError, reason); } - static void throwsStateError(void f(), [String reason]) { - Expect.throws(f, (error) => error is StateError, reason ?? "StateError"); + static void throwsStateError(void f(), [String reason = "StateError"]) { + Expect.throws(f, (error) => error is StateError, reason); } - static void throwsTypeError(void f(), [String reason]) { - Expect.throws(f, (error) => error is TypeError, reason ?? "TypeError"); + static void throwsTypeError(void f(), [String reason = "TypeError"]) { + Expect.throws(f, (error) => error is TypeError, reason); } - static void throwsUnsupportedError(void f(), [String reason]) { - Expect.throws( - f, (error) => error is UnsupportedError, reason ?? "UnsupportedError"); + static void throwsUnsupportedError(void f(), + [String reason = "UnsupportedError"]) { + Expect.throws(f, (error) => error is UnsupportedError, reason); } /// Reports that there is an error in the test itself and not the code under @@ -608,7 +617,7 @@ class Expect { } /// Checks that [object] has type [T]. - static void type(Object object, [String reason]) { + static void type(dynamic object, [String reason = ""]) { if (object is T) return; String msg = _getMessage(reason); _fail("Expect.type($object is $T$msg) fails " @@ -616,7 +625,7 @@ class Expect { } /// Checks that [object] does not have type [T]. - static void notType(Object object, [String reason]) { + static void notType(dynamic object, [String reason = ""]) { if (object is! T) return; String msg = _getMessage(reason); _fail("Expect.type($object is! $T$msg) fails" @@ -648,7 +657,7 @@ class Expect { } static String _getMessage(String reason) => - (reason == null) ? "" : ", '$reason'"; + (reason.isEmpty) ? "" : ", '$reason'"; @alwaysThrows static void _fail(String message) { diff --git a/pkg/expect/lib/matchers_lite.dart b/pkg/expect/lib/matchers_lite.dart index 004e37e74cc..5b8d11e350d 100644 --- a/pkg/expect/lib/matchers_lite.dart +++ b/pkg/expect/lib/matchers_lite.dart @@ -18,7 +18,7 @@ import "expect.dart" show Expect; typedef Matcher = void Function(Object actual); -void expect(Object actual, Object expected) { +void expect(dynamic actual, dynamic expected) { if (expected is Matcher) { expected(actual); } else { @@ -27,7 +27,8 @@ void expect(Object actual, Object expected) { } Matcher unorderedEquals(Iterable expected) { - return (Object actual) => Expect.setEquals(expected, actual); + return (Object actual) => + Expect.setEquals(expected, actual as Iterable); } fail(String message) { @@ -40,7 +41,7 @@ Matcher same(Object expected) { Matcher equals(Object expected) { if (expected is String) { - return (Object actual) => Expect.stringEquals(expected, actual); + return (Object actual) => Expect.stringEquals(expected, actual as String); } else if (expected is Iterable) { return (dynamic actual) => Expect.listEquals(expected.toList(), actual.toList()); diff --git a/pkg/expect/lib/minitest.dart b/pkg/expect/lib/minitest.dart index 81c53f21418..350b6aa6b9e 100644 --- a/pkg/expect/lib/minitest.dart +++ b/pkg/expect/lib/minitest.dart @@ -90,11 +90,9 @@ void group(String description, body()) { void test(String description, body()) { // TODO(rnystrom): Do something useful with the description. for (var group in _groups) { - if (group.setUpFunction != null) { - var result = group.setUpFunction(); - if (result is Future) { - Expect.testError("setUp() does not support asynchronous functions."); - } + var result = group.setUpFunction(); + if (result is Future) { + Expect.testError("setUp() does not support asynchronous functions."); } } @@ -106,12 +104,9 @@ void test(String description, body()) { } finally { for (var i = _groups.length - 1; i >= 0; i--) { var group = _groups[i]; - if (group.tearDownFunction != null) { - var result = group.tearDownFunction(); - if (result is Future) { - Expect.testError( - "tearDown() does not support asynchronous functions."); - } + var result = group.tearDownFunction(); + if (result is Future) { + Expect.testError("tearDown() does not support asynchronous functions."); } } } @@ -119,17 +114,17 @@ void test(String description, body()) { void setUp(body()) { // Can't define multiple setUps at the same level. - assert(_groups.last.setUpFunction == null); + assert(_groups.last.setUpFunction == _defaultAction); _groups.last.setUpFunction = body; } void tearDown(body()) { // Can't define multiple tearDowns at the same level. - assert(_groups.last.tearDownFunction == null); + assert(_groups.last.tearDownFunction == _defaultAction); _groups.last.tearDownFunction = body; } -void expect(Object actual, Object expected, {String reason}) { +void expect(Object actual, Object expected, {String reason = ""}) { // TODO(rnystrom): Do something useful with reason. if (expected is! _Expectation) { expected = equals(expected); @@ -152,10 +147,10 @@ Object notEquals(Object value) => new _Expectation((actual) { }); Object unorderedEquals(Object value) => new _Expectation((actual) { - Expect.setEquals(value, actual); + Expect.setEquals(value as Iterable, actual as Iterable); }); -Object predicate(bool fn(Object value), [String description]) => +Object predicate(bool fn(Object value), [String description = ""]) => new _Expectation((actual) { Expect.isTrue(fn(actual), description); }); @@ -179,7 +174,7 @@ Object same(Object value) => new _Expectation((actual) { }); Object closeTo(num value, num tolerance) => new _Expectation((actual) { - Expect.approxEquals(value, actual, tolerance); + Expect.approxEquals(value, actual as num, tolerance); }); /// Succeeds if the actual value is any of the given strings. Unlike matcher's @@ -192,13 +187,15 @@ Object anyOf(List expected) => new _Expectation((actual) { fail("Expected $actual to be one of $expected."); }); +_defaultAction() {} + /// One level of group() nesting to track an optional [setUp()] and [tearDown()] /// function for the group. /// /// There is also an implicit top level group. class _Group { - _Action setUpFunction; - _Action tearDownFunction; + _Action setUpFunction = _defaultAction; + _Action tearDownFunction = _defaultAction; } /// A wrapper around an expectation function.