1 /* 2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6207984 6272521 6192552 6269713 6197726 6260652 5073546 4137464 27 * 4155650 4216399 4294891 6282555 6318622 6355327 6383475 6420753 28 * 6431845 4802633 6570566 6570575 6570631 6570924 6691185 6691215 29 * 4802647 7123424 8024709 30 * @summary Run many tests on many Collection and Map implementations 31 * @author Martin Buchholz 32 * @modules java.base/java.util:open 33 * @run main MOAT 34 * @key randomness 35 */ 36 37 /* Mother Of All (Collection) Tests 38 * 39 * Testing of collection classes is often spotty, because many tests 40 * need to be performed on many implementations, but the onus on 41 * writing the tests falls on the engineer introducing the new 42 * implementation. 43 * 44 * The idea of this mega-test is that: 45 * 46 * An engineer adding a new collection implementation could simply add 47 * their new implementation to a list of implementations in this 48 * test's main method. Any general purpose Collection<Integer> or 49 * Map<Integer,Integer> class is appropriate. 50 * 51 * An engineer fixing a regression could add their regression test here and 52 * simultaneously test all other implementations. 53 */ 54 55 import java.io.*; 56 import java.util.*; 57 import java.util.concurrent.*; 58 import static java.util.Collections.*; 59 import java.lang.reflect.*; 60 import java.util.stream.Collectors; 61 import java.util.stream.Stream; 62 63 public class MOAT { 64 // Collections under test must not be initialized to contain this value, 65 // and maps under test must not contain this value as a key. 66 // It's used as a sentinel for absent-element testing. 67 static final int ABSENT_VALUE = 778347983; 68 69 static final Integer[] integerArray; 70 static { 71 Integer[] ia = new Integer[20]; 72 // fill with 1..20 inclusive 73 for (int i = 0; i < ia.length; i++) { 74 ia[i] = i + 1; 75 } 76 integerArray = ia; 77 } 78 79 public static void realMain(String[] args) { 80 81 testCollection(new NewAbstractCollection<Integer>()); 82 testCollection(new NewAbstractSet<Integer>()); 83 testCollection(new LinkedHashSet<Integer>()); 84 testCollection(new HashSet<Integer>()); 85 testCollection(new Vector<Integer>()); 86 testCollection(new Vector<Integer>().subList(0,0)); 87 testCollection(new ArrayDeque<Integer>()); 88 testCollection(new ArrayList<Integer>()); 89 testCollection(new ArrayList<Integer>().subList(0,0)); 90 testCollection(new LinkedList<Integer>()); 91 testCollection(new LinkedList<Integer>().subList(0,0)); 92 testCollection(new TreeSet<Integer>()); 93 testCollection(Collections.checkedList(new ArrayList<Integer>(), Integer.class)); 94 testCollection(Collections.synchronizedList(new ArrayList<Integer>())); 95 testCollection(Collections.checkedSet(new HashSet<Integer>(), Integer.class)); 96 testCollection(Collections.checkedSortedSet(new TreeSet<Integer>(), Integer.class)); 97 testCollection(Collections.checkedNavigableSet(new TreeSet<Integer>(), Integer.class)); 98 testCollection(Collections.synchronizedSet(new HashSet<Integer>())); 99 testCollection(Collections.synchronizedSortedSet(new TreeSet<Integer>())); 100 testCollection(Collections.synchronizedNavigableSet(new TreeSet<Integer>())); 101 102 testCollection(new CopyOnWriteArrayList<Integer>()); 103 testCollection(new CopyOnWriteArrayList<Integer>().subList(0,0)); 104 testCollection(new CopyOnWriteArraySet<Integer>()); 105 testCollection(new PriorityQueue<Integer>()); 106 testCollection(new PriorityBlockingQueue<Integer>()); 107 testCollection(new ArrayBlockingQueue<Integer>(20)); 108 testCollection(new LinkedBlockingQueue<Integer>(20)); 109 testCollection(new LinkedBlockingDeque<Integer>(20)); 110 testCollection(new ConcurrentLinkedDeque<Integer>()); 111 testCollection(new ConcurrentLinkedQueue<Integer>()); 112 testCollection(new LinkedTransferQueue<Integer>()); 113 testCollection(new ConcurrentSkipListSet<Integer>()); 114 testCollection(Arrays.asList(new Integer(42))); 115 testCollection(Arrays.asList(1,2,3)); 116 testCollection(nCopies(25,1)); 117 testImmutableList(nCopies(25,1)); 118 119 testMap(new HashMap<Integer,Integer>()); 120 testMap(new LinkedHashMap<Integer,Integer>()); 121 122 // TODO: Add reliable support for WeakHashMap. 123 // This test is subject to very rare failures because the GC 124 // may remove unreferenced-keys from the map at any time. 125 // testMap(new WeakHashMap<Integer,Integer>()); 126 127 testMap(new IdentityHashMap<Integer,Integer>()); 128 testMap(new TreeMap<Integer,Integer>()); 129 testMap(new Hashtable<Integer,Integer>()); 130 testMap(new ConcurrentHashMap<Integer,Integer>(10, 0.5f)); 131 testMap(new ConcurrentSkipListMap<Integer,Integer>()); 132 testMap(Collections.checkedMap(new HashMap<Integer,Integer>(), Integer.class, Integer.class)); 133 testMap(Collections.checkedSortedMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class)); 134 testMap(Collections.checkedNavigableMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class)); 135 testMap(Collections.synchronizedMap(new HashMap<Integer,Integer>())); 136 testMap(Collections.synchronizedSortedMap(new TreeMap<Integer,Integer>())); 137 testMap(Collections.synchronizedNavigableMap(new TreeMap<Integer,Integer>())); 138 139 // Unmodifiable wrappers 140 testImmutableSet(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3)))); 141 testImmutableList(unmodifiableList(Arrays.asList(1,2,3))); 142 testImmutableMap(unmodifiableMap(Collections.singletonMap(1,2))); 143 testCollMutatorsAlwaysThrow(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3)))); 144 testCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet())); 145 testEmptyCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet())); 146 testListMutatorsAlwaysThrow(unmodifiableList(Arrays.asList(1,2,3))); 147 testListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList())); 148 testEmptyListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList())); 149 testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.singletonMap(1,2))); 150 testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap())); 151 testEmptyMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap())); 152 153 // Empty collections 154 final List<Integer> emptyArray = Arrays.asList(new Integer[]{}); 155 testCollection(emptyArray); 156 testEmptyList(emptyArray); 157 THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1)); 158 THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1)); 159 160 List<Integer> noOne = nCopies(0,1); 161 testCollection(noOne); 162 testEmptyList(noOne); 163 testImmutableList(noOne); 164 165 Set<Integer> emptySet = emptySet(); 166 testCollection(emptySet); 167 testEmptySet(emptySet); 168 testEmptySet(EMPTY_SET); 169 testEmptySet(Collections.emptySet()); 170 testEmptySet(Collections.emptySortedSet()); 171 testEmptySet(Collections.emptyNavigableSet()); 172 testImmutableSet(emptySet); 173 174 List<Integer> emptyList = emptyList(); 175 testCollection(emptyList); 176 testEmptyList(emptyList); 177 testEmptyList(EMPTY_LIST); 178 testEmptyList(Collections.emptyList()); 179 testImmutableList(emptyList); 180 181 Map<Integer,Integer> emptyMap = emptyMap(); 182 testMap(emptyMap); 183 testEmptyMap(emptyMap); 184 testEmptyMap(EMPTY_MAP); 185 testEmptyMap(Collections.emptyMap()); 186 testEmptyMap(Collections.emptySortedMap()); 187 testEmptyMap(Collections.emptyNavigableMap()); 188 testImmutableMap(emptyMap); 189 testImmutableMap(Collections.emptyMap()); 190 testImmutableMap(Collections.emptySortedMap()); 191 testImmutableMap(Collections.emptyNavigableMap()); 192 193 // Singleton collections 194 Set<Integer> singletonSet = singleton(1); 195 equal(singletonSet.size(), 1); 196 testCollection(singletonSet); 197 testImmutableSet(singletonSet); 198 199 List<Integer> singletonList = singletonList(1); 200 equal(singletonList.size(), 1); 201 testCollection(singletonList); 202 testImmutableList(singletonList); 203 testImmutableList(singletonList.subList(0,1)); 204 testImmutableList(singletonList.subList(0,1).subList(0,1)); 205 testEmptyList(singletonList.subList(0,0)); 206 testEmptyList(singletonList.subList(0,0).subList(0,0)); 207 208 Map<Integer,Integer> singletonMap = singletonMap(1,2); 209 equal(singletonMap.size(), 1); 210 testMap(singletonMap); 211 testImmutableMap(singletonMap); 212 213 // Immutable List 214 testEmptyList(List.of()); 215 testListMutatorsAlwaysThrow(List.of()); 216 testEmptyListMutatorsAlwaysThrow(List.of()); 217 for (List<Integer> list : Arrays.asList( 218 List.<Integer>of(), 219 List.of(1), 220 List.of(1, 2), 221 List.of(1, 2, 3), 222 List.of(1, 2, 3, 4), 223 List.of(1, 2, 3, 4, 5), 224 List.of(1, 2, 3, 4, 5, 6), 225 List.of(1, 2, 3, 4, 5, 6, 7), 226 List.of(1, 2, 3, 4, 5, 6, 7, 8), 227 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9), 228 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 229 List.of(integerArray))) { 230 testCollection(list); 231 testImmutableList(list); 232 testListMutatorsAlwaysThrow(list); 233 } 234 235 List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3)); 236 testCollection(listCopy); 237 testImmutableList(listCopy); 238 testListMutatorsAlwaysThrow(listCopy); 239 240 List<Integer> listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList()); 241 equal(listCollected, List.of(1, 2, 3)); 242 testCollection(listCollected); 243 testImmutableList(listCollected); 244 testListMutatorsAlwaysThrow(listCollected); 245 246 // Immutable Set 247 testEmptySet(Set.of()); 248 testCollMutatorsAlwaysThrow(Set.of()); 249 testEmptyCollMutatorsAlwaysThrow(Set.of()); 250 for (Set<Integer> set : Arrays.asList( 251 Set.<Integer>of(), 252 Set.of(1), 253 Set.of(1, 2), 254 Set.of(1, 2, 3), 255 Set.of(1, 2, 3, 4), 256 Set.of(1, 2, 3, 4, 5), 257 Set.of(1, 2, 3, 4, 5, 6), 258 Set.of(1, 2, 3, 4, 5, 6, 7), 259 Set.of(1, 2, 3, 4, 5, 6, 7, 8), 260 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9), 261 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 262 Set.of(integerArray))) { 263 testCollection(set); 264 testImmutableSet(set); 265 testCollMutatorsAlwaysThrow(set); 266 } 267 268 Set<Integer> setCopy = Set.copyOf(Arrays.asList(1, 2, 3)); 269 testCollection(setCopy); 270 testImmutableSet(setCopy); 271 testCollMutatorsAlwaysThrow(setCopy); 272 273 Set<Integer> setCollected = Stream.of(1, 1, 2, 3, 2, 3) 274 .collect(Collectors.toUnmodifiableSet()); 275 equal(setCollected, Set.of(1, 2, 3)); 276 testCollection(setCollected); 277 testImmutableSet(setCollected); 278 testCollMutatorsAlwaysThrow(setCollected); 279 280 // Immutable Map 281 282 @SuppressWarnings("unchecked") 283 Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20]; 284 for (int i = 0; i < ea.length; i++) { 285 ea[i] = Map.entry(i+1, i+101); 286 } 287 288 testEmptyMap(Map.of()); 289 testMapMutatorsAlwaysThrow(Map.of()); 290 testEmptyMapMutatorsAlwaysThrow(Map.of()); 291 for (Map<Integer,Integer> map : Arrays.asList( 292 Map.<Integer,Integer>of(), 293 Map.of(1, 101), 294 Map.of(1, 101, 2, 202), 295 Map.of(1, 101, 2, 202, 3, 303), 296 Map.of(1, 101, 2, 202, 3, 303, 4, 404), 297 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505), 298 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606), 299 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707), 300 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808), 301 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909), 302 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010), 303 Map.ofEntries(ea))) { 304 testMap(map); 305 testImmutableMap(map); 306 testMapMutatorsAlwaysThrow(map); 307 } 308 309 Map<Integer,Integer> mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303))); 310 testMap(mapCopy); 311 testImmutableMap(mapCopy); 312 testMapMutatorsAlwaysThrow(mapCopy); 313 314 Map<Integer,Integer> mapCollected1 = 315 Stream.of(1, 2, 3) 316 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); 317 equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303)); 318 testMap(mapCollected1); 319 testImmutableMap(mapCollected1); 320 testMapMutatorsAlwaysThrow(mapCollected1); 321 322 try { 323 Stream.of(1, 1, 2, 3, 2, 3) 324 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); 325 fail("duplicates should have thrown an exception"); 326 } catch (IllegalStateException ise) { 327 pass(); 328 } 329 330 Map<Integer,Integer> mapCollected2 = 331 Stream.of(1, 1, 2, 3, 2, 3) 332 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum)); 333 equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606)); 334 testMap(mapCollected2); 335 testImmutableMap(mapCollected2); 336 testMapMutatorsAlwaysThrow(mapCollected2); 337 } 338 339 private static void checkContainsSelf(Collection<Integer> c) { 340 check(c.containsAll(c)); 341 check(c.containsAll(Arrays.asList(c.toArray()))); 342 check(c.containsAll(Arrays.asList(c.toArray(new Integer[0])))); 343 } 344 345 private static void checkContainsEmpty(Collection<Integer> c) { 346 check(c.containsAll(new ArrayList<Integer>())); 347 } 348 349 private static void checkUnique(Set<Integer> s) { 350 for (Integer i : s) { 351 int count = 0; 352 for (Integer j : s) { 353 if (Objects.equals(i,j)) 354 ++count; 355 } 356 check(count == 1); 357 } 358 } 359 360 private static <T> void testEmptyCollection(Collection<T> c) { 361 check(c.isEmpty()); 362 equal(c.size(), 0); 363 equal(c.toString(),"[]"); 364 equal(c.toArray().length, 0); 365 equal(c.toArray(new Object[0]).length, 0); 366 equal(c.toArray(Object[]::new).length, 0); 367 check(c.toArray(new Object[]{42})[0] == null); 368 369 Object[] a = new Object[1]; a[0] = Boolean.TRUE; 370 equal(c.toArray(a), a); 371 equal(a[0], null); 372 testEmptyIterator(c.iterator()); 373 } 374 375 static <T> void testEmptyIterator(final Iterator<T> it) { 376 if (rnd.nextBoolean()) 377 check(! it.hasNext()); 378 379 THROWS(NoSuchElementException.class, () -> it.next()); 380 381 try { it.remove(); } 382 catch (IllegalStateException ignored) { pass(); } 383 catch (UnsupportedOperationException ignored) { pass(); } 384 catch (Throwable t) { unexpected(t); } 385 386 if (rnd.nextBoolean()) 387 check(! it.hasNext()); 388 } 389 390 private static void testEmptyList(List<?> c) { 391 testEmptyCollection(c); 392 equal(c.hashCode(), 1); 393 equal2(c, Collections.<Integer>emptyList()); 394 } 395 396 private static <T> void testEmptySet(Set<T> c) { 397 testEmptyCollection(c); 398 equal(c.hashCode(), 0); 399 equal2(c, Collections.<Integer>emptySet()); 400 if (c instanceof NavigableSet<?>) 401 testEmptyIterator(((NavigableSet<T>)c).descendingIterator()); 402 } 403 404 private static void testImmutableCollection(final Collection<Integer> c) { 405 THROWS(UnsupportedOperationException.class, 406 () -> c.add(99), 407 () -> c.addAll(singleton(99))); 408 if (! c.isEmpty()) { 409 final Integer first = c.iterator().next(); 410 THROWS(UnsupportedOperationException.class, 411 () -> c.clear(), 412 () -> c.remove(first), 413 () -> c.removeAll(singleton(first)), 414 () -> c.retainAll(emptyList())); 415 } 416 } 417 418 private static void testImmutableSet(final Set<Integer> c) { 419 testImmutableCollection(c); 420 } 421 422 private static void testImmutableList(final List<Integer> c) { 423 testList(c); 424 testImmutableCollection(c); 425 THROWS(UnsupportedOperationException.class, 426 () -> c.set(0,42), 427 () -> c.add(0,42), 428 () -> c.addAll(0,singleton(86))); 429 if (! c.isEmpty()) 430 THROWS(UnsupportedOperationException.class, 431 () -> { Iterator<Integer> it = c.iterator(); 432 it.next(); 433 it.remove(); }, 434 () -> { ListIterator<Integer> it = c.listIterator(); 435 it.next(); 436 it.remove(); }); 437 } 438 439 /** 440 * Test that calling a mutator always throws UOE, even if the mutator 441 * wouldn't actually do anything, given its arguments. 442 * 443 * @param c the collection instance to test 444 */ 445 private static void testCollMutatorsAlwaysThrow(Collection<Integer> c) { 446 THROWS(UnsupportedOperationException.class, 447 () -> c.addAll(Collections.emptyList()), 448 () -> c.remove(ABSENT_VALUE), 449 () -> c.removeAll(Collections.emptyList()), 450 () -> c.removeIf(x -> false), 451 () -> c.retainAll(c)); 452 } 453 454 /** 455 * Test that calling a mutator always throws UOE, even if the mutator 456 * wouldn't actually do anything on an empty collection. 457 * 458 * @param c the collection instance to test, must be empty 459 */ 460 private static void testEmptyCollMutatorsAlwaysThrow(Collection<Integer> c) { 461 if (! c.isEmpty()) { 462 fail("collection is not empty"); 463 } 464 THROWS(UnsupportedOperationException.class, 465 () -> c.clear()); 466 } 467 468 /** 469 * As above, for a list. 470 * 471 * @param c the list instance to test 472 */ 473 private static void testListMutatorsAlwaysThrow(List<Integer> c) { 474 testCollMutatorsAlwaysThrow(c); 475 THROWS(UnsupportedOperationException.class, 476 () -> c.addAll(0, Collections.emptyList())); 477 } 478 479 /** 480 * As above, for an empty list. 481 * 482 * @param c the list instance to test, must be empty 483 */ 484 private static void testEmptyListMutatorsAlwaysThrow(List<Integer> c) { 485 if (! c.isEmpty()) { 486 fail("list is not empty"); 487 } 488 testEmptyCollMutatorsAlwaysThrow(c); 489 THROWS(UnsupportedOperationException.class, 490 () -> c.replaceAll(x -> x), 491 () -> c.sort(null)); 492 } 493 494 /** 495 * As above, for a map. 496 * 497 * @param m the map instance to test 498 */ 499 private static void testMapMutatorsAlwaysThrow(Map<Integer,Integer> m) { 500 THROWS(UnsupportedOperationException.class, 501 () -> m.compute(ABSENT_VALUE, (k, v) -> null), 502 () -> m.computeIfAbsent(ABSENT_VALUE, k -> null), 503 () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null), 504 () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null), 505 () -> m.putAll(Collections.emptyMap()), 506 () -> m.remove(ABSENT_VALUE), 507 () -> m.remove(ABSENT_VALUE, 0), 508 () -> m.replace(ABSENT_VALUE, 0), 509 () -> m.replace(ABSENT_VALUE, 0, 1)); 510 } 511 512 /** 513 * As above, for an empty map. 514 * 515 * @param map the map instance to test, must be empty 516 */ 517 private static void testEmptyMapMutatorsAlwaysThrow(Map<Integer,Integer> m) { 518 if (! m.isEmpty()) { 519 fail("map is not empty"); 520 } 521 THROWS(UnsupportedOperationException.class, 522 () -> m.clear(), 523 () -> m.replaceAll((k, v) -> v)); 524 } 525 526 private static void clear(Collection<Integer> c) { 527 try { c.clear(); } 528 catch (Throwable t) { unexpected(t); } 529 testEmptyCollection(c); 530 } 531 532 private static <K,V> void testEmptyMap(final Map<K,V> m) { 533 check(m.isEmpty()); 534 equal(m.size(), 0); 535 equal(m.toString(),"{}"); 536 testEmptySet(m.keySet()); 537 testEmptySet(m.entrySet()); 538 testEmptyCollection(m.values()); 539 540 try { check(! m.containsValue(null)); } 541 catch (NullPointerException ignored) { /* OK */ } 542 try { check(! m.containsKey(null)); } 543 catch (NullPointerException ignored) { /* OK */ } 544 check(! m.containsValue(1)); 545 check(! m.containsKey(1)); 546 } 547 548 private static void testImmutableMap(final Map<Integer,Integer> m) { 549 THROWS(UnsupportedOperationException.class, 550 () -> m.put(1,1), 551 () -> m.putAll(singletonMap(1,1))); 552 if (! m.isEmpty()) { 553 final Integer first = m.keySet().iterator().next(); 554 THROWS(UnsupportedOperationException.class, 555 () -> m.remove(first), 556 () -> m.clear()); 557 final Map.Entry<Integer,Integer> me 558 = m.entrySet().iterator().next(); 559 Integer key = me.getKey(); 560 Integer val = me.getValue(); 561 THROWS(UnsupportedOperationException.class, 562 () -> me.setValue(3)); 563 equal(key, me.getKey()); 564 equal(val, me.getValue()); 565 } 566 testImmutableSet(m.keySet()); 567 testImmutableCollection(m.values()); 568 //testImmutableSet(m.entrySet()); 569 } 570 571 private static void clear(Map<?,?> m) { 572 try { m.clear(); } 573 catch (Throwable t) { unexpected(t); } 574 testEmptyMap(m); 575 } 576 577 private static void oneElement(Collection<Integer> c) { 578 clear(c); 579 try { 580 check(c.add(-42)); 581 equal(c.toString(), "[-42]"); 582 if (c instanceof Set) check(! c.add(-42)); 583 } catch (Throwable t) { unexpected(t); } 584 check(! c.isEmpty()); check(c.size() == 1); 585 } 586 587 private static boolean supportsAdd(Collection<Integer> c) { 588 try { check(c.add(ABSENT_VALUE)); } 589 catch (UnsupportedOperationException t) { return false; } 590 catch (Throwable t) { unexpected(t); } 591 592 try { 593 check(c.contains(ABSENT_VALUE)); 594 check(c.remove(ABSENT_VALUE)); 595 } catch (Throwable t) { unexpected(t); } 596 return true; 597 } 598 599 private static boolean supportsRemove(Collection<Integer> c) { 600 try { check(! c.remove(ABSENT_VALUE)); } 601 catch (UnsupportedOperationException t) { return false; } 602 catch (Throwable t) { unexpected(t); } 603 return true; 604 } 605 606 // 6260652: (coll) Arrays.asList(x).toArray().getClass() 607 // should be Object[].class 608 // Fixed in jdk9, but not jdk8 ... 609 static final boolean needToWorkAround6260652 = 610 Arrays.asList("").toArray().getClass() != Object[].class; 611 612 private static void checkFunctionalInvariants(Collection<Integer> c) { 613 try { 614 checkContainsSelf(c); 615 checkContainsEmpty(c); 616 check(c.size() != 0 ^ c.isEmpty()); 617 check(! c.contains(ABSENT_VALUE)); 618 619 { 620 int size = 0; 621 for (Integer i : c) size++; 622 check(c.size() == size); 623 } 624 625 if (c instanceof Set) { 626 checkUnique((Set<Integer>)c); 627 } 628 629 check(c.toArray().length == c.size()); 630 check(c.toArray().getClass() == Object[].class 631 || 632 (needToWorkAround6260652 && 633 c.getClass().getName().equals("java.util.Arrays$ArrayList"))); 634 for (int size : new int[]{0,1,c.size(), c.size()+1}) { 635 Integer[] a = c.toArray(new Integer[size]); 636 check((size > c.size()) || a.length == c.size()); 637 int i = 0; for (Integer j : c) check(a[i++] == j); 638 check((size <= c.size()) || (a[c.size()] == null)); 639 check(a.getClass() == Integer[].class); 640 } 641 642 { 643 Integer[] a = c.toArray(Integer[]::new); 644 equal(c.size(), a.length); 645 check(a.getClass() == Integer[].class); 646 check(Arrays.equals(c.toArray(new Integer[0]), a)); 647 } 648 649 check(c.equals(c)); 650 if (c instanceof Serializable) { 651 //System.out.printf("Serializing %s%n", c.getClass().getName()); 652 try { 653 Object clone = serialClone(c); 654 equal(c instanceof Serializable, 655 clone instanceof Serializable); 656 equal(c instanceof RandomAccess, 657 clone instanceof RandomAccess); 658 if ((c instanceof List) || (c instanceof Set)) 659 equal(c, clone); 660 else 661 equal(new HashSet<Integer>(c), 662 new HashSet<Integer>(serialClone(c))); 663 } catch (Error xxx) { 664 if (! (xxx.getCause() instanceof NotSerializableException)) 665 throw xxx; 666 } 667 } 668 } 669 catch (Throwable t) { unexpected(t); } 670 } 671 672 //---------------------------------------------------------------- 673 // If add(null) succeeds, contains(null) & remove(null) should succeed 674 //---------------------------------------------------------------- 675 private static void testNullElement(Collection<Integer> c) { 676 677 try { 678 check(c.add(null)); 679 if (c.size() == 1) 680 equal(c.toString(), "[null]"); 681 try { 682 checkFunctionalInvariants(c); 683 check(c.contains(null)); 684 check(c.remove(null)); 685 } 686 catch (Throwable t) { unexpected(t); } 687 } 688 catch (NullPointerException e) { /* OK */ } 689 catch (Throwable t) { unexpected(t); } 690 } 691 692 //---------------------------------------------------------------- 693 // If add("x") succeeds, contains("x") & remove("x") should succeed 694 //---------------------------------------------------------------- 695 @SuppressWarnings("unchecked") 696 private static void testStringElement(Collection<Integer> c) { 697 Collection x = (Collection)c; // Make type-unsafe 698 try { 699 check(x.add("x")); 700 try { 701 check(x.contains("x")); 702 check(x.remove("x")); 703 } catch (Throwable t) { unexpected(t); } 704 } 705 catch (ClassCastException e) { /* OK */ } 706 catch (Throwable t) { unexpected(t); } 707 } 708 709 private static void testConcurrentCollection(Collection<Integer> c) { 710 try { 711 c.add(1); 712 Iterator<Integer> it = c.iterator(); 713 check(it.hasNext()); 714 clear(c); 715 check(it.next() instanceof Integer); // No CME 716 check(c.isEmpty()); 717 } 718 catch (Throwable t) { unexpected(t); } 719 } 720 721 private static void testQueue(Queue<Integer> q) { 722 q.clear(); 723 for (int i = 0; i < 5; i++) { 724 testQueueAddRemove(q, null); 725 testQueueAddRemove(q, 537); 726 q.add(i); 727 } 728 equal(q.size(), 5); 729 checkFunctionalInvariants(q); 730 q.poll(); 731 equal(q.size(), 4); 732 checkFunctionalInvariants(q); 733 if ((q instanceof LinkedBlockingQueue) || 734 (q instanceof LinkedBlockingDeque) || 735 (q instanceof ConcurrentLinkedDeque) || 736 (q instanceof ConcurrentLinkedQueue)) { 737 testQueueIteratorRemove(q); 738 } 739 } 740 741 private static void testQueueAddRemove(final Queue<Integer> q, 742 final Integer e) { 743 final List<Integer> originalContents = new ArrayList<>(q); 744 final boolean isEmpty = q.isEmpty(); 745 final boolean isList = (q instanceof List); 746 final List asList = isList ? (List) q : null; 747 check(!q.contains(e)); 748 try { 749 q.add(e); 750 } catch (NullPointerException npe) { 751 check(e == null); 752 return; // Null elements not supported 753 } 754 check(q.contains(e)); 755 check(q.remove(e)); 756 check(!q.contains(e)); 757 equal(new ArrayList<Integer>(q), originalContents); 758 759 if (q instanceof Deque<?>) { 760 final Deque<Integer> deq = (Deque<Integer>) q; 761 final List<Integer> singleton = Collections.singletonList(e); 762 763 // insert, query, remove element at head 764 if (isEmpty) { 765 THROWS(NoSuchElementException.class, 766 () -> deq.getFirst(), 767 () -> deq.element(), 768 () -> deq.iterator().next()); 769 check(deq.peekFirst() == null); 770 check(deq.peek() == null); 771 } else { 772 check(deq.getFirst() != e); 773 check(deq.element() != e); 774 check(deq.iterator().next() != e); 775 check(deq.peekFirst() != e); 776 check(deq.peek() != e); 777 } 778 check(!deq.contains(e)); 779 check(!deq.removeFirstOccurrence(e)); 780 check(!deq.removeLastOccurrence(e)); 781 if (isList) { 782 check(asList.indexOf(e) == -1); 783 check(asList.lastIndexOf(e) == -1); 784 } 785 switch (rnd.nextInt(isList ? 4 : 3)) { 786 case 0: deq.addFirst(e); break; 787 case 1: check(deq.offerFirst(e)); break; 788 case 2: deq.push(e); break; 789 case 3: asList.add(0, e); break; 790 default: throw new AssertionError(); 791 } 792 check(deq.peekFirst() == e); 793 check(deq.getFirst() == e); 794 check(deq.element() == e); 795 check(deq.peek() == e); 796 check(deq.iterator().next() == e); 797 check(deq.contains(e)); 798 if (isList) { 799 check(asList.get(0) == e); 800 check(asList.indexOf(e) == 0); 801 check(asList.lastIndexOf(e) == 0); 802 check(asList.subList(0, 1).equals(singleton)); 803 } 804 switch (rnd.nextInt(isList ? 11 : 9)) { 805 case 0: check(deq.pollFirst() == e); break; 806 case 1: check(deq.removeFirst() == e); break; 807 case 2: check(deq.remove() == e); break; 808 case 3: check(deq.pop() == e); break; 809 case 4: check(deq.removeFirstOccurrence(e)); break; 810 case 5: check(deq.removeLastOccurrence(e)); break; 811 case 6: check(deq.remove(e)); break; 812 case 7: check(deq.removeAll(singleton)); break; 813 case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break; 814 case 9: asList.remove(0); break; 815 case 10: asList.subList(0, 1).clear(); break; 816 default: throw new AssertionError(); 817 } 818 if (isEmpty) { 819 THROWS(NoSuchElementException.class, 820 () -> deq.getFirst(), 821 () -> deq.element(), 822 () -> deq.iterator().next()); 823 check(deq.peekFirst() == null); 824 check(deq.peek() == null); 825 } else { 826 check(deq.getFirst() != e); 827 check(deq.element() != e); 828 check(deq.iterator().next() != e); 829 check(deq.peekFirst() != e); 830 check(deq.peek() != e); 831 } 832 check(!deq.contains(e)); 833 check(!deq.removeFirstOccurrence(e)); 834 check(!deq.removeLastOccurrence(e)); 835 if (isList) { 836 check(isEmpty || asList.get(0) != e); 837 check(asList.indexOf(e) == -1); 838 check(asList.lastIndexOf(e) == -1); 839 } 840 equal(new ArrayList<Integer>(deq), originalContents); 841 842 // insert, query, remove element at tail 843 if (isEmpty) { 844 check(deq.peekLast() == null); 845 THROWS(NoSuchElementException.class, () -> deq.getLast()); 846 } else { 847 check(deq.peekLast() != e); 848 check(deq.getLast() != e); 849 } 850 switch (rnd.nextInt(isList ? 6 : 4)) { 851 case 0: deq.addLast(e); break; 852 case 1: check(deq.offerLast(e)); break; 853 case 2: check(deq.add(e)); break; 854 case 3: deq.addAll(singleton); break; 855 case 4: asList.addAll(deq.size(), singleton); break; 856 case 5: asList.add(deq.size(), e); break; 857 default: throw new AssertionError(); 858 } 859 check(deq.peekLast() == e); 860 check(deq.getLast() == e); 861 check(deq.contains(e)); 862 if (isList) { 863 ListIterator it = asList.listIterator(asList.size()); 864 check(it.previous() == e); 865 check(asList.get(asList.size() - 1) == e); 866 check(asList.indexOf(e) == asList.size() - 1); 867 check(asList.lastIndexOf(e) == asList.size() - 1); 868 int size = asList.size(); 869 check(asList.subList(size - 1, size).equals(singleton)); 870 } 871 switch (rnd.nextInt(isList ? 8 : 6)) { 872 case 0: check(deq.pollLast() == e); break; 873 case 1: check(deq.removeLast() == e); break; 874 case 2: check(deq.removeFirstOccurrence(e)); break; 875 case 3: check(deq.removeLastOccurrence(e)); break; 876 case 4: check(deq.remove(e)); break; 877 case 5: check(deq.removeAll(singleton)); break; 878 case 6: asList.remove(asList.size() - 1); break; 879 case 7: 880 ListIterator it = asList.listIterator(asList.size()); 881 it.previous(); 882 it.remove(); 883 break; 884 default: throw new AssertionError(); 885 } 886 if (isEmpty) { 887 check(deq.peekLast() == null); 888 THROWS(NoSuchElementException.class, () -> deq.getLast()); 889 } else { 890 check(deq.peekLast() != e); 891 check(deq.getLast() != e); 892 } 893 check(!deq.contains(e)); 894 equal(new ArrayList<Integer>(deq), originalContents); 895 896 // Test operations on empty deque 897 switch (rnd.nextInt(isList ? 4 : 2)) { 898 case 0: deq.clear(); break; 899 case 1: 900 Iterator it = deq.iterator(); 901 while (it.hasNext()) { 902 it.next(); 903 it.remove(); 904 } 905 break; 906 case 2: asList.subList(0, asList.size()).clear(); break; 907 case 3: 908 ListIterator lit = asList.listIterator(asList.size()); 909 while (lit.hasPrevious()) { 910 lit.previous(); 911 lit.remove(); 912 } 913 break; 914 default: throw new AssertionError(); 915 } 916 testEmptyCollection(deq); 917 check(!deq.iterator().hasNext()); 918 if (isList) { 919 check(!asList.listIterator().hasPrevious()); 920 THROWS(NoSuchElementException.class, 921 () -> asList.listIterator().previous()); 922 } 923 THROWS(NoSuchElementException.class, 924 () -> deq.iterator().next(), 925 () -> deq.element(), 926 () -> deq.getFirst(), 927 () -> deq.getLast(), 928 () -> deq.pop(), 929 () -> deq.remove(), 930 () -> deq.removeFirst(), 931 () -> deq.removeLast()); 932 933 check(deq.poll() == null); 934 check(deq.pollFirst() == null); 935 check(deq.pollLast() == null); 936 check(deq.peek() == null); 937 check(deq.peekFirst() == null); 938 check(deq.peekLast() == null); 939 check(!deq.removeFirstOccurrence(e)); 940 check(!deq.removeLastOccurrence(e)); 941 942 check(deq.addAll(originalContents) == !isEmpty); 943 equal(new ArrayList<Integer>(deq), originalContents); 944 check(!deq.addAll(Collections.<Integer>emptyList())); 945 equal(new ArrayList<Integer>(deq), originalContents); 946 } 947 } 948 949 private static void testQueueIteratorRemove(Queue<Integer> q) { 950 System.err.printf("testQueueIteratorRemove %s%n", 951 q.getClass().getSimpleName()); 952 q.clear(); 953 for (int i = 0; i < 5; i++) 954 q.add(i); 955 Iterator<Integer> it = q.iterator(); 956 check(it.hasNext()); 957 for (int i = 3; i >= 0; i--) 958 q.remove(i); 959 equal(it.next(), 0); 960 equal(it.next(), 4); 961 962 q.clear(); 963 for (int i = 0; i < 5; i++) 964 q.add(i); 965 it = q.iterator(); 966 equal(it.next(), 0); 967 check(it.hasNext()); 968 for (int i = 1; i < 4; i++) 969 q.remove(i); 970 equal(it.next(), 1); 971 equal(it.next(), 4); 972 } 973 974 private static void testList(final List<Integer> l) { 975 //---------------------------------------------------------------- 976 // 4802633: (coll) AbstractList.addAll(-1,emptyCollection) 977 // doesn't throw IndexOutOfBoundsException 978 //---------------------------------------------------------------- 979 try { 980 l.addAll(-1, Collections.<Integer>emptyList()); 981 fail("Expected IndexOutOfBoundsException not thrown"); 982 } 983 catch (UnsupportedOperationException ignored) {/* OK */} 984 catch (IndexOutOfBoundsException ignored) {/* OK */} 985 catch (Throwable t) { unexpected(t); } 986 987 // equal(l instanceof Serializable, 988 // l.subList(0,0) instanceof Serializable); 989 if (l.subList(0,0) instanceof Serializable) 990 check(l instanceof Serializable); 991 992 equal(l instanceof RandomAccess, 993 l.subList(0,0) instanceof RandomAccess); 994 995 l.iterator(); 996 l.listIterator(); 997 l.listIterator(0); 998 l.listIterator(l.size()); 999 THROWS(IndexOutOfBoundsException.class, 1000 () -> l.listIterator(-1), 1001 () -> l.listIterator(l.size() + 1)); 1002 1003 if (l instanceof AbstractList) { 1004 try { 1005 int size = l.size(); 1006 AbstractList<Integer> abList = (AbstractList<Integer>) l; 1007 Method m = AbstractList.class.getDeclaredMethod("removeRange", new Class[] { int.class, int.class }); 1008 m.setAccessible(true); 1009 m.invoke(abList, new Object[] { 0, 0 }); 1010 m.invoke(abList, new Object[] { size, size }); 1011 equal(size, l.size()); 1012 } 1013 catch (UnsupportedOperationException ignored) {/* OK */} 1014 catch (Throwable t) { unexpected(t); } 1015 } 1016 } 1017 1018 private static void testCollection(Collection<Integer> c) { 1019 try { testCollection1(c); } 1020 catch (Throwable t) { unexpected(t); } 1021 } 1022 1023 private static void testCollection1(Collection<Integer> c) { 1024 1025 System.out.println("\n==> " + c.getClass().getName()); 1026 1027 checkFunctionalInvariants(c); 1028 1029 if (! supportsAdd(c)) return; 1030 //System.out.println("add() supported"); 1031 1032 if (c instanceof NavigableSet) { 1033 System.out.println("NavigableSet tests..."); 1034 1035 NavigableSet<Integer> ns = (NavigableSet<Integer>)c; 1036 testNavigableSet(ns); 1037 testNavigableSet(ns.headSet(6, false)); 1038 testNavigableSet(ns.headSet(5, true)); 1039 testNavigableSet(ns.tailSet(0, false)); 1040 testNavigableSet(ns.tailSet(1, true)); 1041 testNavigableSet(ns.subSet(0, false, 5, true)); 1042 testNavigableSet(ns.subSet(1, true, 6, false)); 1043 } 1044 1045 if (c instanceof Queue) 1046 testQueue((Queue<Integer>)c); 1047 1048 if (c instanceof List) 1049 testList((List<Integer>)c); 1050 1051 check(supportsRemove(c)); 1052 1053 try { 1054 oneElement(c); 1055 checkFunctionalInvariants(c); 1056 } 1057 catch (Throwable t) { unexpected(t); } 1058 1059 clear(c); testNullElement(c); 1060 oneElement(c); testNullElement(c); 1061 1062 clear(c); testStringElement(c); 1063 oneElement(c); testStringElement(c); 1064 1065 if (c.getClass().getName().matches(".*concurrent.*")) 1066 testConcurrentCollection(c); 1067 1068 //---------------------------------------------------------------- 1069 // The "all" operations should throw NPE when passed null 1070 //---------------------------------------------------------------- 1071 { 1072 clear(c); 1073 try { 1074 c.removeAll(null); 1075 fail("Expected NullPointerException"); 1076 } 1077 catch (NullPointerException e) { pass(); } 1078 catch (Throwable t) { unexpected(t); } 1079 1080 oneElement(c); 1081 try { 1082 c.removeAll(null); 1083 fail("Expected NullPointerException"); 1084 } 1085 catch (NullPointerException e) { pass(); } 1086 catch (Throwable t) { unexpected(t); } 1087 1088 clear(c); 1089 try { 1090 c.retainAll(null); 1091 fail("Expected NullPointerException"); 1092 } 1093 catch (NullPointerException e) { pass(); } 1094 catch (Throwable t) { unexpected(t); } 1095 1096 oneElement(c); 1097 try { 1098 c.retainAll(null); 1099 fail("Expected NullPointerException"); 1100 } 1101 catch (NullPointerException e) { pass(); } 1102 catch (Throwable t) { unexpected(t); } 1103 1104 oneElement(c); 1105 try { 1106 c.addAll(null); 1107 fail("Expected NullPointerException"); 1108 } 1109 catch (NullPointerException e) { pass(); } 1110 catch (Throwable t) { unexpected(t); } 1111 1112 oneElement(c); 1113 try { 1114 c.containsAll(null); 1115 fail("Expected NullPointerException"); 1116 } 1117 catch (NullPointerException e) { pass(); } 1118 catch (Throwable t) { unexpected(t); } 1119 } 1120 } 1121 1122 //---------------------------------------------------------------- 1123 // Map 1124 //---------------------------------------------------------------- 1125 private static void checkFunctionalInvariants(Map<Integer,Integer> m) { 1126 check(m.keySet().size() == m.entrySet().size()); 1127 check(m.keySet().size() == m.size()); 1128 checkFunctionalInvariants(m.keySet()); 1129 checkFunctionalInvariants(m.values()); 1130 check(m.size() != 0 ^ m.isEmpty()); 1131 check(! m.containsKey(ABSENT_VALUE)); 1132 1133 if (m instanceof Serializable) { 1134 //System.out.printf("Serializing %s%n", m.getClass().getName()); 1135 try { 1136 Object clone = serialClone(m); 1137 equal(m instanceof Serializable, 1138 clone instanceof Serializable); 1139 equal(m, clone); 1140 } catch (Error xxx) { 1141 if (! (xxx.getCause() instanceof NotSerializableException)) 1142 throw xxx; 1143 } 1144 } 1145 } 1146 1147 private static void testMap(Map<Integer,Integer> m) { 1148 System.out.println("\n==> " + m.getClass().getName()); 1149 1150 if (m instanceof ConcurrentMap) 1151 testConcurrentMap((ConcurrentMap<Integer,Integer>) m); 1152 1153 if (m instanceof NavigableMap) { 1154 System.out.println("NavigableMap tests..."); 1155 1156 NavigableMap<Integer,Integer> nm = 1157 (NavigableMap<Integer,Integer>) m; 1158 testNavigableMapRemovers(nm); 1159 testNavigableMap(nm); 1160 testNavigableMap(nm.headMap(6, false)); 1161 testNavigableMap(nm.headMap(5, true)); 1162 testNavigableMap(nm.tailMap(0, false)); 1163 testNavigableMap(nm.tailMap(1, true)); 1164 testNavigableMap(nm.subMap(1, true, 6, false)); 1165 testNavigableMap(nm.subMap(0, false, 5, true)); 1166 } 1167 1168 checkFunctionalInvariants(m); 1169 1170 if (supportsClear(m)) { 1171 try { clear(m); } 1172 catch (Throwable t) { unexpected(t); } 1173 } 1174 1175 if (supportsPut(m)) { 1176 try { 1177 check(m.put(3333, 77777) == null); 1178 check(m.put(9134, 74982) == null); 1179 check(m.get(9134) == 74982); 1180 check(m.put(9134, 1382) == 74982); 1181 check(m.get(9134) == 1382); 1182 check(m.size() == 2); 1183 checkFunctionalInvariants(m); 1184 checkNPEConsistency(m); 1185 } 1186 catch (Throwable t) { unexpected(t); } 1187 } 1188 } 1189 1190 private static boolean supportsPut(Map<Integer,Integer> m) { 1191 // We're asking for .equals(...) semantics 1192 if (m instanceof IdentityHashMap) return false; 1193 1194 try { check(m.put(ABSENT_VALUE,12735) == null); } 1195 catch (UnsupportedOperationException t) { return false; } 1196 catch (Throwable t) { unexpected(t); } 1197 1198 try { 1199 check(m.containsKey(ABSENT_VALUE)); 1200 check(m.remove(ABSENT_VALUE) != null); 1201 } catch (Throwable t) { unexpected(t); } 1202 return true; 1203 } 1204 1205 private static boolean supportsClear(Map<?,?> m) { 1206 try { m.clear(); } 1207 catch (UnsupportedOperationException t) { return false; } 1208 catch (Throwable t) { unexpected(t); } 1209 return true; 1210 } 1211 1212 //---------------------------------------------------------------- 1213 // ConcurrentMap 1214 //---------------------------------------------------------------- 1215 private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) { 1216 System.out.println("ConcurrentMap tests..."); 1217 1218 try { 1219 clear(m); 1220 1221 check(m.putIfAbsent(18357,7346) == null); 1222 check(m.containsKey(18357)); 1223 check(m.putIfAbsent(18357,8263) == 7346); 1224 try { m.putIfAbsent(18357,null); fail("NPE"); } 1225 catch (NullPointerException t) { } 1226 check(m.containsKey(18357)); 1227 1228 check(! m.replace(18357,8888,7777)); 1229 check(m.containsKey(18357)); 1230 try { m.replace(18357,null,7777); fail("NPE"); } 1231 catch (NullPointerException t) { } 1232 check(m.containsKey(18357)); 1233 check(m.get(18357) == 7346); 1234 check(m.replace(18357,7346,5555)); 1235 check(m.replace(18357,5555,7346)); 1236 check(m.get(18357) == 7346); 1237 1238 check(m.replace(92347,7834) == null); 1239 try { m.replace(18357,null); fail("NPE"); } 1240 catch (NullPointerException t) { } 1241 check(m.replace(18357,7346) == 7346); 1242 check(m.replace(18357,5555) == 7346); 1243 check(m.get(18357) == 5555); 1244 check(m.replace(18357,7346) == 5555); 1245 check(m.get(18357) == 7346); 1246 1247 check(! m.remove(18357,9999)); 1248 check(m.get(18357) == 7346); 1249 check(m.containsKey(18357)); 1250 check(! m.remove(18357,null)); // 6272521 1251 check(m.get(18357) == 7346); 1252 check(m.remove(18357,7346)); 1253 check(m.get(18357) == null); 1254 check(! m.containsKey(18357)); 1255 check(m.isEmpty()); 1256 1257 m.putIfAbsent(1,2); 1258 check(m.size() == 1); 1259 check(! m.remove(1,null)); 1260 check(! m.remove(1,null)); 1261 check(! m.remove(1,1)); 1262 check(m.remove(1,2)); 1263 check(m.isEmpty()); 1264 1265 testEmptyMap(m); 1266 } 1267 catch (Throwable t) { unexpected(t); } 1268 } 1269 1270 private static void throwsConsistently(Class<? extends Throwable> k, 1271 Iterable<Fun> fs) { 1272 List<Class<? extends Throwable>> threw = new ArrayList<>(); 1273 for (Fun f : fs) 1274 try { f.f(); threw.add(null); } 1275 catch (Throwable t) { 1276 check(k.isAssignableFrom(t.getClass())); 1277 threw.add(t.getClass()); 1278 } 1279 if (new HashSet<Object>(threw).size() != 1) 1280 fail(threw.toString()); 1281 } 1282 1283 private static <T> void checkNPEConsistency(final Map<T,Integer> m) { 1284 m.clear(); 1285 final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap) 1286 ? (ConcurrentMap<T,Integer>) m 1287 : null; 1288 List<Fun> fs = new ArrayList<>(); 1289 fs.add(() -> check(! m.containsKey(null))); 1290 fs.add(() -> equal(m.remove(null), null)); 1291 fs.add(() -> equal(m.get(null), null)); 1292 if (cm != null) 1293 fs.add(() -> check(! cm.remove(null,null))); 1294 throwsConsistently(NullPointerException.class, fs); 1295 1296 fs.clear(); 1297 final Map<T,Integer> sm = singletonMap(null,1); 1298 fs.add(() -> { equal(m.put(null,1), null); m.clear();}); 1299 fs.add(() -> { m.putAll(sm); m.clear();}); 1300 if (cm != null) { 1301 fs.add(() -> check(! cm.remove(null,null))); 1302 fs.add(() -> equal(cm.putIfAbsent(null,1), 1)); 1303 fs.add(() -> equal(cm.replace(null,1), null)); 1304 fs.add(() -> equal(cm.replace(null,1, 1), 1)); 1305 } 1306 throwsConsistently(NullPointerException.class, fs); 1307 } 1308 1309 //---------------------------------------------------------------- 1310 // NavigableMap 1311 //---------------------------------------------------------------- 1312 private static void 1313 checkNavigableMapKeys(NavigableMap<Integer,Integer> m, 1314 Integer i, 1315 Integer lower, 1316 Integer floor, 1317 Integer ceiling, 1318 Integer higher) { 1319 equal(m.lowerKey(i), lower); 1320 equal(m.floorKey(i), floor); 1321 equal(m.ceilingKey(i), ceiling); 1322 equal(m.higherKey(i), higher); 1323 } 1324 1325 private static void 1326 checkNavigableSetKeys(NavigableSet<Integer> m, 1327 Integer i, 1328 Integer lower, 1329 Integer floor, 1330 Integer ceiling, 1331 Integer higher) { 1332 equal(m.lower(i), lower); 1333 equal(m.floor(i), floor); 1334 equal(m.ceiling(i), ceiling); 1335 equal(m.higher(i), higher); 1336 } 1337 1338 static final Random rnd = new Random(); 1339 static void equalNext(final Iterator<?> it, Object expected) { 1340 if (rnd.nextBoolean()) 1341 check(it.hasNext()); 1342 equal(it.next(), expected); 1343 } 1344 1345 static void equalMaps(Map m1, Map m2) { 1346 equal(m1, m2); 1347 equal(m2, m1); 1348 equal(m1.size(), m2.size()); 1349 equal(m1.isEmpty(), m2.isEmpty()); 1350 equal(m1.toString(), m2.toString()); 1351 check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray())); 1352 } 1353 1354 @SuppressWarnings({"unchecked", "rawtypes"}) 1355 static void testNavigableMapRemovers(NavigableMap m) 1356 { 1357 final Map emptyMap = new HashMap(); 1358 1359 final Map singletonMap = new HashMap(); 1360 singletonMap.put(1, 2); 1361 1362 abstract class NavigableMapView { 1363 abstract NavigableMap view(NavigableMap m); 1364 } 1365 1366 NavigableMapView[] views = { 1367 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1368 return m; }}, 1369 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1370 return m.headMap(99, true); }}, 1371 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1372 return m.tailMap(-99, false); }}, 1373 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1374 return m.subMap(-99, true, 99, false); }}, 1375 }; 1376 1377 abstract class Remover { 1378 abstract void remove(NavigableMap m, Object k, Object v); 1379 } 1380 1381 Remover[] removers = { 1382 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1383 equal(m.remove(k), v); }}, 1384 1385 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1386 equal(m.descendingMap().remove(k), v); }}, 1387 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1388 equal(m.descendingMap().headMap(-86, false).remove(k), v); }}, 1389 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1390 equal(m.descendingMap().tailMap(86, true).remove(k), v); }}, 1391 1392 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1393 equal(m.headMap(86, true).remove(k), v); }}, 1394 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1395 equal(m.tailMap(-86, true).remove(k), v); }}, 1396 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1397 equal(m.subMap(-86, false, 86, true).remove(k), v); }}, 1398 1399 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1400 check(m.keySet().remove(k)); }}, 1401 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1402 check(m.navigableKeySet().remove(k)); }}, 1403 1404 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1405 check(m.navigableKeySet().headSet(86, true).remove(k)); }}, 1406 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1407 check(m.navigableKeySet().tailSet(-86, false).remove(k)); }}, 1408 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1409 check(m.navigableKeySet().subSet(-86, true, 86, false) 1410 .remove(k)); }}, 1411 1412 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1413 check(m.descendingKeySet().headSet(-86, false).remove(k)); }}, 1414 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1415 check(m.descendingKeySet().tailSet(86, true).remove(k)); }}, 1416 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1417 check(m.descendingKeySet().subSet(86, true, -86, false) 1418 .remove(k)); }}, 1419 }; 1420 1421 for (NavigableMapView view : views) { 1422 for (Remover remover : removers) { 1423 try { 1424 m.clear(); 1425 equalMaps(m, emptyMap); 1426 equal(m.put(1, 2), null); 1427 equalMaps(m, singletonMap); 1428 NavigableMap v = view.view(m); 1429 remover.remove(v, 1, 2); 1430 equalMaps(m, emptyMap); 1431 } catch (Throwable t) { unexpected(t); } 1432 } 1433 } 1434 } 1435 1436 private static void testNavigableMap(NavigableMap<Integer,Integer> m) 1437 { 1438 clear(m); 1439 checkNavigableMapKeys(m, 1, null, null, null, null); 1440 1441 equal(m.put(1, 2), null); 1442 equal(m.put(3, 4), null); 1443 equal(m.put(5, 9), null); 1444 1445 equal(m.put(1, 2), 2); 1446 equal(m.put(3, 4), 4); 1447 equal(m.put(5, 6), 9); 1448 1449 checkNavigableMapKeys(m, 0, null, null, 1, 1); 1450 checkNavigableMapKeys(m, 1, null, 1, 1, 3); 1451 checkNavigableMapKeys(m, 2, 1, 1, 3, 3); 1452 checkNavigableMapKeys(m, 3, 1, 3, 3, 5); 1453 checkNavigableMapKeys(m, 5, 3, 5, 5, null); 1454 checkNavigableMapKeys(m, 6, 5, 5, null, null); 1455 1456 for (final Iterator<Integer> it : 1457 (Iterator<Integer>[]) 1458 new Iterator<?>[] { 1459 m.descendingKeySet().iterator(), 1460 m.navigableKeySet().descendingIterator()}) { 1461 equalNext(it, 5); 1462 equalNext(it, 3); 1463 equalNext(it, 1); 1464 check(! it.hasNext()); 1465 THROWS(NoSuchElementException.class, () -> it.next()); 1466 } 1467 1468 { 1469 final Iterator<Map.Entry<Integer,Integer>> it 1470 = m.descendingMap().entrySet().iterator(); 1471 check(it.hasNext()); equal(it.next().getKey(), 5); 1472 check(it.hasNext()); equal(it.next().getKey(), 3); 1473 check(it.hasNext()); equal(it.next().getKey(), 1); 1474 check(! it.hasNext()); 1475 THROWS(NoSuchElementException.class, () -> it.next()); 1476 } 1477 1478 prepMapForDescItrTests(m); 1479 checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator()); 1480 prepMapForDescItrTests(m); 1481 checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator()); 1482 prepMapForDescItrTests(m); 1483 checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator()); 1484 1485 prepMapForDescItrTests(m); 1486 checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator()); 1487 prepMapForDescItrTests(m); 1488 checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator()); 1489 prepMapForDescItrTests(m); 1490 checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator()); 1491 1492 prepMapForDescItrTests(m); 1493 checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator()); 1494 prepMapForDescItrTests(m); 1495 checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator()); 1496 prepMapForDescItrTests(m); 1497 checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator()); 1498 1499 prepMapForDescItrTests(m); 1500 checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator()); 1501 prepMapForDescItrTests(m); 1502 checkDescItrRmMid(m.values(), m.descendingMap().values().iterator()); 1503 prepMapForDescItrTests(m); 1504 checkDescItrRmLast(m.values(), m.descendingMap().values().iterator()); 1505 1506 prepMapForDescItrTests(m); 1507 checkDescItrRmFirst((Collection)m.entrySet(), 1508 m.descendingMap().entrySet().iterator()); 1509 prepMapForDescItrTests(m); 1510 checkDescItrRmMid((Collection)m.entrySet(), 1511 m.descendingMap().entrySet().iterator()); 1512 prepMapForDescItrTests(m); 1513 checkDescItrRmLast((Collection)m.entrySet(), 1514 m.descendingMap().entrySet().iterator()); 1515 } 1516 1517 private static void testNavigableSet(NavigableSet<Integer> s) { 1518 clear(s); 1519 checkNavigableSetKeys(s, 1, null, null, null, null); 1520 1521 check(s.add(1)); 1522 check(s.add(3)); 1523 check(s.add(5)); 1524 1525 check(! s.add(1)); 1526 check(! s.add(3)); 1527 check(! s.add(5)); 1528 1529 checkNavigableSetKeys(s, 0, null, null, 1, 1); 1530 checkNavigableSetKeys(s, 1, null, 1, 1, 3); 1531 checkNavigableSetKeys(s, 2, 1, 1, 3, 3); 1532 checkNavigableSetKeys(s, 3, 1, 3, 3, 5); 1533 checkNavigableSetKeys(s, 5, 3, 5, 5, null); 1534 checkNavigableSetKeys(s, 6, 5, 5, null, null); 1535 1536 for (final Iterator<Integer> it : 1537 (Iterator<Integer>[]) 1538 new Iterator<?>[] { 1539 s.descendingIterator(), 1540 s.descendingSet().iterator()}) { 1541 equalNext(it, 5); 1542 equalNext(it, 3); 1543 equalNext(it, 1); 1544 check(! it.hasNext()); 1545 THROWS(NoSuchElementException.class, () -> it.next()); 1546 } 1547 1548 prepSetForDescItrTests(s); 1549 checkDescItrRmFirst(s, s.descendingIterator()); 1550 prepSetForDescItrTests(s); 1551 checkDescItrRmMid(s, s.descendingIterator()); 1552 prepSetForDescItrTests(s); 1553 checkDescItrRmLast(s, s.descendingIterator()); 1554 1555 prepSetForDescItrTests(s); 1556 checkDescItrRmFirst(s, s.descendingSet().iterator()); 1557 prepSetForDescItrTests(s); 1558 checkDescItrRmMid(s, s.descendingSet().iterator()); 1559 prepSetForDescItrTests(s); 1560 checkDescItrRmLast(s, s.descendingSet().iterator()); 1561 } 1562 1563 private static void prepSetForDescItrTests(Set s) { 1564 clear(s); 1565 check(s.add(1)); 1566 check(s.add(3)); 1567 check(s.add(5)); 1568 } 1569 1570 private static void prepMapForDescItrTests(Map m) { 1571 clear(m); 1572 equal(m.put(1, 2), null); 1573 equal(m.put(3, 4), null); 1574 equal(m.put(5, 9), null); 1575 } 1576 1577 //-------------------------------------------------------------------- 1578 // Check behavior of descending iterator when first element is removed 1579 //-------------------------------------------------------------------- 1580 private static <T> void checkDescItrRmFirst(Collection<T> ascColl, 1581 Iterator<T> descItr) { 1582 T[] expected = (T[]) ascColl.toArray(); 1583 int idx = expected.length -1; 1584 1585 equalNext(descItr, expected[idx--]); 1586 descItr.remove(); 1587 while (idx >= 0 && descItr.hasNext()) { 1588 equalNext(descItr, expected[idx--]); 1589 } 1590 equal(descItr.hasNext(), false); 1591 equal(idx, -1); 1592 } 1593 1594 //----------------------------------------------------------------------- 1595 // Check behavior of descending iterator when a middle element is removed 1596 //----------------------------------------------------------------------- 1597 private static <T> void checkDescItrRmMid(Collection<T> ascColl, 1598 Iterator<T> descItr) { 1599 T[] expected = (T[]) ascColl.toArray(); 1600 int idx = expected.length -1; 1601 1602 while (idx >= expected.length / 2) { 1603 equalNext(descItr, expected[idx--]); 1604 } 1605 descItr.remove(); 1606 while (idx >= 0 && descItr.hasNext()) { 1607 equalNext(descItr, expected[idx--]); 1608 } 1609 equal(descItr.hasNext(), false); 1610 equal(idx, -1); 1611 } 1612 1613 //----------------------------------------------------------------------- 1614 // Check behavior of descending iterator when the last element is removed 1615 //----------------------------------------------------------------------- 1616 private static <T> void checkDescItrRmLast(Collection<T> ascColl, 1617 Iterator<T> descItr) { 1618 T[] expected = (T[]) ascColl.toArray(); 1619 int idx = expected.length -1; 1620 1621 while (idx >= 0 && descItr.hasNext()) { 1622 equalNext(descItr, expected[idx--]); 1623 } 1624 equal(idx, -1); 1625 equal(descItr.hasNext(), false); 1626 descItr.remove(); 1627 equal(ascColl.contains(expected[0]), false); 1628 } 1629 1630 //--------------------- Infrastructure --------------------------- 1631 static volatile int passed = 0, failed = 0; 1632 static void pass() { passed++; } 1633 static void fail() { failed++; Thread.dumpStack(); } 1634 static void fail(String msg) { System.out.println(msg); fail(); } 1635 static void unexpected(Throwable t) { failed++; t.printStackTrace(); } 1636 static void check(boolean cond) { if (cond) pass(); else fail(); } 1637 static void equal(Object x, Object y) { 1638 if (x == null ? y == null : x.equals(y)) pass(); 1639 else {System.out.println(x + " not equal to " + y); fail();}} 1640 static void equal2(Object x, Object y) {equal(x, y); equal(y, x);} 1641 public static void main(String[] args) throws Throwable { 1642 try { realMain(args); } catch (Throwable t) { unexpected(t); } 1643 1644 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 1645 if (failed > 0) throw new Exception("Some tests failed"); 1646 } 1647 interface Fun {void f() throws Throwable;} 1648 private static void THROWS(Class<? extends Throwable> k, Fun... fs) { 1649 for (Fun f : fs) 1650 try { f.f(); fail("Expected " + k.getName() + " not thrown"); } 1651 catch (Throwable t) { 1652 if (k.isAssignableFrom(t.getClass())) pass(); 1653 else unexpected(t);}} 1654 static byte[] serializedForm(Object obj) { 1655 try { 1656 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1657 new ObjectOutputStream(baos).writeObject(obj); 1658 return baos.toByteArray(); 1659 } catch (IOException e) { throw new Error(e); }} 1660 static Object readObject(byte[] bytes) 1661 throws IOException, ClassNotFoundException { 1662 InputStream is = new ByteArrayInputStream(bytes); 1663 return new ObjectInputStream(is).readObject();} 1664 @SuppressWarnings("unchecked") 1665 static <T> T serialClone(T obj) { 1666 try { return (T) readObject(serializedForm(obj)); } 1667 catch (Exception e) { throw new Error(e); }} 1668 private static class NewAbstractCollection<E> extends AbstractCollection<E> { 1669 ArrayList<E> list = new ArrayList<>(); 1670 public boolean remove(Object obj) { 1671 return list.remove(obj); 1672 } 1673 public boolean add(E e) { 1674 return list.add(e); 1675 } 1676 public Iterator<E> iterator() { 1677 return list.iterator(); 1678 } 1679 public int size() { 1680 return list.size(); 1681 } 1682 } 1683 private static class NewAbstractSet<E> extends AbstractSet<E> { 1684 HashSet<E> set = new HashSet<>(); 1685 public boolean remove(Object obj) { 1686 return set.remove(obj); 1687 } 1688 public boolean add(E e) { 1689 return set.add(e); 1690 } 1691 public Iterator<E> iterator() { 1692 return set.iterator(); 1693 } 1694 public int size() { 1695 return set.size(); 1696 } 1697 } 1698 1699 }