Index: tests/corelib/map_test.dart |
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart |
index 4f48be4a085d1f8d7cfaa25425faad4b11042de6..c9ba29f56329d5406b11c94a27b1a1c71b5b1919 100644 |
--- a/tests/corelib/map_test.dart |
+++ b/tests/corelib/map_test.dart |
@@ -29,8 +29,25 @@ void main() { |
testNumericKeys(new Map<num, String>()); |
testNumericKeys(new HashMap()); |
testNumericKeys(new HashMap<num, String>()); |
+ testNumericKeys(new HashMap(equals: identical)); |
+ testNumericKeys(new HashMap<num, String>(equals: identical)); |
testNumericKeys(new LinkedHashMap()); |
testNumericKeys(new LinkedHashMap<num, String>()); |
+ |
+ testNaNKeys(new Map()); |
+ testNaNKeys(new Map<num, String>()); |
+ testNaNKeys(new HashMap()); |
+ testNaNKeys(new HashMap<num, String>()); |
+ testNaNKeys(new LinkedHashMap()); |
+ testNaNKeys(new LinkedHashMap<num, String>()); |
+ // Identity maps fail the NaN-keys tests because the test assumes that |
+ // NaN is not equal to NaN. |
+ |
+ testIdentityMap(new HashMap(equals: identical)); |
+ |
+ testCustomMap(new HashMap(equals: myEquals, hashCode: myHashCode)); |
+ |
+ testIterationOrder(new LinkedHashMap()); |
} |
@@ -373,7 +390,10 @@ void testNumericKeys(Map map) { |
Expect.equals(null, map[key]); |
} |
Expect.isTrue(map.isEmpty); |
+} |
+void testNaNKeys(Map map) { |
+ Expect.isTrue(map.isEmpty); |
// Test NaN. |
var nan = double.NAN; |
Expect.isFalse(map.containsKey(nan)); |
@@ -407,3 +427,224 @@ void testLength(int length, Map map) { |
(length == 0 ? Expect.isTrue : Expect.isFalse)(map.isEmpty); |
(length != 0 ? Expect.isTrue : Expect.isFalse)(map.isNotEmpty); |
} |
+ |
+ |
+testIdentityMap(Map map) { |
+ Expect.isTrue(map.isEmpty); |
+ |
+ var nan = double.NAN; |
+ // TODO(11551): Remove guard when dart2js makes identical(NaN, NaN) true. |
+ if (identical(nan, nan)) { |
+ map[nan] = 42; |
+ testLength(1, map); |
+ Expect.isTrue(map.containsKey(nan)); |
+ Expect.equals(42, map[nan]); |
+ map[nan] = 37; |
+ testLength(1, map); |
+ Expect.equals(37, map[nan]); |
+ Expect.equals(37, map.remove(nan)); |
+ testLength(0, map); |
+ } |
+ |
+ Vampire v1 = const Vampire(1); |
+ Vampire v2 = const Vampire(2); |
+ Expect.isFalse(v1 == v1); |
+ Expect.isFalse(v2 == v2); |
+ Expect.isTrue(v2 == v1); // Snob! |
+ |
+ map[v1] = 1; |
+ map[v2] = 2; |
+ testLength(2, map); |
+ |
+ Expect.isTrue(map.containsKey(v1)); |
+ Expect.isTrue(map.containsKey(v2)); |
+ |
+ Expect.equals(1, map[v1]); |
+ Expect.equals(2, map[v2]); |
+ |
+ Expect.equals(1, map.remove(v1)); |
+ testLength(1, map); |
+ Expect.isFalse(map.containsKey(v1)); |
+ Expect.isTrue(map.containsKey(v2)); |
+ |
+ Expect.isNull(map.remove(v1)); |
+ Expect.equals(2, map.remove(v2)); |
+ testLength(0, map); |
+ |
+ var eq01 = new Equalizer(0); |
+ var eq02 = new Equalizer(0); |
+ var eq11 = new Equalizer(1); |
+ var eq12 = new Equalizer(1); |
+ // Sanity. |
+ Expect.equals(eq01, eq02); |
+ Expect.equals(eq02, eq01); |
+ Expect.equals(eq11, eq12); |
+ Expect.equals(eq12, eq11); |
+ Expect.notEquals(eq01, eq11); |
+ Expect.notEquals(eq01, eq12); |
+ Expect.notEquals(eq02, eq11); |
+ Expect.notEquals(eq02, eq12); |
+ Expect.notEquals(eq11, eq01); |
+ Expect.notEquals(eq11, eq02); |
+ Expect.notEquals(eq12, eq01); |
+ Expect.notEquals(eq12, eq02); |
+ |
+ map[eq01] = 0; |
+ map[eq02] = 1; |
+ map[eq11] = 2; |
+ map[eq12] = 3; |
+ testLength(4, map); |
+ |
+ Expect.equals(0, map[eq01]); |
+ Expect.equals(1, map[eq02]); |
+ Expect.equals(2, map[eq11]); |
+ Expect.equals(3, map[eq12]); |
+ |
+ Expect.isTrue(map.containsKey(eq01)); |
+ Expect.isTrue(map.containsKey(eq02)); |
+ Expect.isTrue(map.containsKey(eq11)); |
+ Expect.isTrue(map.containsKey(eq12)); |
+ |
+ Expect.equals(1, map.remove(eq02)); |
+ Expect.equals(3, map.remove(eq12)); |
+ testLength(2, map); |
+ Expect.isTrue(map.containsKey(eq01)); |
+ Expect.isFalse(map.containsKey(eq02)); |
+ Expect.isTrue(map.containsKey(eq11)); |
+ Expect.isFalse(map.containsKey(eq12)); |
+ |
+ Expect.equals(0, map[eq01]); |
+ Expect.equals(null, map[eq02]); |
+ Expect.equals(2, map[eq11]); |
+ Expect.equals(null, map[eq12]); |
+ |
+ Expect.equals(0, map.remove(eq01)); |
+ Expect.equals(2, map.remove(eq11)); |
+ testLength(0, map); |
+ |
+ map[eq01] = 0; |
+ map[eq02] = 1; |
+ map[eq11] = 2; |
+ map[eq12] = 3; |
+ testLength(4, map); |
+ |
+ // Transfer to equality-based map will collapse elements. |
+ Map eqMap = new HashMap(); |
+ eqMap.addAll(map); |
+ testLength(2, eqMap); |
+ Expect.isTrue(eqMap.containsKey(eq01)); |
+ Expect.isTrue(eqMap.containsKey(eq02)); |
+ Expect.isTrue(eqMap.containsKey(eq11)); |
+ Expect.isTrue(eqMap.containsKey(eq12)); |
+} |
+ |
+/** Class of objects that are equal if they hold the same id. */ |
+class Equalizer { |
+ int id; |
+ Equalizer(this.id); |
+ int get hashCode => id; |
+ bool operator==(Object other) => |
+ other is Equalizer && id == (other as Equalizer).id; |
+} |
+ |
+/** |
+ * Objects that are not reflexive. |
+ * |
+ * They think they are better than their equals. |
+ */ |
+class Vampire { |
+ final int generation; |
+ const Vampire(this.generation); |
+ |
+ int get hashCode => generation; |
+ |
+ // The double-fang operator falsely claims that a vampire is equal to |
+ // any of its sire's generation. |
+ bool operator==(Object other) => |
+ other is Vampire && generation - 1 == (other as Vampire).generation; |
+} |
+ |
+void testCustomMap(Map map) { |
+ testLength(0, map); |
+ var c11 = const Customer(1, 1); |
+ var c12 = const Customer(1, 2); |
+ var c21 = const Customer(2, 1); |
+ var c22 = const Customer(2, 2); |
+ // Sanity. |
+ Expect.equals(c11, c12); |
+ Expect.notEquals(c11, c21); |
+ Expect.notEquals(c11, c22); |
+ Expect.equals(c21, c22); |
+ Expect.notEquals(c21, c11); |
+ Expect.notEquals(c21, c12); |
+ |
+ Expect.isTrue(myEquals(c11, c21)); |
+ Expect.isFalse(myEquals(c11, c12)); |
+ Expect.isFalse(myEquals(c11, c22)); |
+ Expect.isTrue(myEquals(c12, c22)); |
+ Expect.isFalse(myEquals(c12, c11)); |
+ Expect.isFalse(myEquals(c12, c21)); |
+ |
+ map[c11] = 42; |
+ testLength(1, map); |
+ Expect.isTrue(map.containsKey(c11)); |
+ Expect.isTrue(map.containsKey(c21)); |
+ Expect.isFalse(map.containsKey(c12)); |
+ Expect.isFalse(map.containsKey(c22)); |
+ Expect.equals(42, map[c11]); |
+ Expect.equals(42, map[c21]); |
+ |
+ map[c21] = 37; |
+ testLength(1, map); |
+ Expect.isTrue(map.containsKey(c11)); |
+ Expect.isTrue(map.containsKey(c21)); |
+ Expect.isFalse(map.containsKey(c12)); |
+ Expect.isFalse(map.containsKey(c22)); |
+ Expect.equals(37, map[c11]); |
+ Expect.equals(37, map[c21]); |
+ |
+ map[c22] = 42; |
+ testLength(2, map); |
+ Expect.isTrue(map.containsKey(c11)); |
+ Expect.isTrue(map.containsKey(c21)); |
+ Expect.isTrue(map.containsKey(c12)); |
+ Expect.isTrue(map.containsKey(c22)); |
+ Expect.equals(37, map[c11]); |
+ Expect.equals(37, map[c21]); |
+ Expect.equals(42, map[c12]); |
+ Expect.equals(42, map[c22]); |
+ |
+ Expect.equals(42, map.remove(c12)); |
+ testLength(1, map); |
+ Expect.isTrue(map.containsKey(c11)); |
+ Expect.isTrue(map.containsKey(c21)); |
+ Expect.isFalse(map.containsKey(c12)); |
+ Expect.isFalse(map.containsKey(c22)); |
+ Expect.equals(37, map[c11]); |
+ Expect.equals(37, map[c21]); |
+ |
+ Expect.equals(37, map.remove(c11)); |
+ testLength(0, map); |
+} |
+ |
+class Customer { |
+ final int id; |
+ final int secondId; |
+ const Customer(this.id, this.secondId); |
+ int get hashCode => id; |
+ bool operator==(Object other) { |
+ if (other is! Customer) return false; |
+ Customer otherCustomer = other; |
+ return id == otherCustomer.id; |
+ } |
+} |
+ |
+int myHashCode(Customer c) => c.secondId; |
+bool myEquals(Customer a, Customer b) => a.secondId == b.secondId; |
+ |
+testIterationOrder(Map map) { |
+ var order = [0, 6, 4, 2, 7, 9, 7, 1, 2, 5, 3]; |
+ for (int i = 0; i < order.length; i++) map[order[i]] = i; |
+ Expect.listEquals(map.keys.toList(), [0, 6, 4, 2, 7, 9, 1, 5, 3]); |
+ Expect.listEquals(map.values.toList(), [0, 1, 2, 8, 6, 5, 7, 9, 10]); |
+} |