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 8193128 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 testEmptyList(List.of().subList(0,0)); 216 testListMutatorsAlwaysThrow(List.of()); 217 testListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0)); 218 testEmptyListMutatorsAlwaysThrow(List.of()); 219 testEmptyListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0)); 220 for (List<Integer> list : Arrays.asList( 221 List.<Integer>of(), 222 List.of(1), 223 List.of(1, 2), 224 List.of(1, 2, 3), 225 List.of(1, 2, 3, 4), 226 List.of(1, 2, 3, 4, 5), 227 List.of(1, 2, 3, 4, 5, 6), 228 List.of(1, 2, 3, 4, 5, 6, 7), 229 List.of(1, 2, 3, 4, 5, 6, 7, 8), 230 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9), 231 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 232 List.of(integerArray))) { 233 testCollection(list); 234 testImmutableList(list); 235 testListMutatorsAlwaysThrow(list); 236 if (list.size() >= 1) { 237 // test subLists 238 List<Integer> headList = list.subList(0, list.size() - 1); 239 List<Integer> tailList = list.subList(1, list.size()); 240 testCollection(headList); 241 testCollection(tailList); 242 testImmutableList(headList); 243 testImmutableList(tailList); 244 testListMutatorsAlwaysThrow(headList); 245 testListMutatorsAlwaysThrow(tailList); 246 } 247 } 248 249 List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3)); 250 testCollection(listCopy); 251 testImmutableList(listCopy); 252 testListMutatorsAlwaysThrow(listCopy); 253 254 List<Integer> listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList()); 255 equal(listCollected, List.of(1, 2, 3)); 256 testCollection(listCollected); 257 testImmutableList(listCollected); 258 testListMutatorsAlwaysThrow(listCollected); 259 260 // List indexOf / lastIndexOf 261 262 // 0 element 263 System.out.println("testListIndexOf size 0"); 264 testListIndexOf(-1, -1); 265 266 System.out.println("testListIndexOf size 1"); 267 testListIndexOf(-1, -1, 0); 268 testListIndexOf(0, 0, 1); 269 270 System.out.println("testListIndexOf size 2"); 271 testListIndexOf(-1, -1, 0, 0); 272 testListIndexOf(0, 0, 1, 0); 273 testListIndexOf(0, 1, 1, 1); 274 testListIndexOf(1, 1, 0, 1); 275 276 277 System.out.println("testListIndexOf size 3"); 278 testListIndexOf(-1, -1, 0, 0, 0); 279 testListIndexOf(0, 0, 1, 0, 0); 280 testListIndexOf(0, 1, 1, 1, 0); 281 testListIndexOf(1, 2, 0, 1, 1); 282 testListIndexOf(2, 2, 0, 0, 1); 283 284 System.out.println("testListIndexOf size N"); 285 testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0); 286 testListIndexOf(2, 6, 0, 0, 1, 0, 1, 0, 1); 287 testListIndexOf(4, 4, 0, 0, 0, 0, 1, 0, 0); 288 testListIndexOf(0, 6, 1, 1, 1, 1, 1, 1, 1); 289 testListIndexOf(0, 7, 1, 1, 1, 1, 1, 1, 1, 1); 290 testListIndexOf(0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1); 291 testListIndexOf(0, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 292 testListIndexOf(0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 293 testListIndexOf(0, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 294 testListIndexOf(0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 295 testListIndexOf(12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); 296 testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 297 298 // Immutable Set 299 testEmptySet(Set.of()); 300 testCollMutatorsAlwaysThrow(Set.of()); 301 testEmptyCollMutatorsAlwaysThrow(Set.of()); 302 for (Set<Integer> set : Arrays.asList( 303 Set.<Integer>of(), 304 Set.of(1), 305 Set.of(1, 2), 306 Set.of(1, 2, 3), 307 Set.of(1, 2, 3, 4), 308 Set.of(1, 2, 3, 4, 5), 309 Set.of(1, 2, 3, 4, 5, 6), 310 Set.of(1, 2, 3, 4, 5, 6, 7), 311 Set.of(1, 2, 3, 4, 5, 6, 7, 8), 312 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9), 313 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 314 Set.of(integerArray))) { 315 testCollection(set); 316 testImmutableSet(set); 317 testCollMutatorsAlwaysThrow(set); 318 } 319 320 Set<Integer> setCopy = Set.copyOf(Arrays.asList(1, 2, 3)); 321 testCollection(setCopy); 322 testImmutableSet(setCopy); 323 testCollMutatorsAlwaysThrow(setCopy); 324 325 Set<Integer> setCollected = Stream.of(1, 1, 2, 3, 2, 3) 326 .collect(Collectors.toUnmodifiableSet()); 327 equal(setCollected, Set.of(1, 2, 3)); 328 testCollection(setCollected); 329 testImmutableSet(setCollected); 330 testCollMutatorsAlwaysThrow(setCollected); 331 332 // Immutable Map 333 334 @SuppressWarnings("unchecked") 335 Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20]; 336 for (int i = 0; i < ea.length; i++) { 337 ea[i] = Map.entry(i+1, i+101); 338 } 339 340 testEmptyMap(Map.of()); 341 testMapMutatorsAlwaysThrow(Map.of()); 342 testEmptyMapMutatorsAlwaysThrow(Map.of()); 343 for (Map<Integer,Integer> map : Arrays.asList( 344 Map.<Integer,Integer>of(), 345 Map.of(1, 101), 346 Map.of(1, 101, 2, 202), 347 Map.of(1, 101, 2, 202, 3, 303), 348 Map.of(1, 101, 2, 202, 3, 303, 4, 404), 349 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505), 350 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606), 351 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707), 352 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808), 353 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909), 354 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010), 355 Map.ofEntries(ea))) { 356 testMap(map); 357 testImmutableMap(map); 358 testMapMutatorsAlwaysThrow(map); 359 } 360 361 Map<Integer,Integer> mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303))); 362 testMap(mapCopy); 363 testImmutableMap(mapCopy); 364 testMapMutatorsAlwaysThrow(mapCopy); 365 366 Map<Integer,Integer> mapCollected1 = 367 Stream.of(1, 2, 3) 368 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); 369 equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303)); 370 testMap(mapCollected1); 371 testImmutableMap(mapCollected1); 372 testMapMutatorsAlwaysThrow(mapCollected1); 373 374 try { 375 Stream.of(1, 1, 2, 3, 2, 3) 376 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); 377 fail("duplicates should have thrown an exception"); 378 } catch (IllegalStateException ise) { 379 pass(); 380 } 381 382 Map<Integer,Integer> mapCollected2 = 383 Stream.of(1, 1, 2, 3, 2, 3) 384 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum)); 385 equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606)); 386 testMap(mapCollected2); 387 testImmutableMap(mapCollected2); 388 testMapMutatorsAlwaysThrow(mapCollected2); 389 } 390 391 private static void checkContainsSelf(Collection<Integer> c) { 392 check(c.containsAll(c)); 393 check(c.containsAll(Arrays.asList(c.toArray()))); 394 check(c.containsAll(Arrays.asList(c.toArray(new Integer[0])))); 395 } 396 397 private static void checkContainsEmpty(Collection<Integer> c) { 398 check(c.containsAll(new ArrayList<Integer>())); 399 } 400 401 private static void checkUnique(Set<Integer> s) { 402 for (Integer i : s) { 403 int count = 0; 404 for (Integer j : s) { 405 if (Objects.equals(i,j)) 406 ++count; 407 } 408 check(count == 1); 409 } 410 } 411 412 private static <T> void testEmptyCollection(Collection<T> c) { 413 check(c.isEmpty()); 414 equal(c.size(), 0); 415 equal(c.toString(),"[]"); 416 equal(c.toArray().length, 0); 417 equal(c.toArray(new Object[0]).length, 0); 418 check(c.toArray(new Object[]{42})[0] == null); 419 420 Object[] a = new Object[1]; a[0] = Boolean.TRUE; 421 equal(c.toArray(a), a); 422 equal(a[0], null); 423 testEmptyIterator(c.iterator()); 424 } 425 426 static <T> void testEmptyIterator(final Iterator<T> it) { 427 if (rnd.nextBoolean()) 428 check(! it.hasNext()); 429 430 THROWS(NoSuchElementException.class, () -> it.next()); 431 432 try { it.remove(); } 433 catch (IllegalStateException ignored) { pass(); } 434 catch (UnsupportedOperationException ignored) { pass(); } 435 catch (Throwable t) { unexpected(t); } 436 437 if (rnd.nextBoolean()) 438 check(! it.hasNext()); 439 } 440 441 private static void testEmptyList(List<?> c) { 442 testEmptyCollection(c); 443 equal(c.hashCode(), 1); 444 equal2(c, Collections.<Integer>emptyList()); 445 } 446 447 private static <T> void testEmptySet(Set<T> c) { 448 testEmptyCollection(c); 449 equal(c.hashCode(), 0); 450 equal2(c, Collections.<Integer>emptySet()); 451 if (c instanceof NavigableSet<?>) 452 testEmptyIterator(((NavigableSet<T>)c).descendingIterator()); 453 } 454 455 private static void testImmutableCollection(final Collection<Integer> c) { 456 THROWS(UnsupportedOperationException.class, 457 () -> c.add(99), 458 () -> c.addAll(singleton(99))); 459 if (! c.isEmpty()) { 460 final Integer first = c.iterator().next(); 461 THROWS(UnsupportedOperationException.class, 462 () -> c.clear(), 463 () -> c.remove(first), 464 () -> c.removeAll(singleton(first)), 465 () -> c.retainAll(emptyList())); 466 } 467 } 468 469 private static void testImmutableSet(final Set<Integer> c) { 470 testImmutableCollection(c); 471 } 472 473 private static void testImmutableList(final List<Integer> c) { 474 testList(c); 475 testImmutableCollection(c); 476 THROWS(UnsupportedOperationException.class, 477 () -> c.set(0,42), 478 () -> c.add(0,42), 479 () -> c.addAll(0,singleton(86))); 480 if (! c.isEmpty()) 481 THROWS(UnsupportedOperationException.class, 482 () -> { Iterator<Integer> it = c.iterator(); 483 it.next(); 484 it.remove(); }, 485 () -> { ListIterator<Integer> it = c.listIterator(); 486 it.next(); 487 it.remove(); }); 488 } 489 490 /** 491 * Test that calling a mutator always throws UOE, even if the mutator 492 * wouldn't actually do anything, given its arguments. 493 * 494 * @param c the collection instance to test 495 */ 496 private static void testCollMutatorsAlwaysThrow(Collection<Integer> c) { 497 THROWS(UnsupportedOperationException.class, 498 () -> c.addAll(Collections.emptyList()), 499 () -> c.remove(ABSENT_VALUE), 500 () -> c.removeAll(Collections.emptyList()), 501 () -> c.removeIf(x -> false), 502 () -> c.retainAll(c)); 503 } 504 505 /** 506 * Test that calling a mutator always throws UOE, even if the mutator 507 * wouldn't actually do anything on an empty collection. 508 * 509 * @param c the collection instance to test, must be empty 510 */ 511 private static void testEmptyCollMutatorsAlwaysThrow(Collection<Integer> c) { 512 if (! c.isEmpty()) { 513 fail("collection is not empty"); 514 } 515 THROWS(UnsupportedOperationException.class, 516 () -> c.clear()); 517 } 518 519 /** 520 * As above, for a list. 521 * 522 * @param c the list instance to test 523 */ 524 private static void testListMutatorsAlwaysThrow(List<Integer> c) { 525 testCollMutatorsAlwaysThrow(c); 526 THROWS(UnsupportedOperationException.class, 527 () -> c.addAll(0, Collections.emptyList())); 528 } 529 530 /** 531 * As above, for an empty list. 532 * 533 * @param c the list instance to test, must be empty 534 */ 535 private static void testEmptyListMutatorsAlwaysThrow(List<Integer> c) { 536 if (! c.isEmpty()) { 537 fail("list is not empty"); 538 } 539 testEmptyCollMutatorsAlwaysThrow(c); 540 THROWS(UnsupportedOperationException.class, 541 () -> c.replaceAll(x -> x), 542 () -> c.sort(null)); 543 } 544 545 /** 546 * As above, for a map. 547 * 548 * @param m the map instance to test 549 */ 550 private static void testMapMutatorsAlwaysThrow(Map<Integer,Integer> m) { 551 THROWS(UnsupportedOperationException.class, 552 () -> m.compute(ABSENT_VALUE, (k, v) -> null), 553 () -> m.computeIfAbsent(ABSENT_VALUE, k -> null), 554 () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null), 555 () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null), 556 () -> m.putAll(Collections.emptyMap()), 557 () -> m.remove(ABSENT_VALUE), 558 () -> m.remove(ABSENT_VALUE, 0), 559 () -> m.replace(ABSENT_VALUE, 0), 560 () -> m.replace(ABSENT_VALUE, 0, 1)); 561 } 562 563 /** 564 * As above, for an empty map. 565 * 566 * @param map the map instance to test, must be empty 567 */ 568 private static void testEmptyMapMutatorsAlwaysThrow(Map<Integer,Integer> m) { 569 if (! m.isEmpty()) { 570 fail("map is not empty"); 571 } 572 THROWS(UnsupportedOperationException.class, 573 () -> m.clear(), 574 () -> m.replaceAll((k, v) -> v)); 575 } 576 577 private static void clear(Collection<Integer> c) { 578 try { c.clear(); } 579 catch (Throwable t) { unexpected(t); } 580 testEmptyCollection(c); 581 } 582 583 private static <K,V> void testEmptyMap(final Map<K,V> m) { 584 check(m.isEmpty()); 585 equal(m.size(), 0); 586 equal(m.toString(),"{}"); 587 testEmptySet(m.keySet()); 588 testEmptySet(m.entrySet()); 589 testEmptyCollection(m.values()); 590 591 try { check(! m.containsValue(null)); } 592 catch (NullPointerException ignored) { /* OK */ } 593 try { check(! m.containsKey(null)); } 594 catch (NullPointerException ignored) { /* OK */ } 595 check(! m.containsValue(1)); 596 check(! m.containsKey(1)); 597 } 598 599 private static void testImmutableMap(final Map<Integer,Integer> m) { 600 THROWS(UnsupportedOperationException.class, 601 () -> m.put(1,1), 602 () -> m.putAll(singletonMap(1,1))); 603 if (! m.isEmpty()) { 604 final Integer first = m.keySet().iterator().next(); 605 THROWS(UnsupportedOperationException.class, 606 () -> m.remove(first), 607 () -> m.clear()); 608 final Map.Entry<Integer,Integer> me 609 = m.entrySet().iterator().next(); 610 Integer key = me.getKey(); 611 Integer val = me.getValue(); 612 THROWS(UnsupportedOperationException.class, 613 () -> me.setValue(3)); 614 equal(key, me.getKey()); 615 equal(val, me.getValue()); 616 } 617 testImmutableSet(m.keySet()); 618 testImmutableCollection(m.values()); 619 //testImmutableSet(m.entrySet()); 620 } 621 622 private static void clear(Map<?,?> m) { 623 try { m.clear(); } 624 catch (Throwable t) { unexpected(t); } 625 testEmptyMap(m); 626 } 627 628 private static void oneElement(Collection<Integer> c) { 629 clear(c); 630 try { 631 check(c.add(-42)); 632 equal(c.toString(), "[-42]"); 633 if (c instanceof Set) check(! c.add(-42)); 634 } catch (Throwable t) { unexpected(t); } 635 check(! c.isEmpty()); check(c.size() == 1); 636 } 637 638 private static boolean supportsAdd(Collection<Integer> c) { 639 try { check(c.add(ABSENT_VALUE)); } 640 catch (UnsupportedOperationException t) { return false; } 641 catch (Throwable t) { unexpected(t); } 642 643 try { 644 check(c.contains(ABSENT_VALUE)); 645 check(c.remove(ABSENT_VALUE)); 646 } catch (Throwable t) { unexpected(t); } 647 return true; 648 } 649 650 private static boolean supportsRemove(Collection<Integer> c) { 651 try { check(! c.remove(ABSENT_VALUE)); } 652 catch (UnsupportedOperationException t) { return false; } 653 catch (Throwable t) { unexpected(t); } 654 return true; 655 } 656 657 // 6260652: (coll) Arrays.asList(x).toArray().getClass() 658 // should be Object[].class 659 // Fixed in jdk9, but not jdk8 ... 660 static final boolean needToWorkAround6260652 = 661 Arrays.asList("").toArray().getClass() != Object[].class; 662 663 private static void checkFunctionalInvariants(Collection<Integer> c) { 664 try { 665 checkContainsSelf(c); 666 checkContainsEmpty(c); 667 check(c.size() != 0 ^ c.isEmpty()); 668 check(! c.contains(ABSENT_VALUE)); 669 670 { 671 int size = 0; 672 for (Integer i : c) size++; 673 check(c.size() == size); 674 } 675 676 if (c instanceof Set) { 677 checkUnique((Set<Integer>)c); 678 } 679 680 check(c.toArray().length == c.size()); 681 check(c.toArray().getClass() == Object[].class 682 || 683 (needToWorkAround6260652 && 684 c.getClass().getName().equals("java.util.Arrays$ArrayList"))); 685 for (int size : new int[]{0,1,c.size(), c.size()+1}) { 686 Integer[] a = c.toArray(new Integer[size]); 687 check((size > c.size()) || a.length == c.size()); 688 int i = 0; for (Integer j : c) check(a[i++] == j); 689 check((size <= c.size()) || (a[c.size()] == null)); 690 check(a.getClass() == Integer[].class); 691 } 692 693 check(c.equals(c)); 694 if (c instanceof Serializable) { 695 //System.out.printf("Serializing %s%n", c.getClass().getName()); 696 try { 697 Object clone = serialClone(c); 698 equal(c instanceof Serializable, 699 clone instanceof Serializable); 700 equal(c instanceof RandomAccess, 701 clone instanceof RandomAccess); 702 if ((c instanceof List) || (c instanceof Set)) 703 equal(c, clone); 704 else 705 equal(new HashSet<Integer>(c), 706 new HashSet<Integer>(serialClone(c))); 707 } catch (Error xxx) { 708 if (! (xxx.getCause() instanceof NotSerializableException)) 709 throw xxx; 710 } 711 } 712 } 713 catch (Throwable t) { unexpected(t); } 714 } 715 716 //---------------------------------------------------------------- 717 // If add(null) succeeds, contains(null) & remove(null) should succeed 718 //---------------------------------------------------------------- 719 private static void testNullElement(Collection<Integer> c) { 720 721 try { 722 check(c.add(null)); 723 if (c.size() == 1) 724 equal(c.toString(), "[null]"); 725 try { 726 checkFunctionalInvariants(c); 727 check(c.contains(null)); 728 check(c.remove(null)); 729 } 730 catch (Throwable t) { unexpected(t); } 731 } 732 catch (NullPointerException e) { /* OK */ } 733 catch (Throwable t) { unexpected(t); } 734 } 735 736 //---------------------------------------------------------------- 737 // If add("x") succeeds, contains("x") & remove("x") should succeed 738 //---------------------------------------------------------------- 739 @SuppressWarnings("unchecked") 740 private static void testStringElement(Collection<Integer> c) { 741 Collection x = (Collection)c; // Make type-unsafe 742 try { 743 check(x.add("x")); 744 try { 745 check(x.contains("x")); 746 check(x.remove("x")); 747 } catch (Throwable t) { unexpected(t); } 748 } 749 catch (ClassCastException e) { /* OK */ } 750 catch (Throwable t) { unexpected(t); } 751 } 752 753 private static void testConcurrentCollection(Collection<Integer> c) { 754 try { 755 c.add(1); 756 Iterator<Integer> it = c.iterator(); 757 check(it.hasNext()); 758 clear(c); 759 check(it.next() instanceof Integer); // No CME 760 check(c.isEmpty()); 761 } 762 catch (Throwable t) { unexpected(t); } 763 } 764 765 private static void testQueue(Queue<Integer> q) { 766 q.clear(); 767 for (int i = 0; i < 5; i++) { 768 testQueueAddRemove(q, null); 769 testQueueAddRemove(q, 537); 770 q.add(i); 771 } 772 equal(q.size(), 5); 773 checkFunctionalInvariants(q); 774 q.poll(); 775 equal(q.size(), 4); 776 checkFunctionalInvariants(q); 777 if ((q instanceof LinkedBlockingQueue) || 778 (q instanceof LinkedBlockingDeque) || 779 (q instanceof ConcurrentLinkedDeque) || 780 (q instanceof ConcurrentLinkedQueue)) { 781 testQueueIteratorRemove(q); 782 } 783 } 784 785 private static void testQueueAddRemove(final Queue<Integer> q, 786 final Integer e) { 787 final List<Integer> originalContents = new ArrayList<>(q); 788 final boolean isEmpty = q.isEmpty(); 789 final boolean isList = (q instanceof List); 790 final List asList = isList ? (List) q : null; 791 check(!q.contains(e)); 792 try { 793 q.add(e); 794 } catch (NullPointerException npe) { 795 check(e == null); 796 return; // Null elements not supported 797 } 798 check(q.contains(e)); 799 check(q.remove(e)); 800 check(!q.contains(e)); 801 equal(new ArrayList<Integer>(q), originalContents); 802 803 if (q instanceof Deque<?>) { 804 final Deque<Integer> deq = (Deque<Integer>) q; 805 final List<Integer> singleton = Collections.singletonList(e); 806 807 // insert, query, remove element at head 808 if (isEmpty) { 809 THROWS(NoSuchElementException.class, 810 () -> deq.getFirst(), 811 () -> deq.element(), 812 () -> deq.iterator().next()); 813 check(deq.peekFirst() == null); 814 check(deq.peek() == null); 815 } else { 816 check(deq.getFirst() != e); 817 check(deq.element() != e); 818 check(deq.iterator().next() != e); 819 check(deq.peekFirst() != e); 820 check(deq.peek() != e); 821 } 822 check(!deq.contains(e)); 823 check(!deq.removeFirstOccurrence(e)); 824 check(!deq.removeLastOccurrence(e)); 825 if (isList) { 826 check(asList.indexOf(e) == -1); 827 check(asList.lastIndexOf(e) == -1); 828 } 829 switch (rnd.nextInt(isList ? 4 : 3)) { 830 case 0: deq.addFirst(e); break; 831 case 1: check(deq.offerFirst(e)); break; 832 case 2: deq.push(e); break; 833 case 3: asList.add(0, e); break; 834 default: throw new AssertionError(); 835 } 836 check(deq.peekFirst() == e); 837 check(deq.getFirst() == e); 838 check(deq.element() == e); 839 check(deq.peek() == e); 840 check(deq.iterator().next() == e); 841 check(deq.contains(e)); 842 if (isList) { 843 check(asList.get(0) == e); 844 check(asList.indexOf(e) == 0); 845 check(asList.lastIndexOf(e) == 0); 846 check(asList.subList(0, 1).equals(singleton)); 847 } 848 switch (rnd.nextInt(isList ? 11 : 9)) { 849 case 0: check(deq.pollFirst() == e); break; 850 case 1: check(deq.removeFirst() == e); break; 851 case 2: check(deq.remove() == e); break; 852 case 3: check(deq.pop() == e); break; 853 case 4: check(deq.removeFirstOccurrence(e)); break; 854 case 5: check(deq.removeLastOccurrence(e)); break; 855 case 6: check(deq.remove(e)); break; 856 case 7: check(deq.removeAll(singleton)); break; 857 case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break; 858 case 9: asList.remove(0); break; 859 case 10: asList.subList(0, 1).clear(); break; 860 default: throw new AssertionError(); 861 } 862 if (isEmpty) { 863 THROWS(NoSuchElementException.class, 864 () -> deq.getFirst(), 865 () -> deq.element(), 866 () -> deq.iterator().next()); 867 check(deq.peekFirst() == null); 868 check(deq.peek() == null); 869 } else { 870 check(deq.getFirst() != e); 871 check(deq.element() != e); 872 check(deq.iterator().next() != e); 873 check(deq.peekFirst() != e); 874 check(deq.peek() != e); 875 } 876 check(!deq.contains(e)); 877 check(!deq.removeFirstOccurrence(e)); 878 check(!deq.removeLastOccurrence(e)); 879 if (isList) { 880 check(isEmpty || asList.get(0) != e); 881 check(asList.indexOf(e) == -1); 882 check(asList.lastIndexOf(e) == -1); 883 } 884 equal(new ArrayList<Integer>(deq), originalContents); 885 886 // insert, query, remove element at tail 887 if (isEmpty) { 888 check(deq.peekLast() == null); 889 THROWS(NoSuchElementException.class, () -> deq.getLast()); 890 } else { 891 check(deq.peekLast() != e); 892 check(deq.getLast() != e); 893 } 894 switch (rnd.nextInt(isList ? 6 : 4)) { 895 case 0: deq.addLast(e); break; 896 case 1: check(deq.offerLast(e)); break; 897 case 2: check(deq.add(e)); break; 898 case 3: deq.addAll(singleton); break; 899 case 4: asList.addAll(deq.size(), singleton); break; 900 case 5: asList.add(deq.size(), e); break; 901 default: throw new AssertionError(); 902 } 903 check(deq.peekLast() == e); 904 check(deq.getLast() == e); 905 check(deq.contains(e)); 906 if (isList) { 907 ListIterator it = asList.listIterator(asList.size()); 908 check(it.previous() == e); 909 check(asList.get(asList.size() - 1) == e); 910 check(asList.indexOf(e) == asList.size() - 1); 911 check(asList.lastIndexOf(e) == asList.size() - 1); 912 int size = asList.size(); 913 check(asList.subList(size - 1, size).equals(singleton)); 914 } 915 switch (rnd.nextInt(isList ? 8 : 6)) { 916 case 0: check(deq.pollLast() == e); break; 917 case 1: check(deq.removeLast() == e); break; 918 case 2: check(deq.removeFirstOccurrence(e)); break; 919 case 3: check(deq.removeLastOccurrence(e)); break; 920 case 4: check(deq.remove(e)); break; 921 case 5: check(deq.removeAll(singleton)); break; 922 case 6: asList.remove(asList.size() - 1); break; 923 case 7: 924 ListIterator it = asList.listIterator(asList.size()); 925 it.previous(); 926 it.remove(); 927 break; 928 default: throw new AssertionError(); 929 } 930 if (isEmpty) { 931 check(deq.peekLast() == null); 932 THROWS(NoSuchElementException.class, () -> deq.getLast()); 933 } else { 934 check(deq.peekLast() != e); 935 check(deq.getLast() != e); 936 } 937 check(!deq.contains(e)); 938 equal(new ArrayList<Integer>(deq), originalContents); 939 940 // Test operations on empty deque 941 switch (rnd.nextInt(isList ? 4 : 2)) { 942 case 0: deq.clear(); break; 943 case 1: 944 Iterator it = deq.iterator(); 945 while (it.hasNext()) { 946 it.next(); 947 it.remove(); 948 } 949 break; 950 case 2: asList.subList(0, asList.size()).clear(); break; 951 case 3: 952 ListIterator lit = asList.listIterator(asList.size()); 953 while (lit.hasPrevious()) { 954 lit.previous(); 955 lit.remove(); 956 } 957 break; 958 default: throw new AssertionError(); 959 } 960 testEmptyCollection(deq); 961 check(!deq.iterator().hasNext()); 962 if (isList) { 963 check(!asList.listIterator().hasPrevious()); 964 THROWS(NoSuchElementException.class, 965 () -> asList.listIterator().previous()); 966 } 967 THROWS(NoSuchElementException.class, 968 () -> deq.iterator().next(), 969 () -> deq.element(), 970 () -> deq.getFirst(), 971 () -> deq.getLast(), 972 () -> deq.pop(), 973 () -> deq.remove(), 974 () -> deq.removeFirst(), 975 () -> deq.removeLast()); 976 977 check(deq.poll() == null); 978 check(deq.pollFirst() == null); 979 check(deq.pollLast() == null); 980 check(deq.peek() == null); 981 check(deq.peekFirst() == null); 982 check(deq.peekLast() == null); 983 check(!deq.removeFirstOccurrence(e)); 984 check(!deq.removeLastOccurrence(e)); 985 986 check(deq.addAll(originalContents) == !isEmpty); 987 equal(new ArrayList<Integer>(deq), originalContents); 988 check(!deq.addAll(Collections.<Integer>emptyList())); 989 equal(new ArrayList<Integer>(deq), originalContents); 990 } 991 } 992 993 private static void testQueueIteratorRemove(Queue<Integer> q) { 994 System.err.printf("testQueueIteratorRemove %s%n", 995 q.getClass().getSimpleName()); 996 q.clear(); 997 for (int i = 0; i < 5; i++) 998 q.add(i); 999 Iterator<Integer> it = q.iterator(); 1000 check(it.hasNext()); 1001 for (int i = 3; i >= 0; i--) 1002 q.remove(i); 1003 equal(it.next(), 0); 1004 equal(it.next(), 4); 1005 1006 q.clear(); 1007 for (int i = 0; i < 5; i++) 1008 q.add(i); 1009 it = q.iterator(); 1010 equal(it.next(), 0); 1011 check(it.hasNext()); 1012 for (int i = 1; i < 4; i++) 1013 q.remove(i); 1014 equal(it.next(), 1); 1015 equal(it.next(), 4); 1016 } 1017 1018 // for any array of integer values, check that the result of lastIndexOf(1) 1019 // and indexOf(1) match assumptions for all types of List<Integer> we can 1020 // construct 1021 private static void testListIndexOf(final int index, 1022 final int lastIndex, 1023 final Integer ... values) { 1024 if (values.length == 0) { 1025 checkListIndexOf(emptyList(), index, lastIndex); 1026 } else if (values.length == 1) { 1027 checkListIndexOf(singletonList(values[0]), index, lastIndex); 1028 checkListIndexOf(nCopies(25, values[0]), index, lastIndex == 0 ? 24 : -1); 1029 } 1030 List<Integer> l = List.of(values); 1031 checkListIndexOf(l, index, lastIndex); 1032 checkListIndexOf(Arrays.asList(values), index, lastIndex); 1033 checkListIndexOf(new ArrayList(l), index, lastIndex); 1034 checkListIndexOf(new LinkedList(l), index, lastIndex); 1035 checkListIndexOf(new Vector(l), index, lastIndex); 1036 checkListIndexOf(new CopyOnWriteArrayList(l), index, lastIndex); 1037 } 1038 1039 private static void checkListIndexOf(final List<Integer> list, 1040 final int index, 1041 final int lastIndex) { 1042 String msg = list.getClass().toString(); 1043 equal(list.indexOf(1), index, msg); 1044 equal(list.lastIndexOf(1), lastIndex, msg); 1045 equal(list.subList(0, list.size()).indexOf(1), index, msg); 1046 equal(list.subList(0, list.size()).lastIndexOf(1), lastIndex, msg); 1047 } 1048 1049 private static void testList(final List<Integer> l) { 1050 //---------------------------------------------------------------- 1051 // 4802633: (coll) AbstractList.addAll(-1,emptyCollection) 1052 // doesn't throw IndexOutOfBoundsException 1053 //---------------------------------------------------------------- 1054 try { 1055 l.addAll(-1, Collections.<Integer>emptyList()); 1056 fail("Expected IndexOutOfBoundsException not thrown"); 1057 } 1058 catch (UnsupportedOperationException ignored) {/* OK */} 1059 catch (IndexOutOfBoundsException ignored) {/* OK */} 1060 catch (Throwable t) { unexpected(t); } 1061 1062 // equal(l instanceof Serializable, 1063 // l.subList(0,0) instanceof Serializable); 1064 if (l.subList(0,0) instanceof Serializable) 1065 check(l instanceof Serializable); 1066 1067 equal(l instanceof RandomAccess, 1068 l.subList(0,0) instanceof RandomAccess); 1069 1070 l.iterator(); 1071 l.listIterator(); 1072 l.listIterator(0); 1073 l.listIterator(l.size()); 1074 THROWS(IndexOutOfBoundsException.class, 1075 () -> l.listIterator(-1), 1076 () -> l.listIterator(l.size() + 1)); 1077 1078 if (l instanceof AbstractList) { 1079 try { 1080 int size = l.size(); 1081 AbstractList<Integer> abList = (AbstractList<Integer>) l; 1082 Method m = AbstractList.class.getDeclaredMethod("removeRange", new Class[] { int.class, int.class }); 1083 m.setAccessible(true); 1084 m.invoke(abList, new Object[] { 0, 0 }); 1085 m.invoke(abList, new Object[] { size, size }); 1086 equal(size, l.size()); 1087 } 1088 catch (UnsupportedOperationException ignored) {/* OK */} 1089 catch (Throwable t) { unexpected(t); } 1090 } 1091 } 1092 1093 private static void testCollection(Collection<Integer> c) { 1094 try { testCollection1(c); } 1095 catch (Throwable t) { unexpected(t); } 1096 } 1097 1098 private static void testCollection1(Collection<Integer> c) { 1099 1100 System.out.println("\n==> " + c.getClass().getName()); 1101 1102 checkFunctionalInvariants(c); 1103 1104 if (! supportsAdd(c)) return; 1105 //System.out.println("add() supported"); 1106 1107 if (c instanceof NavigableSet) { 1108 System.out.println("NavigableSet tests..."); 1109 1110 NavigableSet<Integer> ns = (NavigableSet<Integer>)c; 1111 testNavigableSet(ns); 1112 testNavigableSet(ns.headSet(6, false)); 1113 testNavigableSet(ns.headSet(5, true)); 1114 testNavigableSet(ns.tailSet(0, false)); 1115 testNavigableSet(ns.tailSet(1, true)); 1116 testNavigableSet(ns.subSet(0, false, 5, true)); 1117 testNavigableSet(ns.subSet(1, true, 6, false)); 1118 } 1119 1120 if (c instanceof Queue) 1121 testQueue((Queue<Integer>)c); 1122 1123 if (c instanceof List) 1124 testList((List<Integer>)c); 1125 1126 check(supportsRemove(c)); 1127 1128 try { 1129 oneElement(c); 1130 checkFunctionalInvariants(c); 1131 } 1132 catch (Throwable t) { unexpected(t); } 1133 1134 clear(c); testNullElement(c); 1135 oneElement(c); testNullElement(c); 1136 1137 clear(c); testStringElement(c); 1138 oneElement(c); testStringElement(c); 1139 1140 if (c.getClass().getName().matches(".*concurrent.*")) 1141 testConcurrentCollection(c); 1142 1143 //---------------------------------------------------------------- 1144 // The "all" operations should throw NPE when passed null 1145 //---------------------------------------------------------------- 1146 { 1147 clear(c); 1148 try { 1149 c.removeAll(null); 1150 fail("Expected NullPointerException"); 1151 } 1152 catch (NullPointerException e) { pass(); } 1153 catch (Throwable t) { unexpected(t); } 1154 1155 oneElement(c); 1156 try { 1157 c.removeAll(null); 1158 fail("Expected NullPointerException"); 1159 } 1160 catch (NullPointerException e) { pass(); } 1161 catch (Throwable t) { unexpected(t); } 1162 1163 clear(c); 1164 try { 1165 c.retainAll(null); 1166 fail("Expected NullPointerException"); 1167 } 1168 catch (NullPointerException e) { pass(); } 1169 catch (Throwable t) { unexpected(t); } 1170 1171 oneElement(c); 1172 try { 1173 c.retainAll(null); 1174 fail("Expected NullPointerException"); 1175 } 1176 catch (NullPointerException e) { pass(); } 1177 catch (Throwable t) { unexpected(t); } 1178 1179 oneElement(c); 1180 try { 1181 c.addAll(null); 1182 fail("Expected NullPointerException"); 1183 } 1184 catch (NullPointerException e) { pass(); } 1185 catch (Throwable t) { unexpected(t); } 1186 1187 oneElement(c); 1188 try { 1189 c.containsAll(null); 1190 fail("Expected NullPointerException"); 1191 } 1192 catch (NullPointerException e) { pass(); } 1193 catch (Throwable t) { unexpected(t); } 1194 } 1195 } 1196 1197 //---------------------------------------------------------------- 1198 // Map 1199 //---------------------------------------------------------------- 1200 private static void checkFunctionalInvariants(Map<Integer,Integer> m) { 1201 check(m.keySet().size() == m.entrySet().size()); 1202 check(m.keySet().size() == m.size()); 1203 checkFunctionalInvariants(m.keySet()); 1204 checkFunctionalInvariants(m.values()); 1205 check(m.size() != 0 ^ m.isEmpty()); 1206 check(! m.containsKey(ABSENT_VALUE)); 1207 1208 if (m instanceof Serializable) { 1209 //System.out.printf("Serializing %s%n", m.getClass().getName()); 1210 try { 1211 Object clone = serialClone(m); 1212 equal(m instanceof Serializable, 1213 clone instanceof Serializable); 1214 equal(m, clone); 1215 } catch (Error xxx) { 1216 if (! (xxx.getCause() instanceof NotSerializableException)) 1217 throw xxx; 1218 } 1219 } 1220 } 1221 1222 private static void testMap(Map<Integer,Integer> m) { 1223 System.out.println("\n==> " + m.getClass().getName()); 1224 1225 if (m instanceof ConcurrentMap) 1226 testConcurrentMap((ConcurrentMap<Integer,Integer>) m); 1227 1228 if (m instanceof NavigableMap) { 1229 System.out.println("NavigableMap tests..."); 1230 1231 NavigableMap<Integer,Integer> nm = 1232 (NavigableMap<Integer,Integer>) m; 1233 testNavigableMapRemovers(nm); 1234 testNavigableMap(nm); 1235 testNavigableMap(nm.headMap(6, false)); 1236 testNavigableMap(nm.headMap(5, true)); 1237 testNavigableMap(nm.tailMap(0, false)); 1238 testNavigableMap(nm.tailMap(1, true)); 1239 testNavigableMap(nm.subMap(1, true, 6, false)); 1240 testNavigableMap(nm.subMap(0, false, 5, true)); 1241 } 1242 1243 checkFunctionalInvariants(m); 1244 1245 if (supportsClear(m)) { 1246 try { clear(m); } 1247 catch (Throwable t) { unexpected(t); } 1248 } 1249 1250 if (supportsPut(m)) { 1251 try { 1252 check(m.put(3333, 77777) == null); 1253 check(m.put(9134, 74982) == null); 1254 check(m.get(9134) == 74982); 1255 check(m.put(9134, 1382) == 74982); 1256 check(m.get(9134) == 1382); 1257 check(m.size() == 2); 1258 checkFunctionalInvariants(m); 1259 checkNPEConsistency(m); 1260 } 1261 catch (Throwable t) { unexpected(t); } 1262 } 1263 } 1264 1265 private static boolean supportsPut(Map<Integer,Integer> m) { 1266 // We're asking for .equals(...) semantics 1267 if (m instanceof IdentityHashMap) return false; 1268 1269 try { check(m.put(ABSENT_VALUE,12735) == null); } 1270 catch (UnsupportedOperationException t) { return false; } 1271 catch (Throwable t) { unexpected(t); } 1272 1273 try { 1274 check(m.containsKey(ABSENT_VALUE)); 1275 check(m.remove(ABSENT_VALUE) != null); 1276 } catch (Throwable t) { unexpected(t); } 1277 return true; 1278 } 1279 1280 private static boolean supportsClear(Map<?,?> m) { 1281 try { m.clear(); } 1282 catch (UnsupportedOperationException t) { return false; } 1283 catch (Throwable t) { unexpected(t); } 1284 return true; 1285 } 1286 1287 //---------------------------------------------------------------- 1288 // ConcurrentMap 1289 //---------------------------------------------------------------- 1290 private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) { 1291 System.out.println("ConcurrentMap tests..."); 1292 1293 try { 1294 clear(m); 1295 1296 check(m.putIfAbsent(18357,7346) == null); 1297 check(m.containsKey(18357)); 1298 check(m.putIfAbsent(18357,8263) == 7346); 1299 try { m.putIfAbsent(18357,null); fail("NPE"); } 1300 catch (NullPointerException t) { } 1301 check(m.containsKey(18357)); 1302 1303 check(! m.replace(18357,8888,7777)); 1304 check(m.containsKey(18357)); 1305 try { m.replace(18357,null,7777); fail("NPE"); } 1306 catch (NullPointerException t) { } 1307 check(m.containsKey(18357)); 1308 check(m.get(18357) == 7346); 1309 check(m.replace(18357,7346,5555)); 1310 check(m.replace(18357,5555,7346)); 1311 check(m.get(18357) == 7346); 1312 1313 check(m.replace(92347,7834) == null); 1314 try { m.replace(18357,null); fail("NPE"); } 1315 catch (NullPointerException t) { } 1316 check(m.replace(18357,7346) == 7346); 1317 check(m.replace(18357,5555) == 7346); 1318 check(m.get(18357) == 5555); 1319 check(m.replace(18357,7346) == 5555); 1320 check(m.get(18357) == 7346); 1321 1322 check(! m.remove(18357,9999)); 1323 check(m.get(18357) == 7346); 1324 check(m.containsKey(18357)); 1325 check(! m.remove(18357,null)); // 6272521 1326 check(m.get(18357) == 7346); 1327 check(m.remove(18357,7346)); 1328 check(m.get(18357) == null); 1329 check(! m.containsKey(18357)); 1330 check(m.isEmpty()); 1331 1332 m.putIfAbsent(1,2); 1333 check(m.size() == 1); 1334 check(! m.remove(1,null)); 1335 check(! m.remove(1,null)); 1336 check(! m.remove(1,1)); 1337 check(m.remove(1,2)); 1338 check(m.isEmpty()); 1339 1340 testEmptyMap(m); 1341 } 1342 catch (Throwable t) { unexpected(t); } 1343 } 1344 1345 private static void throwsConsistently(Class<? extends Throwable> k, 1346 Iterable<Fun> fs) { 1347 List<Class<? extends Throwable>> threw = new ArrayList<>(); 1348 for (Fun f : fs) 1349 try { f.f(); threw.add(null); } 1350 catch (Throwable t) { 1351 check(k.isAssignableFrom(t.getClass())); 1352 threw.add(t.getClass()); 1353 } 1354 if (new HashSet<Object>(threw).size() != 1) 1355 fail(threw.toString()); 1356 } 1357 1358 private static <T> void checkNPEConsistency(final Map<T,Integer> m) { 1359 m.clear(); 1360 final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap) 1361 ? (ConcurrentMap<T,Integer>) m 1362 : null; 1363 List<Fun> fs = new ArrayList<>(); 1364 fs.add(() -> check(! m.containsKey(null))); 1365 fs.add(() -> equal(m.remove(null), null)); 1366 fs.add(() -> equal(m.get(null), null)); 1367 if (cm != null) 1368 fs.add(() -> check(! cm.remove(null,null))); 1369 throwsConsistently(NullPointerException.class, fs); 1370 1371 fs.clear(); 1372 final Map<T,Integer> sm = singletonMap(null,1); 1373 fs.add(() -> { equal(m.put(null,1), null); m.clear();}); 1374 fs.add(() -> { m.putAll(sm); m.clear();}); 1375 if (cm != null) { 1376 fs.add(() -> check(! cm.remove(null,null))); 1377 fs.add(() -> equal(cm.putIfAbsent(null,1), 1)); 1378 fs.add(() -> equal(cm.replace(null,1), null)); 1379 fs.add(() -> equal(cm.replace(null,1, 1), 1)); 1380 } 1381 throwsConsistently(NullPointerException.class, fs); 1382 } 1383 1384 //---------------------------------------------------------------- 1385 // NavigableMap 1386 //---------------------------------------------------------------- 1387 private static void 1388 checkNavigableMapKeys(NavigableMap<Integer,Integer> m, 1389 Integer i, 1390 Integer lower, 1391 Integer floor, 1392 Integer ceiling, 1393 Integer higher) { 1394 equal(m.lowerKey(i), lower); 1395 equal(m.floorKey(i), floor); 1396 equal(m.ceilingKey(i), ceiling); 1397 equal(m.higherKey(i), higher); 1398 } 1399 1400 private static void 1401 checkNavigableSetKeys(NavigableSet<Integer> m, 1402 Integer i, 1403 Integer lower, 1404 Integer floor, 1405 Integer ceiling, 1406 Integer higher) { 1407 equal(m.lower(i), lower); 1408 equal(m.floor(i), floor); 1409 equal(m.ceiling(i), ceiling); 1410 equal(m.higher(i), higher); 1411 } 1412 1413 static final Random rnd = new Random(); 1414 static void equalNext(final Iterator<?> it, Object expected) { 1415 if (rnd.nextBoolean()) 1416 check(it.hasNext()); 1417 equal(it.next(), expected); 1418 } 1419 1420 static void equalMaps(Map m1, Map m2) { 1421 equal(m1, m2); 1422 equal(m2, m1); 1423 equal(m1.size(), m2.size()); 1424 equal(m1.isEmpty(), m2.isEmpty()); 1425 equal(m1.toString(), m2.toString()); 1426 check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray())); 1427 } 1428 1429 @SuppressWarnings({"unchecked", "rawtypes"}) 1430 static void testNavigableMapRemovers(NavigableMap m) 1431 { 1432 final Map emptyMap = new HashMap(); 1433 1434 final Map singletonMap = new HashMap(); 1435 singletonMap.put(1, 2); 1436 1437 abstract class NavigableMapView { 1438 abstract NavigableMap view(NavigableMap m); 1439 } 1440 1441 NavigableMapView[] views = { 1442 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1443 return m; }}, 1444 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1445 return m.headMap(99, true); }}, 1446 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1447 return m.tailMap(-99, false); }}, 1448 new NavigableMapView() { NavigableMap view(NavigableMap m) { 1449 return m.subMap(-99, true, 99, false); }}, 1450 }; 1451 1452 abstract class Remover { 1453 abstract void remove(NavigableMap m, Object k, Object v); 1454 } 1455 1456 Remover[] removers = { 1457 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1458 equal(m.remove(k), v); }}, 1459 1460 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1461 equal(m.descendingMap().remove(k), v); }}, 1462 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1463 equal(m.descendingMap().headMap(-86, false).remove(k), v); }}, 1464 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1465 equal(m.descendingMap().tailMap(86, true).remove(k), v); }}, 1466 1467 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1468 equal(m.headMap(86, true).remove(k), v); }}, 1469 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1470 equal(m.tailMap(-86, true).remove(k), v); }}, 1471 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1472 equal(m.subMap(-86, false, 86, true).remove(k), v); }}, 1473 1474 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1475 check(m.keySet().remove(k)); }}, 1476 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1477 check(m.navigableKeySet().remove(k)); }}, 1478 1479 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1480 check(m.navigableKeySet().headSet(86, true).remove(k)); }}, 1481 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1482 check(m.navigableKeySet().tailSet(-86, false).remove(k)); }}, 1483 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1484 check(m.navigableKeySet().subSet(-86, true, 86, false) 1485 .remove(k)); }}, 1486 1487 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1488 check(m.descendingKeySet().headSet(-86, false).remove(k)); }}, 1489 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1490 check(m.descendingKeySet().tailSet(86, true).remove(k)); }}, 1491 new Remover() { void remove(NavigableMap m, Object k, Object v) { 1492 check(m.descendingKeySet().subSet(86, true, -86, false) 1493 .remove(k)); }}, 1494 }; 1495 1496 for (NavigableMapView view : views) { 1497 for (Remover remover : removers) { 1498 try { 1499 m.clear(); 1500 equalMaps(m, emptyMap); 1501 equal(m.put(1, 2), null); 1502 equalMaps(m, singletonMap); 1503 NavigableMap v = view.view(m); 1504 remover.remove(v, 1, 2); 1505 equalMaps(m, emptyMap); 1506 } catch (Throwable t) { unexpected(t); } 1507 } 1508 } 1509 } 1510 1511 private static void testNavigableMap(NavigableMap<Integer,Integer> m) 1512 { 1513 clear(m); 1514 checkNavigableMapKeys(m, 1, null, null, null, null); 1515 1516 equal(m.put(1, 2), null); 1517 equal(m.put(3, 4), null); 1518 equal(m.put(5, 9), null); 1519 1520 equal(m.put(1, 2), 2); 1521 equal(m.put(3, 4), 4); 1522 equal(m.put(5, 6), 9); 1523 1524 checkNavigableMapKeys(m, 0, null, null, 1, 1); 1525 checkNavigableMapKeys(m, 1, null, 1, 1, 3); 1526 checkNavigableMapKeys(m, 2, 1, 1, 3, 3); 1527 checkNavigableMapKeys(m, 3, 1, 3, 3, 5); 1528 checkNavigableMapKeys(m, 5, 3, 5, 5, null); 1529 checkNavigableMapKeys(m, 6, 5, 5, null, null); 1530 1531 for (final Iterator<Integer> it : 1532 (Iterator<Integer>[]) 1533 new Iterator<?>[] { 1534 m.descendingKeySet().iterator(), 1535 m.navigableKeySet().descendingIterator()}) { 1536 equalNext(it, 5); 1537 equalNext(it, 3); 1538 equalNext(it, 1); 1539 check(! it.hasNext()); 1540 THROWS(NoSuchElementException.class, () -> it.next()); 1541 } 1542 1543 { 1544 final Iterator<Map.Entry<Integer,Integer>> it 1545 = m.descendingMap().entrySet().iterator(); 1546 check(it.hasNext()); equal(it.next().getKey(), 5); 1547 check(it.hasNext()); equal(it.next().getKey(), 3); 1548 check(it.hasNext()); equal(it.next().getKey(), 1); 1549 check(! it.hasNext()); 1550 THROWS(NoSuchElementException.class, () -> it.next()); 1551 } 1552 1553 prepMapForDescItrTests(m); 1554 checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator()); 1555 prepMapForDescItrTests(m); 1556 checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator()); 1557 prepMapForDescItrTests(m); 1558 checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator()); 1559 1560 prepMapForDescItrTests(m); 1561 checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator()); 1562 prepMapForDescItrTests(m); 1563 checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator()); 1564 prepMapForDescItrTests(m); 1565 checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator()); 1566 1567 prepMapForDescItrTests(m); 1568 checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator()); 1569 prepMapForDescItrTests(m); 1570 checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator()); 1571 prepMapForDescItrTests(m); 1572 checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator()); 1573 1574 prepMapForDescItrTests(m); 1575 checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator()); 1576 prepMapForDescItrTests(m); 1577 checkDescItrRmMid(m.values(), m.descendingMap().values().iterator()); 1578 prepMapForDescItrTests(m); 1579 checkDescItrRmLast(m.values(), m.descendingMap().values().iterator()); 1580 1581 prepMapForDescItrTests(m); 1582 checkDescItrRmFirst((Collection)m.entrySet(), 1583 m.descendingMap().entrySet().iterator()); 1584 prepMapForDescItrTests(m); 1585 checkDescItrRmMid((Collection)m.entrySet(), 1586 m.descendingMap().entrySet().iterator()); 1587 prepMapForDescItrTests(m); 1588 checkDescItrRmLast((Collection)m.entrySet(), 1589 m.descendingMap().entrySet().iterator()); 1590 } 1591 1592 private static void testNavigableSet(NavigableSet<Integer> s) { 1593 clear(s); 1594 checkNavigableSetKeys(s, 1, null, null, null, null); 1595 1596 check(s.add(1)); 1597 check(s.add(3)); 1598 check(s.add(5)); 1599 1600 check(! s.add(1)); 1601 check(! s.add(3)); 1602 check(! s.add(5)); 1603 1604 checkNavigableSetKeys(s, 0, null, null, 1, 1); 1605 checkNavigableSetKeys(s, 1, null, 1, 1, 3); 1606 checkNavigableSetKeys(s, 2, 1, 1, 3, 3); 1607 checkNavigableSetKeys(s, 3, 1, 3, 3, 5); 1608 checkNavigableSetKeys(s, 5, 3, 5, 5, null); 1609 checkNavigableSetKeys(s, 6, 5, 5, null, null); 1610 1611 for (final Iterator<Integer> it : 1612 (Iterator<Integer>[]) 1613 new Iterator<?>[] { 1614 s.descendingIterator(), 1615 s.descendingSet().iterator()}) { 1616 equalNext(it, 5); 1617 equalNext(it, 3); 1618 equalNext(it, 1); 1619 check(! it.hasNext()); 1620 THROWS(NoSuchElementException.class, () -> it.next()); 1621 } 1622 1623 prepSetForDescItrTests(s); 1624 checkDescItrRmFirst(s, s.descendingIterator()); 1625 prepSetForDescItrTests(s); 1626 checkDescItrRmMid(s, s.descendingIterator()); 1627 prepSetForDescItrTests(s); 1628 checkDescItrRmLast(s, s.descendingIterator()); 1629 1630 prepSetForDescItrTests(s); 1631 checkDescItrRmFirst(s, s.descendingSet().iterator()); 1632 prepSetForDescItrTests(s); 1633 checkDescItrRmMid(s, s.descendingSet().iterator()); 1634 prepSetForDescItrTests(s); 1635 checkDescItrRmLast(s, s.descendingSet().iterator()); 1636 } 1637 1638 private static void prepSetForDescItrTests(Set s) { 1639 clear(s); 1640 check(s.add(1)); 1641 check(s.add(3)); 1642 check(s.add(5)); 1643 } 1644 1645 private static void prepMapForDescItrTests(Map m) { 1646 clear(m); 1647 equal(m.put(1, 2), null); 1648 equal(m.put(3, 4), null); 1649 equal(m.put(5, 9), null); 1650 } 1651 1652 //-------------------------------------------------------------------- 1653 // Check behavior of descending iterator when first element is removed 1654 //-------------------------------------------------------------------- 1655 private static <T> void checkDescItrRmFirst(Collection<T> ascColl, 1656 Iterator<T> descItr) { 1657 T[] expected = (T[]) ascColl.toArray(); 1658 int idx = expected.length -1; 1659 1660 equalNext(descItr, expected[idx--]); 1661 descItr.remove(); 1662 while (idx >= 0 && descItr.hasNext()) { 1663 equalNext(descItr, expected[idx--]); 1664 } 1665 equal(descItr.hasNext(), false); 1666 equal(idx, -1); 1667 } 1668 1669 //----------------------------------------------------------------------- 1670 // Check behavior of descending iterator when a middle element is removed 1671 //----------------------------------------------------------------------- 1672 private static <T> void checkDescItrRmMid(Collection<T> ascColl, 1673 Iterator<T> descItr) { 1674 T[] expected = (T[]) ascColl.toArray(); 1675 int idx = expected.length -1; 1676 1677 while (idx >= expected.length / 2) { 1678 equalNext(descItr, expected[idx--]); 1679 } 1680 descItr.remove(); 1681 while (idx >= 0 && descItr.hasNext()) { 1682 equalNext(descItr, expected[idx--]); 1683 } 1684 equal(descItr.hasNext(), false); 1685 equal(idx, -1); 1686 } 1687 1688 //----------------------------------------------------------------------- 1689 // Check behavior of descending iterator when the last element is removed 1690 //----------------------------------------------------------------------- 1691 private static <T> void checkDescItrRmLast(Collection<T> ascColl, 1692 Iterator<T> descItr) { 1693 T[] expected = (T[]) ascColl.toArray(); 1694 int idx = expected.length -1; 1695 1696 while (idx >= 0 && descItr.hasNext()) { 1697 equalNext(descItr, expected[idx--]); 1698 } 1699 equal(idx, -1); 1700 equal(descItr.hasNext(), false); 1701 descItr.remove(); 1702 equal(ascColl.contains(expected[0]), false); 1703 } 1704 1705 //--------------------- Infrastructure --------------------------- 1706 static volatile int passed = 0, failed = 0; 1707 static void pass() { passed++; } 1708 static void fail() { failed++; Thread.dumpStack(); } 1709 static void fail(String msg) { System.out.println(msg); fail(); } 1710 static void unexpected(Throwable t) { failed++; t.printStackTrace(); } 1711 static void check(boolean cond) { if (cond) pass(); else fail(); } 1712 static void equal(Object x, Object y) { 1713 if (x == null ? y == null : x.equals(y)) pass(); 1714 else {System.out.println(x + " not equal to " + y); fail();}} 1715 static void equal(Object x, Object y, String msg) { 1716 if (x == null ? y == null : x.equals(y)) pass(); 1717 else {System.out.println(x + " not equal to " + y + " : " + msg); fail();}} 1718 static void equal2(Object x, Object y) {equal(x, y); equal(y, x);} 1719 public static void main(String[] args) throws Throwable { 1720 try { realMain(args); } catch (Throwable t) { unexpected(t); } 1721 1722 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 1723 if (failed > 0) throw new Exception("Some tests failed"); 1724 } 1725 interface Fun {void f() throws Throwable;} 1726 private static void THROWS(Class<? extends Throwable> k, Fun... fs) { 1727 for (Fun f : fs) 1728 try { f.f(); fail("Expected " + k.getName() + " not thrown"); } 1729 catch (Throwable t) { 1730 if (k.isAssignableFrom(t.getClass())) pass(); 1731 else unexpected(t);}} 1732 static byte[] serializedForm(Object obj) { 1733 try { 1734 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1735 new ObjectOutputStream(baos).writeObject(obj); 1736 return baos.toByteArray(); 1737 } catch (IOException e) { throw new Error(e); }} 1738 static Object readObject(byte[] bytes) 1739 throws IOException, ClassNotFoundException { 1740 InputStream is = new ByteArrayInputStream(bytes); 1741 return new ObjectInputStream(is).readObject();} 1742 @SuppressWarnings("unchecked") 1743 static <T> T serialClone(T obj) { 1744 try { return (T) readObject(serializedForm(obj)); } 1745 catch (Exception e) { throw new Error(e); }} 1746 private static class NewAbstractCollection<E> extends AbstractCollection<E> { 1747 ArrayList<E> list = new ArrayList<>(); 1748 public boolean remove(Object obj) { 1749 return list.remove(obj); 1750 } 1751 public boolean add(E e) { 1752 return list.add(e); 1753 } 1754 public Iterator<E> iterator() { 1755 return list.iterator(); 1756 } 1757 public int size() { 1758 return list.size(); 1759 } 1760 } 1761 private static class NewAbstractSet<E> extends AbstractSet<E> { 1762 HashSet<E> set = new HashSet<>(); 1763 public boolean remove(Object obj) { 1764 return set.remove(obj); 1765 } 1766 public boolean add(E e) { 1767 return set.add(e); 1768 } 1769 public Iterator<E> iterator() { 1770 return set.iterator(); 1771 } 1772 public int size() { 1773 return set.size(); 1774 } 1775 } 1776 1777 }