OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 // Tests of hash set behavior, with focus in iteration and concurrent | |
6 // modification errors. | |
7 | |
8 library hash_map2_test; | |
9 import 'dart:collection'; | |
10 | |
11 testSet(Set newSet(), Set newSetFrom(Set from)) { | |
12 Set gen(int from, int to) => | |
13 new Set.from(new Iterable.generate(to - from, (n) => n + from)); | |
14 | |
15 bool odd(int n) => (n & 1) == 1; | |
16 bool even(int n) => (n & 1) == 0; | |
17 | |
18 { // Test growing to largish capacity. | |
19 Set set = newSet(); | |
20 | |
21 for (int i = 0; i < 256; i++) { | |
22 set.add(i); | |
23 } | |
24 set.addAll(gen(256, 512)); | |
25 set.addAll(newSetFrom(gen(512, 1000))); | |
26 Expect.equals(1000, set.length); | |
27 | |
28 // Remove half. | |
29 for (int i = 0; i < 1000; i += 2) set.remove(i); | |
30 Expect.equals(500, set.length); | |
31 Expect.isFalse(set.any(even)); | |
32 Expect.isTrue(set.every(odd)); | |
33 | |
34 // Re-add all. | |
35 set.addAll(gen(0, 1000)); | |
36 Expect.equals(1000, set.length); | |
37 } | |
38 | |
39 { // Test having many deleted elements. | |
40 Set set = newSet(); | |
41 set.add(0); | |
42 for (int i = 0; i < 1000; i++) { | |
43 set.add(i + 1); | |
44 set.remove(i); | |
45 Expect.equals(1, set.length); | |
46 } | |
47 } | |
48 | |
49 { // Test having many elements with same hashCode | |
50 Set set = newSet(); | |
51 for (int i = 0; i < 1000; i++) { | |
52 set.add(new BadHashCode()); | |
53 } | |
54 Expect.equals(1000, set.length); | |
55 } | |
56 | |
57 { // Check concurrent modification | |
58 Set set = newSet()..add(0)..add(1); | |
59 | |
60 { // Test adding before a moveNext. | |
61 Iterator iter = set.iterator; | |
62 iter.moveNext(); | |
63 set.add(1); // Updating existing key isn't a modification. | |
64 iter.moveNext(); | |
65 set.add(2); | |
66 Expect.throws(iter.moveNext, (e) => e is Error); | |
67 } | |
68 | |
69 { // Test adding after last element. | |
70 Iterator iter = set.iterator; | |
71 Expect.equals(3, set.length); | |
72 iter.moveNext(); | |
73 iter.moveNext(); | |
74 iter.moveNext(); | |
75 set.add(3); | |
76 Expect.throws(iter.moveNext, (e) => e is Error); | |
77 } | |
78 | |
79 { // Test removing during iteration. | |
80 Iterator iter = set.iterator; | |
81 iter.moveNext(); | |
82 set.remove(1000); // Not a modification if it's not there. | |
83 iter.moveNext(); | |
84 int n = iter.current; | |
85 set.remove(n); | |
86 // Removing doesn't change current. | |
87 Expect.equals(n, iter.current); | |
88 Expect.throws(iter.moveNext, (e) => e is Error); | |
89 } | |
90 | |
91 { // Test removing after last element. | |
92 Iterator iter = set.iterator; | |
93 Expect.equals(3, set.length); | |
94 iter.moveNext(); | |
95 iter.moveNext(); | |
96 iter.moveNext(); | |
97 int n = iter.current; | |
98 set.remove(n); | |
99 // Removing doesn't change current. | |
100 Expect.equals(n, iter.current); | |
101 Expect.throws(iter.moveNext, (e) => e is Error); | |
102 } | |
103 | |
104 { // Test that updating value doesn't cause error. | |
105 Iterator iter = set.iterator; | |
106 Expect.equals(2, set.length); | |
107 iter.moveNext(); | |
108 int n = iter.current; | |
109 set.add(n); | |
110 iter.moveNext(); | |
111 Expect.isTrue(set.contains(iter.current)); | |
112 } | |
113 | |
114 { // Check adding many existing values isn't considered modification. | |
115 Set set2 = newSet(); | |
116 for (var value in set) { | |
117 set2.add(value); | |
118 } | |
119 Iterator iter = set.iterator; | |
120 set.addAll(set2); | |
121 // Shouldn't throw. | |
122 iter.moveNext(); | |
123 } | |
124 } | |
125 | |
126 { // Check that updating existing elements is not a modification. | |
127 // This must be the case even if the underlying data structure is | |
128 // nearly full. | |
129 for (int i = 1; i < 128; i++) { | |
130 // Create maps of different sizes, some of which should be | |
131 // at a limit of the underlying data structure. | |
132 Set set = newSetFrom(gen(0, i)); | |
133 Iterator iter = set.iterator; | |
134 for (int j = 0; j < i; j++) { | |
135 set.add(j); | |
136 } | |
137 iter.moveNext(); // Should not throw. | |
138 | |
139 for (int j = 1; j < i; j++) { | |
140 set.remove(j); | |
141 } | |
142 iter = set.iterator; | |
143 set.add(0); | |
144 iter.moveNext(); // Should not throw. | |
145 } | |
146 } | |
147 | |
148 { // Check that null can be in the set. | |
149 Set set = newSet(); | |
150 set.add(null); | |
151 Expect.equals(1, set.length); | |
152 Expect.isTrue(set.contains(null)); | |
153 Expect.isNull(set.first); | |
154 Expect.isNull(set.last); | |
155 set.add(null); | |
156 Expect.equals(1, set.length); | |
157 Expect.isTrue(set.contains(null)); | |
158 set.remove(null); | |
159 Expect.isTrue(set.isEmpty); | |
160 Expect.isFalse(set.contains(null)); | |
161 | |
162 // Created using Set.from. | |
163 set = newSetFrom([null]); | |
164 Expect.equals(1, set.length); | |
165 Expect.isTrue(set.contains(null)); | |
166 Expect.isNull(set.first); | |
167 Expect.isNull(set.last); | |
168 set.add(null); | |
169 Expect.equals(1, set.length); | |
170 Expect.isTrue(set.contains(null)); | |
171 set.remove(null); | |
172 Expect.isTrue(set.isEmpty); | |
173 Expect.isFalse(set.contains(null)); | |
174 | |
175 // Set that grows with null in it. | |
176 set = newSetFrom([1, 2, 3, null, 4, 5, 6]); | |
177 Expect.equals(7, set.length); | |
178 for (int i = 7; i < 128; i++) { | |
179 set.add(i); | |
180 } | |
181 Expect.equals(128, set.length); | |
182 Expect.isTrue(set.contains(null)); | |
183 set.add(null); | |
184 Expect.equals(128, set.length); | |
185 Expect.isTrue(set.contains(null)); | |
186 set.remove(null); | |
187 Expect.equals(127, set.length); | |
188 Expect.isFalse(set.contains(null)); | |
189 } | |
190 } | |
191 | |
192 void main() { | |
193 testSet(() => new HashSet(), (m) => new HashSet.from(m)); | |
194 testSet(() => new LinkedHashSet(), (m) => new LinkedHashSet.from(m)); | |
195 } | |
196 | |
197 | |
198 class BadHashCode { | |
199 static int idCounter = 0; | |
200 final int id; | |
201 BadHashCode() : id = idCounter++; | |
202 int get hashCode => 42; | |
203 // operator == is identity. | |
204 // Can't make a bad compareTo that isn't invalid. | |
205 int compareTo(BadHashCode other) => id - other.id; | |
206 } | |
OLD | NEW |