| 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 set_test; | 5 library set_test; |
| 6 | 6 |
| 7 | 7 |
| 8 import 'package:expect/expect.dart'; | 8 import 'package:expect/expect.dart'; |
| 9 import "dart:collection"; | 9 import "dart:collection"; |
| 10 | 10 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 // in a way that doesn't match the equality of the set. | 248 // in a way that doesn't match the equality of the set. |
| 249 // It must not throw away equal elements that are different in the | 249 // It must not throw away equal elements that are different in the |
| 250 // equality of the set. | 250 // equality of the set. |
| 251 // It must not consider objects to be not there if they are equal | 251 // It must not consider objects to be not there if they are equal |
| 252 // in the equality of the set. | 252 // in the equality of the set. |
| 253 | 253 |
| 254 // If set equality is natural equality, using different but equal objects | 254 // If set equality is natural equality, using different but equal objects |
| 255 // must work. Can't use an identity set internally (as was done at some point | 255 // must work. Can't use an identity set internally (as was done at some point |
| 256 // during development). | 256 // during development). |
| 257 Set set = create(); | 257 Set set = create(); |
| 258 set.addAll([new EO(0), new EO(1), new EO(2)]); | 258 set.addAll([new CE(0), new CE(1), new CE(2)]); |
| 259 Expect.equals(3, set.length); // All different. | 259 Expect.equals(3, set.length); // All different. |
| 260 set.retainAll([new EO(0), new EO(2)]); | 260 set.retainAll([new CE(0), new CE(2)]); |
| 261 Expect.equals(2, set.length); | 261 Expect.equals(2, set.length); |
| 262 Expect.isTrue(set.contains(new EO(0))); | 262 Expect.isTrue(set.contains(new CE(0))); |
| 263 Expect.isTrue(set.contains(new EO(2))); | 263 Expect.isTrue(set.contains(new CE(2))); |
| 264 | 264 |
| 265 // If equality of set is identity, we can't internally use a non-identity | 265 // If equality of set is identity, we can't internally use a non-identity |
| 266 // based set because it might throw away equal objects that are not identical. | 266 // based set because it might throw away equal objects that are not identical. |
| 267 var elems = [new EO(0), new EO(1), new EO(2), new EO(0)]; | 267 var elems = [new CE(0), new CE(1), new CE(2), new CE(0)]; |
| 268 set = create(identical); | 268 set = create(identical, null, null, identityCompare); |
| 269 set.addAll(elems); | 269 set.addAll(elems); |
| 270 Expect.equals(4, set.length); | 270 Expect.equals(4, set.length); |
| 271 set.retainAll([elems[0], elems[2], elems[3]]); | 271 set.retainAll([elems[0], elems[2], elems[3]]); |
| 272 Expect.equals(3, set.length); | 272 Expect.equals(3, set.length); |
| 273 Expect.isTrue(set.contains(elems[0])); | 273 Expect.isTrue(set.contains(elems[0])); |
| 274 Expect.isTrue(set.contains(elems[2])); | 274 Expect.isTrue(set.contains(elems[2])); |
| 275 Expect.isTrue(set.contains(elems[3])); | 275 Expect.isTrue(set.contains(elems[3])); |
| 276 | 276 |
| 277 // If set equality is less precise than equality, we must not use equality | 277 // If set equality is less precise than equality, we must not use equality |
| 278 // internally to see if the element is there: | 278 // internally to see if the element is there: |
| 279 set = create(customEq(3), customHash(3), validKey); | 279 set = create(customEq(3), customHash(3), validKey, customCompare(3)); |
| 280 set.addAll([new EO(0), new EO(1), new EO(2)]); | 280 set.addAll([new CE(0), new CE(1), new CE(2)]); |
| 281 Expect.equals(3, set.length); | 281 Expect.equals(3, set.length); |
| 282 set.retainAll([new EO(3), new EO(5)]); | 282 set.retainAll([new CE(3), new CE(5)]); |
| 283 Expect.equals(2, set.length); | 283 Expect.equals(2, set.length); |
| 284 Expect.isTrue(set.contains(new EO(6))); | 284 Expect.isTrue(set.contains(new CE(6))); |
| 285 Expect.isTrue(set.contains(new EO(8))); | 285 Expect.isTrue(set.contains(new CE(8))); |
| 286 | 286 |
| 287 // It shouldn't matter if the input is a set. | 287 // It shouldn't matter if the input is a set. |
| 288 set.clear(); | 288 set.clear(); |
| 289 set.addAll([new EO(0), new EO(1), new EO(2)]); | 289 set.addAll([new CE(0), new CE(1), new CE(2)]); |
| 290 Expect.equals(3, set.length); | 290 Expect.equals(3, set.length); |
| 291 set.retainAll(new Set.from([new EO(3), new EO(5)])); | 291 set.retainAll(new Set.from([new CE(3), new CE(5)])); |
| 292 Expect.equals(2, set.length); | 292 Expect.equals(2, set.length); |
| 293 Expect.isTrue(set.contains(new EO(6))); | 293 Expect.isTrue(set.contains(new CE(6))); |
| 294 Expect.isTrue(set.contains(new EO(8))); | 294 Expect.isTrue(set.contains(new CE(8))); |
| 295 } |
| 296 |
| 297 void testDifferenceIntersection(create([equals, hashCode, validKey, compare])) { |
| 298 // Test that elements of intersection comes from receiver set. |
| 299 CE ce1a = new CE(1); |
| 300 CE ce1b = new CE(1); |
| 301 CE ce2 = new CE(2); |
| 302 CE ce3 = new CE(3); |
| 303 Expect.equals(ce1a, ce1b); // Sanity check. |
| 304 |
| 305 var set1 = create(); |
| 306 var set2 = create(); |
| 307 set1.add(ce1a); |
| 308 set1.add(ce2); |
| 309 set2.add(ce1b); |
| 310 set2.add(ce3); |
| 311 |
| 312 var difference = set1.difference(set2); |
| 313 testLength(1, difference); |
| 314 Expect.identical(ce2, difference.lookup(ce2)); |
| 315 |
| 316 difference = set2.difference(set1); |
| 317 testLength(1, difference); |
| 318 Expect.identical(ce3, difference.lookup(ce3)); |
| 319 |
| 320 // Difference uses other.contains to check for equality. |
| 321 var set3 = create(identical, identityHashCode, null, identityCompare); |
| 322 set3.add(ce1b); |
| 323 difference = set1.difference(set3); |
| 324 testLength(2, difference); // ce1a is not identical to element in set3. |
| 325 Expect.identical(ce1a, difference.lookup(ce1a)); |
| 326 Expect.identical(ce2, difference.lookup(ce2)); |
| 327 |
| 328 // Intesection always takes elements from receiver set. |
| 329 var intersection = set1.intersection(set2); |
| 330 testLength(1, intersection); |
| 331 Expect.identical(ce1a, intersection.lookup(ce1a)); |
| 332 |
| 333 intersection = set1.intersection(set3); |
| 334 testLength(0, intersection); |
| 295 } | 335 } |
| 296 | 336 |
| 297 // Objects that are equal based on data. | 337 // Objects that are equal based on data. |
| 298 class EO { | 338 class CE implements Comparable<CE> { |
| 299 final int id; | 339 final int id; |
| 300 const EO(this.id); | 340 const CE(this.id); |
| 301 int get hashCode => id; | 341 int get hashCode => id; |
| 302 bool operator==(Object other) => other is EO && id == (other as EO).id; | 342 bool operator==(Object other) => other is CE && id == (other as CE).id; |
| 343 int compareTo(CE other) => id - other.id; |
| 344 String toString() => "CE($id)"; |
| 303 } | 345 } |
| 304 | 346 |
| 305 // Equality of Id objects based on id modulo value. | 347 // Equality of Id objects based on id modulo value. |
| 306 Function customEq(int mod) => (EO e1, EO e2) => ((e1.id - e2.id) % mod) == 0; | 348 Function customEq(int mod) => (CE e1, CE e2) => ((e1.id - e2.id) % mod) == 0; |
| 307 Function customHash(int mod) => (EO e) => e.id % mod; | 349 Function customHash(int mod) => (CE e) => e.id % mod; |
| 308 bool validKey(Object o) => o is EO; | 350 Function customCompare(int mod) => (CE e1, CE e2) => |
| 309 | 351 (e1.id % mod) - (e2.id % mod); |
| 352 bool validKey(Object o) => o is CE; |
| 353 final customId = new Map.identity(); |
| 354 int counter = 0; |
| 355 int identityCompare(e1, e2) { |
| 356 if (identical(e1, e2)) return 0; |
| 357 int i1 = customId.putIfAbsent(e1, () => ++counter); |
| 358 int i2 = customId.putIfAbsent(e2, () => ++counter); |
| 359 return i1 - i2; |
| 360 } |
| 310 | 361 |
| 311 main() { | 362 main() { |
| 312 testMain(() => new HashSet()); | 363 testMain(() => new HashSet()); |
| 313 testMain(() => new LinkedHashSet()); | 364 testMain(() => new LinkedHashSet()); |
| 314 testMain(() => new HashSet(equals: identical)); | 365 testMain(() => new HashSet(equals: identical)); |
| 315 testMain(() => new LinkedHashSet(equals: identical)); | 366 testMain(() => new LinkedHashSet(equals: identical)); |
| 316 testMain(() => new HashSet(equals: (a, b) => a == b, | 367 testMain(() => new HashSet(equals: (a, b) => a == b, |
| 317 hashCode: (a) => -a.hashCode, | 368 hashCode: (a) => -a.hashCode, |
| 318 isValidKey: (a) => true)); | 369 isValidKey: (a) => true)); |
| 319 testMain(() => new LinkedHashSet( | 370 testMain(() => new LinkedHashSet( |
| 320 equals: (a, b) => a == b, | 371 equals: (a, b) => a == b, |
| 321 hashCode: (a) => -a.hashCode, | 372 hashCode: (a) => -a.hashCode, |
| 322 isValidKey: (a) => true)); | 373 isValidKey: (a) => true)); |
| 374 testMain(() => new SplayTreeSet()); |
| 323 | 375 |
| 324 testTypeAnnotations(new HashSet<int>()); | 376 testTypeAnnotations(new HashSet<int>()); |
| 325 testTypeAnnotations(new LinkedHashSet<int>()); | 377 testTypeAnnotations(new LinkedHashSet<int>()); |
| 326 testTypeAnnotations(new HashSet<int>(equals: identical)); | 378 testTypeAnnotations(new HashSet<int>(equals: identical)); |
| 327 testTypeAnnotations(new LinkedHashSet<int>(equals: identical)); | 379 testTypeAnnotations(new LinkedHashSet<int>(equals: identical)); |
| 328 testTypeAnnotations(new HashSet<int>(equals: (int a, int b) => a == b, | 380 testTypeAnnotations(new HashSet<int>(equals: (int a, int b) => a == b, |
| 329 hashCode: (int a) => a.hashCode, | 381 hashCode: (int a) => a.hashCode, |
| 330 isValidKey: (a) => a is int)); | 382 isValidKey: (a) => a is int)); |
| 331 testTypeAnnotations(new LinkedHashSet<int>(equals: (int a, int b) => a == b, | 383 testTypeAnnotations(new LinkedHashSet<int>(equals: (int a, int b) => a == b, |
| 332 hashCode: (int a) => a.hashCode, | 384 hashCode: (int a) => a.hashCode, |
| 333 isValidKey: (a) => a is int)); | 385 isValidKey: (a) => a is int)); |
| 386 testTypeAnnotations(new SplayTreeSet<int>()); |
| 334 | 387 |
| 335 testRetainWhere(([equals, hashCode, validKey]) => | 388 testRetainWhere(([equals, hashCode, validKey, comparator]) => |
| 336 new HashSet(equals: equals, hashCode: hashCode, isValidKey: validKey)); | 389 new HashSet(equals: equals, hashCode: hashCode, isValidKey: validKey)); |
| 337 testRetainWhere(([equals, hashCode, validKey]) => | 390 testRetainWhere(([equals, hashCode, validKey, comparator]) => |
| 338 new LinkedHashSet(equals: equals, hashCode: hashCode, | 391 new LinkedHashSet(equals: equals, hashCode: hashCode, |
| 339 isValidKey: validKey)); | 392 isValidKey: validKey)); |
| 393 testRetainWhere(([equals, hashCode, validKey, comparator]) => |
| 394 new SplayTreeSet(comparator, validKey)); |
| 395 |
| 396 testDifferenceIntersection(([equals, hashCode, validKey, comparator]) => |
| 397 new HashSet(equals: equals, hashCode: hashCode, isValidKey: validKey)); |
| 398 testDifferenceIntersection(([equals, hashCode, validKey, comparator]) => |
| 399 new LinkedHashSet(equals: equals, hashCode: hashCode, |
| 400 isValidKey: validKey)); |
| 401 testDifferenceIntersection(([equals, hashCode, validKey, comparator]) => |
| 402 new SplayTreeSet(comparator, validKey)); |
| 403 |
| 340 } | 404 } |
| OLD | NEW |