OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library map_test; | 5 library map_test; |
6 import "package:expect/expect.dart"; | 6 import "package:expect/expect.dart"; |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 void main() { | 9 void main() { |
10 test(new HashMap()); | 10 test(new HashMap()); |
11 test(new LinkedHashMap()); | 11 test(new LinkedHashMap()); |
12 test(new SplayTreeMap()); | 12 test(new SplayTreeMap()); |
13 test(new SplayTreeMap(Comparable.compare)); | 13 test(new SplayTreeMap(Comparable.compare)); |
| 14 test(new MapView(new HashMap())); |
| 15 test(new MapView(new SplayTreeMap())); |
| 16 test(new MapBaseMap()); |
14 testLinkedHashMap(); | 17 testLinkedHashMap(); |
15 testMapLiteral(); | 18 testMapLiteral(); |
16 testNullValue(); | 19 testNullValue(); |
17 testTypes(); | 20 testTypes(); |
18 | 21 |
19 testWeirdStringKeys(new Map()); | 22 testWeirdStringKeys(new Map()); |
20 testWeirdStringKeys(new Map<String, String>()); | 23 testWeirdStringKeys(new Map<String, String>()); |
21 testWeirdStringKeys(new HashMap()); | 24 testWeirdStringKeys(new HashMap()); |
22 testWeirdStringKeys(new HashMap<String, String>()); | 25 testWeirdStringKeys(new HashMap<String, String>()); |
23 testWeirdStringKeys(new LinkedHashMap()); | 26 testWeirdStringKeys(new LinkedHashMap()); |
24 testWeirdStringKeys(new LinkedHashMap<String, String>()); | 27 testWeirdStringKeys(new LinkedHashMap<String, String>()); |
25 testWeirdStringKeys(new SplayTreeMap()); | 28 testWeirdStringKeys(new SplayTreeMap()); |
26 testWeirdStringKeys(new SplayTreeMap<String, String>()); | 29 testWeirdStringKeys(new SplayTreeMap<String, String>()); |
| 30 testWeirdStringKeys(new MapBaseMap<String, String>()); |
27 | 31 |
28 testNumericKeys(new Map()); | 32 testNumericKeys(new Map()); |
29 testNumericKeys(new Map<num, String>()); | 33 testNumericKeys(new Map<num, String>()); |
30 testNumericKeys(new HashMap()); | 34 testNumericKeys(new HashMap()); |
31 testNumericKeys(new HashMap<num, String>()); | 35 testNumericKeys(new HashMap<num, String>()); |
32 testNumericKeys(new HashMap.identity()); | 36 testNumericKeys(new HashMap.identity()); |
33 testNumericKeys(new HashMap<num, String>.identity()); | 37 testNumericKeys(new HashMap<num, String>.identity()); |
34 testNumericKeys(new LinkedHashMap()); | 38 testNumericKeys(new LinkedHashMap()); |
35 testNumericKeys(new LinkedHashMap<num, String>()); | 39 testNumericKeys(new LinkedHashMap<num, String>()); |
36 testNumericKeys(new LinkedHashMap.identity()); | 40 testNumericKeys(new LinkedHashMap.identity()); |
37 testNumericKeys(new LinkedHashMap<num, String>.identity()); | 41 testNumericKeys(new LinkedHashMap<num, String>.identity()); |
| 42 testNumericKeys(new MapBaseMap<num, String>()); |
38 | 43 |
39 testNaNKeys(new Map()); | 44 testNaNKeys(new Map()); |
40 testNaNKeys(new Map<num, String>()); | 45 testNaNKeys(new Map<num, String>()); |
41 testNaNKeys(new HashMap()); | 46 testNaNKeys(new HashMap()); |
42 testNaNKeys(new HashMap<num, String>()); | 47 testNaNKeys(new HashMap<num, String>()); |
43 testNaNKeys(new LinkedHashMap()); | 48 testNaNKeys(new LinkedHashMap()); |
44 testNaNKeys(new LinkedHashMap<num, String>()); | 49 testNaNKeys(new LinkedHashMap<num, String>()); |
| 50 testNaNKeys(new MapBaseMap<num, String>()); |
45 // Identity maps fail the NaN-keys tests because the test assumes that | 51 // Identity maps fail the NaN-keys tests because the test assumes that |
46 // NaN is not equal to NaN. | 52 // NaN is not equal to NaN. |
47 | 53 |
48 testIdentityMap(new Map.identity()); | 54 testIdentityMap(new Map.identity()); |
49 testIdentityMap(new HashMap.identity()); | 55 testIdentityMap(new HashMap.identity()); |
50 testIdentityMap(new LinkedHashMap.identity()); | 56 testIdentityMap(new LinkedHashMap.identity()); |
51 testIdentityMap(new HashMap(equals: identical, | 57 testIdentityMap(new HashMap(equals: identical, |
52 hashCode: identityHashCode)); | 58 hashCode: identityHashCode)); |
53 testIdentityMap(new LinkedHashMap(equals: identical, | 59 testIdentityMap(new LinkedHashMap(equals: identical, |
54 hashCode: identityHashCode)); | 60 hashCode: identityHashCode)); |
(...skipping 27 matching lines...) Expand all Loading... |
82 testOtherKeys(new HashMap(equals: (int x, int y) => x == y, | 88 testOtherKeys(new HashMap(equals: (int x, int y) => x == y, |
83 hashCode: (int v) => v.hashCode, | 89 hashCode: (int v) => v.hashCode, |
84 isValidKey: (v) => v is int)); | 90 isValidKey: (v) => v is int)); |
85 testOtherKeys(new LinkedHashMap<int, int>()); | 91 testOtherKeys(new LinkedHashMap<int, int>()); |
86 testOtherKeys(new LinkedHashMap<int, int>.identity()); | 92 testOtherKeys(new LinkedHashMap<int, int>.identity()); |
87 testOtherKeys(new LinkedHashMap<int, int>(hashCode: (v) => v.hashCode, | 93 testOtherKeys(new LinkedHashMap<int, int>(hashCode: (v) => v.hashCode, |
88 isValidKey: (v) => v is int)); | 94 isValidKey: (v) => v is int)); |
89 testOtherKeys(new LinkedHashMap(equals: (int x, int y) => x == y, | 95 testOtherKeys(new LinkedHashMap(equals: (int x, int y) => x == y, |
90 hashCode: (int v) => v.hashCode, | 96 hashCode: (int v) => v.hashCode, |
91 isValidKey: (v) => v is int)); | 97 isValidKey: (v) => v is int)); |
| 98 testOtherKeys(new MapBaseMap<int, int>()); |
| 99 |
| 100 testUnmodifiableMap(new UnmodifiableMapView({1 : 37})); |
| 101 testUnmodifiableMap(new UnmodifiableMapBaseMap([1, 37])); |
| 102 testUnmodifiableMap(new MapBaseUnmodifiableMap([1, 37])); |
92 } | 103 } |
93 | 104 |
94 | 105 |
95 void test(Map map) { | 106 void test(Map map) { |
96 testDeletedElement(map); | 107 testDeletedElement(map); |
97 testMap(map, 1, 2, 3, 4, 5, 6, 7, 8); | 108 testMap(map, 1, 2, 3, 4, 5, 6, 7, 8); |
98 map.clear(); | 109 map.clear(); |
99 testMap(map, "value1", "value2", "value3", "value4", "value5", | 110 testMap(map, "value1", "value2", "value3", "value4", "value5", |
100 "value6", "value7", "value8"); | 111 "value6", "value7", "value8"); |
101 } | 112 } |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 Expect.isTrue(map.containsKey(c21)); | 708 Expect.isTrue(map.containsKey(c21)); |
698 Expect.isFalse(map.containsKey(c12)); | 709 Expect.isFalse(map.containsKey(c12)); |
699 Expect.isFalse(map.containsKey(c22)); | 710 Expect.isFalse(map.containsKey(c22)); |
700 Expect.equals(37, map[c11]); | 711 Expect.equals(37, map[c11]); |
701 Expect.equals(37, map[c21]); | 712 Expect.equals(37, map[c21]); |
702 | 713 |
703 Expect.equals(37, map.remove(c11)); | 714 Expect.equals(37, map.remove(c11)); |
704 testLength(0, map); | 715 testLength(0, map); |
705 } | 716 } |
706 | 717 |
| 718 void testUnmodifiableMap(Map map) { |
| 719 Expect.isTrue(map.containsKey(1)); |
| 720 testLength(1, map); |
| 721 Expect.equals(1, map.keys.first); |
| 722 Expect.equals(37, map.values.first); |
| 723 |
| 724 Expect.throws(map.clear); |
| 725 Expect.throws(() { map.remove(1); }); |
| 726 Expect.throws(() { map[2] = 42; }); |
| 727 Expect.throws(() { map.addAll({2 : 42}); }); |
| 728 } |
| 729 |
707 class Customer { | 730 class Customer { |
708 final int id; | 731 final int id; |
709 final int secondId; | 732 final int secondId; |
710 const Customer(this.id, this.secondId); | 733 const Customer(this.id, this.secondId); |
711 int get hashCode => id; | 734 int get hashCode => id; |
712 bool operator==(Object other) { | 735 bool operator==(Object other) { |
713 if (other is! Customer) return false; | 736 if (other is! Customer) return false; |
714 Customer otherCustomer = other; | 737 Customer otherCustomer = other; |
715 return id == otherCustomer.id; | 738 return id == otherCustomer.id; |
716 } | 739 } |
(...skipping 25 matching lines...) Expand all Loading... |
742 Expect.isNull(map["not an int"]); | 765 Expect.isNull(map["not an int"]); |
743 Expect.isNull(map[1.5]); | 766 Expect.isNull(map[1.5]); |
744 } | 767 } |
745 | 768 |
746 class Mutable { | 769 class Mutable { |
747 int id; | 770 int id; |
748 Mutable(this.id); | 771 Mutable(this.id); |
749 int get hashCode => id; | 772 int get hashCode => id; |
750 bool operator==(other) => other is Mutable && other.id == id; | 773 bool operator==(other) => other is Mutable && other.id == id; |
751 } | 774 } |
| 775 |
| 776 |
| 777 // Slow implementation of Map based on MapBase. |
| 778 class MapBaseMap<K, V> extends MapBase<K, V> { |
| 779 final List _keys = <K>[]; |
| 780 final List _values = <V>[]; |
| 781 int _modCount = 0; |
| 782 |
| 783 V operator[](Object key) { |
| 784 int index = _keys.indexOf(key); |
| 785 if (index < 0) return null; |
| 786 return _values[index]; |
| 787 } |
| 788 |
| 789 Iterable<K> get keys => new TestKeyIterable<K>(this); |
| 790 |
| 791 void operator[]=(K key, V value) { |
| 792 int index = _keys.indexOf(key); |
| 793 if (index >= 0) { |
| 794 _values[index] = value; |
| 795 } else { |
| 796 _modCount++; |
| 797 _keys.add(key); |
| 798 _values.add(value); |
| 799 } |
| 800 } |
| 801 |
| 802 V remove(Object key) { |
| 803 int index = _keys.indexOf(key); |
| 804 if (index >= 0) { |
| 805 var result = _values[index]; |
| 806 key = _keys.removeLast(); |
| 807 var value = _values.removeLast(); |
| 808 if (index != _keys.length) { |
| 809 _keys[index] = key; |
| 810 _values[index] = value; |
| 811 } |
| 812 _modCount++; |
| 813 return result; |
| 814 } |
| 815 return null; |
| 816 } |
| 817 |
| 818 void clear() { |
| 819 // Clear cannot be based on remove, since remove won't remove keys that |
| 820 // are not equal to themselves. It will fail the testNaNKeys test. |
| 821 _keys.clear(); |
| 822 _values.clear(); |
| 823 _modCount++; |
| 824 } |
| 825 } |
| 826 |
| 827 class TestKeyIterable<K> extends IterableBase<K> { |
| 828 final _map; |
| 829 TestKeyIterable(this._map); |
| 830 int get length => _map._keys.length; |
| 831 Iterator<K> get iterator => new TestKeyIterator<K>(_map); |
| 832 } |
| 833 |
| 834 class TestKeyIterator<K> implements Iterator<K> { |
| 835 final _map; |
| 836 final int _modCount; |
| 837 int _index = 0; |
| 838 var _current; |
| 839 TestKeyIterator(map) : _map = map, _modCount = map._modCount; |
| 840 bool moveNext() { |
| 841 if (_modCount != _map._modCount) { |
| 842 throw new ConcurrentModificationError(_map); |
| 843 } |
| 844 if (_index == _map._keys.length) { |
| 845 _current = null; |
| 846 return false; |
| 847 } |
| 848 _current = _map._keys[_index++]; |
| 849 return true; |
| 850 } |
| 851 K get current => _current; |
| 852 } |
| 853 |
| 854 // Slow implementation of Map based on MapBase. |
| 855 class UnmodifiableMapBaseMap<K, V> extends UnmodifiableMapBase<K, V> { |
| 856 final List _keys = <K>[]; |
| 857 final List _values = <V>[]; |
| 858 UnmodifiableMapBaseMap(List pairs) { |
| 859 for (int i = 0; i < pairs.length; i += 2) { |
| 860 _keys.add(pairs[i]); |
| 861 _values.add(pairs[i + 1]); |
| 862 } |
| 863 } |
| 864 |
| 865 int get _modCount => 0; |
| 866 |
| 867 V operator[](K key) { |
| 868 int index = _keys.indexOf(key); |
| 869 if (index < 0) return null; |
| 870 return _values[index]; |
| 871 } |
| 872 |
| 873 Iterable<K> get keys => _keys.skip(0); |
| 874 } |
| 875 |
| 876 // Slow implementation of unmodifiable Map based on MapBase and |
| 877 // UnmodifiableMapMixin. |
| 878 class MapBaseUnmodifiableMap<K, V> extends MapBase<K, V> |
| 879 with UnmodifiableMapMixin<K, V> { |
| 880 final List _keys = <K>[]; |
| 881 final List _values = <V>[]; |
| 882 |
| 883 int get _modCount => 0; |
| 884 |
| 885 MapBaseUnmodifiableMap(List pairs) { |
| 886 for (int i = 0; i < pairs.length; i += 2) { |
| 887 _keys.add(pairs[i]); |
| 888 _values.add(pairs[i + 1]); |
| 889 } |
| 890 } |
| 891 |
| 892 V operator[](Object key) { |
| 893 int index = _keys.indexOf(key); |
| 894 if (index < 0) return null; |
| 895 return _values[index]; |
| 896 } |
| 897 |
| 898 Iterable<K> get keys => new TestKeyIterable<K>(this); |
| 899 } |
OLD | NEW |