Fix 2 tests (#93)
Fix two tests to be Dart 2 type-safe.
Clean up test/wrapper_test.dart signficantly.
Add enough type annotations to test/unmodifiable_collection_test.dart
to get the necessary inference.
Update dependency on SDK to allow using the new `Invocation` constructor.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10d5842..3af6a93 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## 1.14.10
-* Fix the parameter names in overridden methods to match the source.
+* Fix the parameter names in overridden methods to match the source.
+* Make tests Dart 2 type-safe.
## 1.14.9
@@ -13,7 +14,7 @@
* Deprecated `Delegating{Name}.typed` static methods in favor of the new Dart 2
`cast` methods. For example, `DelegatingList.typed<String>(list)` can now be
- written as `list.cast<String>()`.
+ written as `list.cast<String>()`.
## 1.14.7
@@ -37,7 +38,7 @@
## 1.14.4
* Add implementation stubs of upcoming Dart 2.0 core library methods, namely
- new methods for classes that implement `Iterable`, `List`, `Map`, `Queue`,
+ new methods for classes that implement `Iterable`, `List`, `Map`, `Queue`,
and `Set`.
## 1.14.3
diff --git a/pubspec.yaml b/pubspec.yaml
index d3bec8b..06f183e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,10 +6,10 @@
environment:
# Required for Dart 2.0 collection changes.
- sdk: '>=2.0.0-dev.36.0 <2.0.0'
+ sdk: '>=2.0.0-dev.49.0 <2.0.0'
dev_dependencies:
build_runner: ^0.8.0
build_test: ^0.10.0
build_web_compilers: ^0.3.1
- test: ^0.12.0
+ test: ^0.12.35
diff --git a/test/unmodifiable_collection_test.dart b/test/unmodifiable_collection_test.dart
index a6705f6..c7b539f 100644
--- a/test/unmodifiable_collection_test.dart
+++ b/test/unmodifiable_collection_test.dart
@@ -37,13 +37,13 @@
testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "empty");
aSet = new Set();
testUnmodifiableSet(aSet, const UnmodifiableSetView.empty(), "const empty");
- aSet = new Set.from([42]);
+ aSet = new Set.of([42]);
testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "single-42");
- aSet = new Set.from([7]);
+ aSet = new Set.of([7]);
testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "single!42");
- aSet = new Set.from([1, 42, 10]);
+ aSet = new Set.of([1, 42, 10]);
testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "three-42");
- aSet = new Set.from([1, 7, 10]);
+ aSet = new Set.of([1, 7, 10]);
testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "three!42");
}
@@ -311,8 +311,8 @@
});
}
-void testNoWriteList(List original, List wrapped, String name) {
- List copy = new List.from(original);
+void testNoWriteList(List<int> original, List<int> wrapped, String name) {
+ var copy = new List.of(original);
testThrows(name, thunk) {
test(name, () {
@@ -345,7 +345,7 @@
}
void testWriteList(List<int> original, List wrapped, String name) {
- var copy = new List<int>.from(original);
+ var copy = new List.of(original);
test("$name - []=", () {
if (original.isNotEmpty) {
@@ -361,7 +361,7 @@
});
test("$name - sort", () {
- List sortCopy = new List.from(original);
+ List sortCopy = new List.of(original);
sortCopy.sort();
wrapped.sort();
expect(original, orderedEquals(sortCopy));
@@ -391,8 +391,9 @@
});
}
-void testNoChangeLengthList(List original, List wrapped, String name) {
- List copy = new List.from(original);
+void testNoChangeLengthList(
+ List<int> original, List<int> wrapped, String name) {
+ var copy = new List.of(original);
void testThrows(String name, thunk) {
test(name, () {
@@ -455,8 +456,8 @@
});
}
-void testReadSet(Set original, Set wrapped, String name) {
- Set copy = new Set.from(original);
+void testReadSet(Set<int> original, Set<int> wrapped, String name) {
+ var copy = new Set.of(original);
test("$name - containsAll", () {
expect(wrapped.containsAll(copy), isTrue);
@@ -468,27 +469,27 @@
test("$name - intersection", () {
expect(wrapped.intersection(new Set()), isEmpty);
expect(wrapped.intersection(copy), unorderedEquals(original));
- expect(wrapped.intersection(new Set.from([42])),
- new Set.from(original.contains(42) ? [42] : []));
+ expect(wrapped.intersection(new Set.of([42])),
+ new Set.of(original.contains(42) ? [42] : []));
});
test("$name - union", () {
expect(wrapped.union(new Set()), unorderedEquals(original));
expect(wrapped.union(copy), unorderedEquals(original));
- expect(wrapped.union(new Set.from([42])),
- equals(original.union(new Set.from([42]))));
+ expect(wrapped.union(new Set.of([42])),
+ equals(original.union(new Set.of([42]))));
});
test("$name - difference", () {
expect(wrapped.difference(new Set()), unorderedEquals(original));
expect(wrapped.difference(copy), isEmpty);
- expect(wrapped.difference(new Set.from([42])),
- equals(original.difference(new Set.from([42]))));
+ expect(wrapped.difference(new Set.of([42])),
+ equals(original.difference(new Set.of([42]))));
});
}
-void testNoChangeSet(Set original, Set wrapped, String name) {
- List originalElements = original.toList();
+void testNoChangeSet(Set<int> original, Set<int> wrapped, String name) {
+ var originalElements = original.toList();
testThrows(name, thunk) {
test(name, () {
@@ -588,8 +589,8 @@
});
}
-testNoChangeMap(Map original, Map wrapped, String name) {
- Map copy = new Map.from(original);
+testNoChangeMap(Map<int, int> original, Map<int, int> wrapped, String name) {
+ var copy = new Map.of(original);
testThrows(name, thunk) {
test(name, () {
diff --git a/test/wrapper_test.dart b/test/wrapper_test.dart
index 0df053c..bb8f90f 100644
--- a/test/wrapper_test.dart
+++ b/test/wrapper_test.dart
@@ -25,253 +25,237 @@
/// Utility class to record a member access and a member access on a wrapped
/// object, and compare them for equality.
+///
+/// Use as `(expector..someAccess()).equals.someAccess();`.
+/// Alle the intercepted member accesses returns `null`.
abstract class Expector {
- getWrappedObject(action(Invocation i));
- // Hack to test assignment ([]=) because it doesn't return the result
- // of the member call. Instead use (expect..[4]=5).equal[4]=5 where
- // you would normally use expect[4].equals[4] for non-assignments.
+ wrappedChecker(Invocation i);
+ // After calling any member on the Expector, equals is an object that expects
+ // the *same* invocation on the wrapped object.
var equals;
- noSuchMethod(Invocation m) => new _Equals(equals = getWrappedObject((m2) {
- testInvocations(m, m2);
- }));
+ noSuchMethod(Invocation i) {
+ equals = wrappedChecker(i);
+ return null;
+ }
- // dartanalyzer complains if this method is named `toString()`, since, if it
- // truly overrides Object's `toString()`, it should return a String.
- asString() => new _Equals(equals = getWrappedObject((m2) {
- testInvocations(TO_STRING_INVOCATION, m2);
- }));
+ toString() {
+ // Cannot return an _Equals object since toString must return a String.
+ // Just set equals and return a string.
+ equals = wrappedChecker(toStringInvocation);
+ return "";
+ }
}
-// An object with a field called "equals", only introduced into the
-// flow to allow writing expect.xxx.equals.xxx.
-class _Equals {
- final equals;
- _Equals(this.equals);
+// Parameterization of noSuchMethod. Calls [_action] on every
+// member invocation.
+class InvocationChecker {
+ Invocation _expected;
+ InvocationChecker(this._expected);
+ noSuchMethod(Invocation actual) {
+ testInvocations(_expected, actual);
+ return null;
+ }
+
+ toString() {
+ testInvocations(_expected, toStringInvocation);
+ return "";
+ }
+ // Could also handle runtimeType, hashCode and == the same way as
+ // toString, but we are not testing them since collections generally
+ // don't override those and so the wrappers don't forward those.
}
-class SyntheticInvocation implements Invocation {
- static const int METHOD = 0x00;
- static const int GETTER = 0x01;
- static const int SETTER = 0x02;
- final Symbol memberName;
- final List positionalArguments;
- final Map<Symbol, dynamic> namedArguments;
- final int _type;
- const SyntheticInvocation(this.memberName, this.positionalArguments,
- this.namedArguments, this._type);
+final toStringInvocation = new Invocation.method(#toString, const []);
- List<Type> get typeArguments => const <Type>[];
-
- bool get isMethod => _type == METHOD;
-
- bool get isGetter => _type == GETTER;
-
- bool get isSetter => _type == SETTER;
-
- bool get isAccessor => isGetter || isSetter;
+// InvocationCheckers with types Queue, Set, List or Iterable to allow them as
+// argument to DelegatingIterable/Set/List/Queue.
+class IterableInvocationChecker<T> extends InvocationChecker
+ implements Iterable<T> {
+ IterableInvocationChecker(Invocation expected) : super(expected);
}
-// Parameterization of noSuchMethod.
-class NSM {
- Function _action;
- NSM(this._action);
- noSuchMethod(Invocation i) => _action(i);
+class ListInvocationChecker<T> extends InvocationChecker implements List<T> {
+ ListInvocationChecker(Invocation expected) : super(expected);
}
-const TO_STRING_INVOCATION = const SyntheticInvocation(
- #toString, const [], const {}, SyntheticInvocation.METHOD);
+class SetInvocationChecker<T> extends InvocationChecker implements Set<T> {
+ SetInvocationChecker(Invocation expected) : super(expected);
+}
-// LikeNSM, but has types Iterable, Set and List to allow it as
-// argument to DelegatingIterable/Set/List.
-class IterableNSM extends NSM implements Iterable, Set, List, Queue {
- IterableNSM(action(Invocation i)) : super(action);
- toString() => super.noSuchMethod(TO_STRING_INVOCATION) as String;
+class QueueInvocationChecker<T> extends InvocationChecker implements Queue<T> {
+ QueueInvocationChecker(Invocation expected) : super(expected);
+}
- Null cast<T>();
- Null retype<T>();
+class MapInvocationChecker<K, V> extends InvocationChecker
+ implements Map<K, V> {
+ MapInvocationChecker(Invocation expected) : super(expected);
}
// Expector that wraps in DelegatingIterable.
-class IterableExpector extends Expector {
- getWrappedObject(void action(Invocation i)) {
- return new DelegatingIterable(new IterableNSM(action));
- }
+class IterableExpector<T> extends Expector implements Iterable<T> {
+ wrappedChecker(Invocation i) =>
+ new DelegatingIterable<T>(new IterableInvocationChecker<T>(i));
}
// Expector that wraps in DelegatingList.
-class ListExpector extends Expector {
- getWrappedObject(void action(Invocation i)) {
- return new DelegatingList(new IterableNSM(action));
- }
+class ListExpector<T> extends Expector implements List<T> {
+ wrappedChecker(Invocation i) =>
+ new DelegatingList<T>(new ListInvocationChecker<T>(i));
}
// Expector that wraps in DelegatingSet.
-class SetExpector extends Expector {
- getWrappedObject(void action(Invocation i)) {
- return new DelegatingSet(new IterableNSM(action));
- }
+class SetExpector<T> extends Expector implements Set<T> {
+ wrappedChecker(Invocation i) =>
+ new DelegatingSet<T>(new SetInvocationChecker<T>(i));
}
// Expector that wraps in DelegatingSet.
-class QueueExpector extends Expector {
- getWrappedObject(void action(Invocation i)) {
- return new DelegatingQueue(new IterableNSM(action));
- }
-}
-
-// Like NSM but implements Map to allow as argument for DelegatingMap.
-class MapNSM extends NSM implements Map {
- MapNSM(action(Invocation i)) : super(action);
- toString() => super.noSuchMethod(TO_STRING_INVOCATION) as String;
+class QueueExpector<T> extends Expector implements Queue<T> {
+ wrappedChecker(Invocation i) =>
+ new DelegatingQueue<T>(new QueueInvocationChecker<T>(i));
}
// Expector that wraps in DelegatingMap.
-class MapExpector extends Expector {
- getWrappedObject(void action(Invocation i)) {
- return new DelegatingMap(new MapNSM(action));
- }
+class MapExpector<K, V> extends Expector implements Map<K, V> {
+ wrappedChecker(Invocation i) =>
+ new DelegatingMap<K, V>(new MapInvocationChecker<K, V>(i));
}
// Utility values to use as arguments in calls.
-func0() {}
-func1(x) {}
-func2(x, y) {}
+Null func0() => null;
+Null func1(Object x) => null;
+Null func2(Object x, Object y) => null;
var val = new Object();
void main() {
testIterable(var expect) {
- expect.any(func1).equals.any(func1);
- expect.contains(val).equals.contains(val);
- expect.elementAt(0).equals.elementAt(0);
- expect.every(func1).equals.every(func1);
- expect.expand(func1).equals.expand(func1);
- expect.first.equals.first;
+ (expect..any(func1)).equals.any(func1);
+ (expect..contains(val)).equals.contains(val);
+ (expect..elementAt(0)).equals.elementAt(0);
+ (expect..every(func1)).equals.every(func1);
+ (expect..expand(func1)).equals.expand(func1);
+ (expect..first).equals.first;
// Default values of the Iterable interface will be added in the
// second call to firstWhere, so we must record them in our
// expectation (which doesn't have the interface implemented or
// its default values).
- expect.firstWhere(func1, orElse: null).equals.firstWhere(func1);
- expect
- .firstWhere(func1, orElse: func0)
+ (expect..firstWhere(func1, orElse: null)).equals.firstWhere(func1);
+ (expect..firstWhere(func1, orElse: func0))
.equals
.firstWhere(func1, orElse: func0);
- expect.fold(null, func2).equals.fold(null, func2);
- expect.forEach(func1).equals.forEach(func1);
- expect.isEmpty.equals.isEmpty;
- expect.isNotEmpty.equals.isNotEmpty;
- expect.iterator.equals.iterator;
- expect.join('').equals.join();
- expect.join("X").equals.join("X");
- expect.last.equals.last;
- expect.lastWhere(func1, orElse: null).equals.lastWhere(func1);
- expect
- .lastWhere(func1, orElse: func0)
+ (expect..fold(null, func2)).equals.fold(null, func2);
+ (expect..forEach(func1)).equals.forEach(func1);
+ (expect..isEmpty).equals.isEmpty;
+ (expect..isNotEmpty).equals.isNotEmpty;
+ (expect..iterator).equals.iterator;
+ (expect..join('')).equals.join();
+ (expect..join("X")).equals.join("X");
+ (expect..last).equals.last;
+ (expect..lastWhere(func1, orElse: null)).equals.lastWhere(func1);
+ (expect..lastWhere(func1, orElse: func0))
.equals
.lastWhere(func1, orElse: func0);
- expect.length.equals.length;
- expect.map(func1).equals.map(func1);
- expect.reduce(func2).equals.reduce(func2);
- expect.single.equals.single;
-
- // TODO: This currently fails because of the named parameter.
- // expect.singleWhere(func1).equals.singleWhere(func1);
-
- expect.skip(5).equals.skip(5);
- expect.skipWhile(func1).equals.skipWhile(func1);
- expect.take(5).equals.take(5);
- expect.takeWhile(func1).equals.takeWhile(func1);
- expect.toList(growable: true).equals.toList();
- expect.toList(growable: true).equals.toList(growable: true);
- expect.toList(growable: false).equals.toList(growable: false);
- expect.toSet().equals.toSet();
- expect.asString().equals.toString();
- expect.where(func1).equals.where(func1);
+ (expect..length).equals.length;
+ (expect..map(func1)).equals.map(func1);
+ (expect..reduce(func2)).equals.reduce(func2);
+ (expect..single).equals.single;
+ (expect..singleWhere(func1, orElse: null)).equals.singleWhere(func1);
+ (expect..skip(5)).equals.skip(5);
+ (expect..skipWhile(func1)).equals.skipWhile(func1);
+ (expect..take(5)).equals.take(5);
+ (expect..takeWhile(func1)).equals.takeWhile(func1);
+ (expect..toList(growable: true)).equals.toList();
+ (expect..toList(growable: true)).equals.toList(growable: true);
+ (expect..toList(growable: false)).equals.toList(growable: false);
+ (expect..toSet()).equals.toSet();
+ (expect..toString()).equals.toString();
+ (expect..where(func1)).equals.where(func1);
}
void testList(var expect) {
testIterable(expect);
- expect[4].equals[4];
+ (expect..[4]).equals[4];
(expect..[4] = 5).equals[4] = 5;
- expect.add(val).equals.add(val);
- expect.addAll([val]).equals.addAll([val]);
- expect.asMap().equals.asMap();
- expect.clear().equals.clear();
- expect.fillRange(4, 5, null).equals.fillRange(4, 5);
- expect.fillRange(4, 5, val).equals.fillRange(4, 5, val);
- expect.getRange(4, 5).equals.getRange(4, 5);
- expect.indexOf(val, 0).equals.indexOf(val);
- expect.indexOf(val, 4).equals.indexOf(val, 4);
- expect.insert(4, val).equals.insert(4, val);
- expect.insertAll(4, [val]).equals.insertAll(4, [val]);
- expect.lastIndexOf(val, null).equals.lastIndexOf(val);
- expect.lastIndexOf(val, 4).equals.lastIndexOf(val, 4);
+ (expect..add(val)).equals.add(val);
+ (expect..addAll([val])).equals.addAll([val]);
+ (expect..asMap()).equals.asMap();
+ (expect..clear()).equals.clear();
+ (expect..fillRange(4, 5, null)).equals.fillRange(4, 5);
+ (expect..fillRange(4, 5, val)).equals.fillRange(4, 5, val);
+ (expect..getRange(4, 5)).equals.getRange(4, 5);
+ (expect..indexOf(val, 0)).equals.indexOf(val);
+ (expect..indexOf(val, 4)).equals.indexOf(val, 4);
+ (expect..insert(4, val)).equals.insert(4, val);
+ (expect..insertAll(4, [val])).equals.insertAll(4, [val]);
+ (expect..lastIndexOf(val, null)).equals.lastIndexOf(val);
+ (expect..lastIndexOf(val, 4)).equals.lastIndexOf(val, 4);
(expect..length = 4).equals.length = 4;
- expect.remove(val).equals.remove(val);
- expect.removeAt(4).equals.removeAt(4);
- expect.removeLast().equals.removeLast();
- expect.removeRange(4, 5).equals.removeRange(4, 5);
- expect.removeWhere(func1).equals.removeWhere(func1);
- expect.replaceRange(4, 5, [val]).equals.replaceRange(4, 5, [val]);
- expect.retainWhere(func1).equals.retainWhere(func1);
- expect.reversed.equals.reversed;
- expect.setAll(4, [val]).equals.setAll(4, [val]);
- expect.setRange(4, 5, [val], 0).equals.setRange(4, 5, [val]);
- expect.setRange(4, 5, [val], 3).equals.setRange(4, 5, [val], 3);
- expect.sort(null).equals.sort();
- expect.sort(func2).equals.sort(func2);
- expect.sublist(4, null).equals.sublist(4);
- expect.sublist(4, 5).equals.sublist(4, 5);
+ (expect..remove(val)).equals.remove(val);
+ (expect..removeAt(4)).equals.removeAt(4);
+ (expect..removeLast()).equals.removeLast();
+ (expect..removeRange(4, 5)).equals.removeRange(4, 5);
+ (expect..removeWhere(func1)).equals.removeWhere(func1);
+ (expect..replaceRange(4, 5, [val])).equals.replaceRange(4, 5, [val]);
+ (expect..retainWhere(func1)).equals.retainWhere(func1);
+ (expect..reversed).equals.reversed;
+ (expect..setAll(4, [val])).equals.setAll(4, [val]);
+ (expect..setRange(4, 5, [val], 0)).equals.setRange(4, 5, [val]);
+ (expect..setRange(4, 5, [val], 3)).equals.setRange(4, 5, [val], 3);
+ (expect..sort(null)).equals.sort();
+ (expect..sort(func2)).equals.sort(func2);
+ (expect..sublist(4, null)).equals.sublist(4);
+ (expect..sublist(4, 5)).equals.sublist(4, 5);
}
void testSet(var expect) {
testIterable(expect);
Set set = new Set();
- expect.add(val).equals.add(val);
- expect.addAll([val]).equals.addAll([val]);
- expect.clear().equals.clear();
- expect.containsAll([val]).equals.containsAll([val]);
- expect.difference(set).equals.difference(set);
- expect.intersection(set).equals.intersection(set);
- expect.remove(val).equals.remove(val);
- expect.removeAll([val]).equals.removeAll([val]);
- expect.removeWhere(func1).equals.removeWhere(func1);
- expect.retainAll([val]).equals.retainAll([val]);
- expect.retainWhere(func1).equals.retainWhere(func1);
- expect.union(set).equals.union(set);
+ (expect..add(val)).equals.add(val);
+ (expect..addAll([val])).equals.addAll([val]);
+ (expect..clear()).equals.clear();
+ (expect..containsAll([val])).equals.containsAll([val]);
+ (expect..difference(set)).equals.difference(set);
+ (expect..intersection(set)).equals.intersection(set);
+ (expect..remove(val)).equals.remove(val);
+ (expect..removeAll([val])).equals.removeAll([val]);
+ (expect..removeWhere(func1)).equals.removeWhere(func1);
+ (expect..retainAll([val])).equals.retainAll([val]);
+ (expect..retainWhere(func1)).equals.retainWhere(func1);
+ (expect..union(set)).equals.union(set);
}
void testQueue(var expect) {
testIterable(expect);
- expect.add(val).equals.add(val);
- expect.addAll([val]).equals.addAll([val]);
- expect.addFirst(val).equals.addFirst(val);
- expect.addLast(val).equals.addLast(val);
- expect.clear().equals.clear();
- expect.remove(val).equals.remove(val);
- expect.removeFirst().equals.removeFirst();
- expect.removeLast().equals.removeLast();
+ (expect..add(val)).equals.add(val);
+ (expect..addAll([val])).equals.addAll([val]);
+ (expect..addFirst(val)).equals.addFirst(val);
+ (expect..addLast(val)).equals.addLast(val);
+ (expect..clear()).equals.clear();
+ (expect..remove(val)).equals.remove(val);
+ (expect..removeFirst()).equals.removeFirst();
+ (expect..removeLast()).equals.removeLast();
}
void testMap(var expect) {
Map map = new Map();
- expect[val].equals[val];
+ (expect..[val]).equals[val];
(expect..[val] = val).equals[val] = val;
- expect.addAll(map).equals.addAll(map);
- expect.clear().equals.clear();
- expect.containsKey(val).equals.containsKey(val);
- expect.containsValue(val).equals.containsValue(val);
- expect.forEach(func2).equals.forEach(func2);
- expect.isEmpty.equals.isEmpty;
- expect.isNotEmpty.equals.isNotEmpty;
- expect.keys.equals.keys;
- expect.length.equals.length;
- expect.putIfAbsent(val, func0).equals.putIfAbsent(val, func0);
- expect.remove(val).equals.remove(val);
- expect.values.equals.values;
- expect.asString().equals.toString();
+ (expect..addAll(map)).equals.addAll(map);
+ (expect..clear()).equals.clear();
+ (expect..containsKey(val)).equals.containsKey(val);
+ (expect..containsValue(val)).equals.containsValue(val);
+ (expect..forEach(func2)).equals.forEach(func2);
+ (expect..isEmpty).equals.isEmpty;
+ (expect..isNotEmpty).equals.isNotEmpty;
+ (expect..keys).equals.keys;
+ (expect..length).equals.length;
+ (expect..putIfAbsent(val, func0)).equals.putIfAbsent(val, func0);
+ (expect..remove(val)).equals.remove(val);
+ (expect..values).equals.values;
+ (expect..toString()).equals.toString();
}
// Runs tests of Set behavior.
@@ -279,7 +263,7 @@
// [setUpSet] should return a set with two elements: "foo" and "bar".
void testTwoElementSet(Set<String> setUpSet()) {
group("with two elements", () {
- var set;
+ Set<String> set;
setUp(() => set = setUpSet());
test(".any", () {