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