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