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