/*
 * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug     6207984 6272521 6192552 6269713 6197726 6260652 5073546 4137464
 *          4155650 4216399 4294891 6282555 6318622 6355327 6383475 6420753
 *          6431845 4802633 6570566 6570575 6570631 6570924 6691185 6691215
 *          4802647 7123424 8024709 8193128 8327858
 * @summary Run many tests on many Collection and Map implementations
 * @author  Martin Buchholz
 * @modules java.base/java.util:open
 * @enablePreview
 * @run main MOAT
 * @key randomness
 */

/* Mother Of All (Collection) Tests
 *
 * Testing of collection classes is often spotty, because many tests
 * need to be performed on many implementations, but the onus on
 * writing the tests falls on the engineer introducing the new
 * implementation.
 *
 * The idea of this mega-test is that:
 *
 * An engineer adding a new collection implementation could simply add
 * their new implementation to a list of implementations in this
 * test's main method.  Any general purpose Collection<Integer> or
 * Map<Integer,Integer> class is appropriate.
 *
 * An engineer fixing a regression could add their regression test here and
 * simultaneously test all other implementations.
 */

import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import static java.util.Collections.*;
import java.lang.reflect.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class MOAT {
    // Collections under test must not be initialized to contain this value,
    // and maps under test must not contain this value as a key.
    // It's used as a sentinel for absent-element testing.
    static final int ABSENT_VALUE = 778347983;

    static final Integer[] integerArray;
    static {
        Integer[] ia = new Integer[20];
        // fill with 1..20 inclusive
        for (int i = 0; i < ia.length; i++) {
            ia[i] = i + 1;
        }
        integerArray = ia;
    }

    public static void realMain(String[] args) {

        testCollection(new NewAbstractCollection<Integer>());
        testCollection(new NewAbstractSet<Integer>());
        testCollection(new LinkedHashSet<Integer>());
        testCollection(new HashSet<Integer>());
        testCollection(new Vector<Integer>());
        testCollection(new Vector<Integer>().subList(0,0));
        testCollection(new ArrayDeque<Integer>());
        testCollection(new ArrayList<Integer>());
        testCollection(new ArrayList<Integer>().subList(0,0));
        testCollection(new LinkedList<Integer>());
        testCollection(new LinkedList<Integer>().subList(0,0));
        testCollection(new TreeSet<Integer>());
        testCollection(Collections.checkedList(new ArrayList<Integer>(), Integer.class));
        testCollection(Collections.synchronizedList(new ArrayList<Integer>()));
        testCollection(Collections.checkedSet(new HashSet<Integer>(), Integer.class));
        testCollection(Collections.checkedSortedSet(new TreeSet<Integer>(), Integer.class));
        testCollection(Collections.checkedNavigableSet(new TreeSet<Integer>(), Integer.class));
        testCollection(Collections.synchronizedSet(new HashSet<Integer>()));
        testCollection(Collections.synchronizedSortedSet(new TreeSet<Integer>()));
        testCollection(Collections.synchronizedNavigableSet(new TreeSet<Integer>()));

        testCollection(new CopyOnWriteArrayList<Integer>());
        testCollection(new CopyOnWriteArrayList<Integer>().subList(0,0));
        testCollection(new CopyOnWriteArraySet<Integer>());
        testCollection(new PriorityQueue<Integer>());
        testCollection(new PriorityBlockingQueue<Integer>());
        testCollection(new ArrayBlockingQueue<Integer>(20));
        testCollection(new LinkedBlockingQueue<Integer>(20));
        testCollection(new LinkedBlockingDeque<Integer>(20));
        testCollection(new ConcurrentLinkedDeque<Integer>());
        testCollection(new ConcurrentLinkedQueue<Integer>());
        testCollection(new LinkedTransferQueue<Integer>());
        testCollection(new ConcurrentSkipListSet<Integer>());
        testCollection(Arrays.asList(new Integer(42)));
        testCollection(Arrays.asList(1,2,3));
        testCollection(nCopies(25,1));
        testImmutableList(nCopies(25,1));

        testMap(new HashMap<Integer,Integer>());
        testMap(new LinkedHashMap<Integer,Integer>());

        // TODO: Add reliable support for WeakHashMap.
        // This test is subject to very rare failures because the GC
        // may remove unreferenced-keys from the map at any time.
        // testMap(new WeakHashMap<Integer,Integer>());

        testMap(new IdentityHashMap<Integer,Integer>());
        testMap(new TreeMap<Integer,Integer>());
        testMap(new Hashtable<Integer,Integer>());
        testMap(new ConcurrentHashMap<Integer,Integer>(10, 0.5f));
        testMap(new ConcurrentSkipListMap<Integer,Integer>());
        testMap(Collections.checkedMap(new HashMap<Integer,Integer>(), Integer.class, Integer.class));
        testMap(Collections.checkedSortedMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
        testMap(Collections.checkedNavigableMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
        testMap(Collections.synchronizedMap(new HashMap<Integer,Integer>()));
        testMap(Collections.synchronizedSortedMap(new TreeMap<Integer,Integer>()));
        testMap(Collections.synchronizedNavigableMap(new TreeMap<Integer,Integer>()));

        // Unmodifiable wrappers
        testImmutableSet(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))), 99);
        testImmutableSet(AccessFlag.maskToAccessFlags(0, AccessFlag.Location.CLASS), AccessFlag.ABSTRACT);
        testImmutableSet(AccessFlag.maskToAccessFlags(Modifier.PUBLIC | Modifier.STATIC | Modifier.SYNCHRONIZED, AccessFlag.Location.METHOD), AccessFlag.ABSTRACT);
        testImmutableList(unmodifiableList(Arrays.asList(1,2,3)));
        testImmutableMap(unmodifiableMap(Collections.singletonMap(1,2)));
        testImmutableSeqColl(unmodifiableSequencedCollection(Arrays.asList(1,2,3)), 99);
        testImmutableSeqColl(unmodifiableSequencedSet(new LinkedHashSet<>(Arrays.asList(1,2,3))), 99);
        var lhm = new LinkedHashMap<Integer,Integer>(); lhm.put(1,2); lhm.put(3, 4);
        testImmutableSeqMap(unmodifiableSequencedMap(lhm));
        testCollMutatorsAlwaysThrow(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))));
        testCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
        testEmptyCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
        testListMutatorsAlwaysThrow(unmodifiableList(Arrays.asList(1,2,3)));
        testListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
        testEmptyListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
        testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.singletonMap(1,2)));
        testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));
        testEmptyMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));

        // Empty collections
        final List<Integer> emptyArray = Arrays.asList(new Integer[]{});
        testCollection(emptyArray);
        testEmptyList(emptyArray);
        THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1));
        THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1));

        List<Integer> noOne = nCopies(0,1);
        testCollection(noOne);
        testEmptyList(noOne);
        testImmutableList(noOne);

        Set<Integer> emptySet = emptySet();
        testCollection(emptySet);
        testEmptySet(emptySet);
        testEmptySet(EMPTY_SET);
        testEmptySet(Collections.emptySet());
        testEmptySet(Collections.emptySortedSet());
        testEmptySet(Collections.emptyNavigableSet());
        testImmutableSet(emptySet, 99);

        List<Integer> emptyList = emptyList();
        testCollection(emptyList);
        testEmptyList(emptyList);
        testEmptyList(EMPTY_LIST);
        testEmptyList(Collections.emptyList());
        testImmutableList(emptyList);

        Map<Integer,Integer> emptyMap = emptyMap();
        testMap(emptyMap);
        testEmptyMap(emptyMap);
        testEmptyMap(EMPTY_MAP);
        testEmptyMap(Collections.emptyMap());
        testEmptyMap(Collections.emptySortedMap());
        testEmptyMap(Collections.emptyNavigableMap());
        testImmutableMap(emptyMap);
        testImmutableMap(Collections.emptyMap());
        testImmutableMap(Collections.emptySortedMap());
        testImmutableMap(Collections.emptyNavigableMap());

        // Singleton collections
        Set<Integer> singletonSet = singleton(1);
        equal(singletonSet.size(), 1);
        testCollection(singletonSet);
        testImmutableSet(singletonSet, 99);

        List<Integer> singletonList = singletonList(1);
        equal(singletonList.size(), 1);
        testCollection(singletonList);
        testImmutableList(singletonList);
        testImmutableList(singletonList.subList(0,1));
        testImmutableList(singletonList.subList(0,1).subList(0,1));
        testEmptyList(singletonList.subList(0,0));
        testEmptyList(singletonList.subList(0,0).subList(0,0));

        Map<Integer,Integer> singletonMap = singletonMap(1,2);
        equal(singletonMap.size(), 1);
        testMap(singletonMap);
        testImmutableMap(singletonMap);

        // Immutable List
        testEmptyList(List.of());
        testEmptyList(List.of().subList(0,0));
        testEmptyList(StableValue.list(0, i -> i));
        testEmptyList(StableValue.list(3, i -> i).subList(0, 0));
        testListMutatorsAlwaysThrow(List.of());
        testListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
        testListMutatorsAlwaysThrow(StableValue.list(0, i -> i));
        testEmptyListMutatorsAlwaysThrow(List.of());
        testEmptyListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
        testEmptyListMutatorsAlwaysThrow(StableValue.list(0, i -> i));
        testEmptyListMutatorsAlwaysThrow(StableValue.list(3, i -> i).subList(0, 0));
        for (List<Integer> list : Arrays.asList(
                List.<Integer>of(),
                List.of(1),
                List.of(1, 2),
                List.of(1, 2, 3),
                List.of(1, 2, 3, 4),
                List.of(1, 2, 3, 4, 5),
                List.of(1, 2, 3, 4, 5, 6),
                List.of(1, 2, 3, 4, 5, 6, 7),
                List.of(1, 2, 3, 4, 5, 6, 7, 8),
                List.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
                List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
                List.of(integerArray),
                Stream.<Integer>empty().toList(),
                Stream.of(1).toList(),
                Stream.of(1, 2).toList(),
                Stream.of(1, 2, 3).toList(),
                Stream.of(1, 2, 3, 4).toList(),
                Stream.of((Integer)null).toList(),
                Stream.of(1, null).toList(),
                Stream.of(1, null, 3).toList(),
                Stream.of(1, null, 3, 4).toList(),
                StableValue.list(0, i -> i),
                StableValue.list(3, i -> i),
                StableValue.list(10, i -> i))) {
            testCollection(list);
            testImmutableList(list);
            testListMutatorsAlwaysThrow(list);
            testImmutableListMutatorsAlwaysThrow(list);
            if (list.size() >= 1) {
                // test subLists
                List<Integer> headList = list.subList(0, list.size() - 1);
                List<Integer> tailList = list.subList(1, list.size());
                testCollection(headList);
                testCollection(tailList);
                testImmutableList(headList);
                testImmutableList(tailList);
                testListMutatorsAlwaysThrow(headList);
                testListMutatorsAlwaysThrow(tailList);
            }
        }

        List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3));
        testCollection(listCopy);
        testImmutableList(listCopy);
        testListMutatorsAlwaysThrow(listCopy);

        List<Integer> listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList());
        equal(listCollected, List.of(1, 2, 3));
        testCollection(listCollected);
        testImmutableList(listCollected);
        testListMutatorsAlwaysThrow(listCollected);

        // List indexOf / lastIndexOf

        // 0 element
        System.out.println("testListIndexOf size 0");
        testListIndexOf(-1, -1);

        System.out.println("testListIndexOf size 1");
        testListIndexOf(-1, -1, 0);
        testListIndexOf(0, 0, 1);

        System.out.println("testListIndexOf size 2");
        testListIndexOf(-1, -1, 0, 0);
        testListIndexOf(0, 0, 1, 0);
        testListIndexOf(0, 1, 1, 1);
        testListIndexOf(1, 1, 0, 1);


        System.out.println("testListIndexOf size 3");
        testListIndexOf(-1, -1, 0, 0, 0);
        testListIndexOf(0, 0, 1, 0, 0);
        testListIndexOf(0, 1, 1, 1, 0);
        testListIndexOf(1, 2, 0, 1, 1);
        testListIndexOf(2, 2, 0, 0, 1);

        System.out.println("testListIndexOf size N");
        testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0);
        testListIndexOf(2, 6, 0, 0, 1, 0, 1, 0, 1);
        testListIndexOf(4, 4, 0, 0, 0, 0, 1, 0, 0);
        testListIndexOf(0, 6, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 7, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        testListIndexOf(12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
        testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

        // Immutable Set
        testEmptySet(Set.of());
        testCollMutatorsAlwaysThrow(Set.of());
        testEmptyCollMutatorsAlwaysThrow(Set.of());
        for (Set<Integer> set : Arrays.asList(
                Set.<Integer>of(),
                Set.of(1),
                Set.of(1, 2),
                Set.of(1, 2, 3),
                Set.of(1, 2, 3, 4),
                Set.of(1, 2, 3, 4, 5),
                Set.of(1, 2, 3, 4, 5, 6),
                Set.of(1, 2, 3, 4, 5, 6, 7),
                Set.of(1, 2, 3, 4, 5, 6, 7, 8),
                Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
                Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
                Set.of(integerArray))) {
            testCollection(set);
            testImmutableSet(set, 99);
            testCollMutatorsAlwaysThrow(set);
        }

        Set<Integer> setCopy = Set.copyOf(Arrays.asList(1, 2, 3));
        testCollection(setCopy);
        testImmutableSet(setCopy, 99);
        testCollMutatorsAlwaysThrow(setCopy);

        Set<Integer> setCollected = Stream.of(1, 1, 2, 3, 2, 3)
                                          .collect(Collectors.toUnmodifiableSet());
        equal(setCollected, Set.of(1, 2, 3));
        testCollection(setCollected);
        testImmutableSet(setCollected, 99);
        testCollMutatorsAlwaysThrow(setCollected);

        // Immutable Map

        @SuppressWarnings("unchecked")
        Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20];
        for (int i = 0; i < ea.length; i++) {
            ea[i] = Map.entry(i+1, i+101);
        }

        testEmptyMap(Map.of());
        testMapMutatorsAlwaysThrow(Map.of());
        testEmptyMapMutatorsAlwaysThrow(Map.of());
        testEmptyMap(StableValue.map(Set.of(), k -> k));
        testMapMutatorsAlwaysThrow(StableValue.map(Set.of(), k -> k));
        testEmptyMapMutatorsAlwaysThrow(StableValue.map(Set.of(), k -> k));
        for (Map<Integer,Integer> map : Arrays.asList(
                Map.<Integer,Integer>of(),
                Map.of(1, 101),
                Map.of(1, 101, 2, 202),
                Map.of(1, 101, 2, 202, 3, 303),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909),
                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010),
                Map.ofEntries(ea),
                StableValue.map(Set.<Integer>of(), k -> k),
                StableValue.map(Set.of(1), k -> k),
                StableValue.map(Set.of(1, 2, 3), k -> k))) {
            testMap(map);
            testImmutableMap(map);
            testMapMutatorsAlwaysThrow(map);
        }

        Map<Integer,Integer> mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303)));
        testMap(mapCopy);
        testImmutableMap(mapCopy);
        testMapMutatorsAlwaysThrow(mapCopy);

        Map<Integer,Integer> mapCollected1 =
            Stream.of(1, 2, 3)
                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
        equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303));
        testMap(mapCollected1);
        testImmutableMap(mapCollected1);
        testMapMutatorsAlwaysThrow(mapCollected1);

        try {
            Stream.of(1, 1, 2, 3, 2, 3)
                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
            fail("duplicates should have thrown an exception");
        } catch (IllegalStateException ise) {
            pass();
        }

        Map<Integer,Integer> mapCollected2 =
            Stream.of(1, 1, 2, 3, 2, 3)
                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum));
        equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606));
        testMap(mapCollected2);
        testImmutableMap(mapCollected2);
        testMapMutatorsAlwaysThrow(mapCollected2);
    }

    private static void checkContainsSelf(Collection<Integer> c) {
        check(c.containsAll(c));
        check(c.containsAll(Arrays.asList(c.toArray())));
        check(c.containsAll(Arrays.asList(c.toArray(new Integer[0]))));
    }

    private static void checkContainsEmpty(Collection<Integer> c) {
        check(c.containsAll(new ArrayList<Integer>()));
    }

    private static void checkUnique(Set<Integer> s) {
        for (Integer i : s) {
            int count = 0;
            for (Integer j : s) {
                if (Objects.equals(i,j))
                    ++count;
            }
            check(count == 1);
        }
    }

    private static <T> void testEmptyCollection(Collection<T> c) {
        check(c.isEmpty());
        equal(c.size(), 0);
        equal(c.toString(),"[]");
        equal(c.toArray().length, 0);
        equal(c.toArray(new Object[0]).length, 0);
        equal(c.toArray(Object[]::new).length, 0);
        check(c.toArray(new Object[]{42})[0] == null);

        Object[] a = new Object[1]; a[0] = Boolean.TRUE;
        equal(c.toArray(a), a);
        equal(a[0], null);
        testEmptyIterator(c.iterator());
    }

    static <T> void testEmptyIterator(final Iterator<T> it) {
        if (rnd.nextBoolean())
            check(! it.hasNext());

        THROWS(NoSuchElementException.class, () -> it.next());

        try { it.remove(); }
        catch (IllegalStateException ignored) { pass(); }
        catch (UnsupportedOperationException ignored) { pass(); }
        catch (Throwable t) { unexpected(t); }

        if (rnd.nextBoolean())
            check(! it.hasNext());
    }

    private static void testEmptyList(List<?> c) {
        testEmptyCollection(c);
        equal(c.hashCode(), 1);
        equal2(c, Collections.<Integer>emptyList());
    }

    private static <T> void testEmptySet(Set<T> c) {
        testEmptyCollection(c);
        equal(c.hashCode(), 0);
        equal2(c, Collections.<Integer>emptySet());
        if (c instanceof NavigableSet<?>)
            testEmptyIterator(((NavigableSet<T>)c).descendingIterator());
    }

    private static <T> void testImmutableCollection(final Collection<T> c, T t) {
        THROWS(UnsupportedOperationException.class,
               () -> c.add(t),
               () -> c.addAll(singleton(t)));
        if (! c.isEmpty()) {
            final T first = c.iterator().next();
            THROWS(UnsupportedOperationException.class,
                   () -> c.clear(),
                   () -> c.remove(first),
                   () -> c.removeAll(singleton(first)),
                   () -> c.retainAll(emptyList()));
        } else {
            testEmptyIterator(c.iterator());
        }
        testForEachMatch(c);
        testSpliteratorMatch(c);
    }

    private static <T> void testImmutableSeqColl(final SequencedCollection<T> c, T t) {
        SequencedCollection<T> r = c.reversed();
        testImmutableCollection(c, t);
        testImmutableCollection(r, t);
        THROWS(UnsupportedOperationException.class,
               () -> c.addFirst(t),
               () -> c.addLast(t),
               () -> r.addFirst(t),
               () -> r.addLast(t));
        if (! c.isEmpty()) {
            THROWS(UnsupportedOperationException.class,
                   () -> c.removeFirst(),
                   () -> c.removeLast(),
                   () -> r.removeFirst(),
                   () -> r.removeLast());
        }
    }

    private static <T> void testImmutableSet(final Set<T> c, T t) {
        testImmutableCollection(c, t);
    }

    private static <T> void testImmutableSeqSet(final SequencedSet<T> c, T t) {
        testImmutableSeqColl(c, t);
    }

    private static void testImmutableList(final List<Integer> c) {
        testList(c);
        testImmutableCollection(c, 42);
        testImmutableSeqColl(c, 42);
        THROWS(UnsupportedOperationException.class,
               () -> c.set(0,42),
               () -> c.add(0,42),
               () -> c.addAll(0,singleton(86)));
        if (! c.isEmpty())
            THROWS(UnsupportedOperationException.class,
                   () -> { Iterator<Integer> it = c.iterator();
                           it.next();
                           it.remove(); },
                   () -> { ListIterator<Integer> it = c.listIterator();
                           it.next();
                           it.remove(); });
    }

    /**
     * Test that calling a mutator always throws UOE, even if the mutator
     * wouldn't actually do anything, given its arguments.
     *
     * @param c the collection instance to test
     */
    private static void testCollMutatorsAlwaysThrow(Collection<Integer> c) {
        THROWS(UnsupportedOperationException.class,
                () -> c.addAll(Collections.emptyList()),
                () -> c.remove(ABSENT_VALUE),
                () -> c.removeAll(Collections.emptyList()),
                () -> c.removeIf(x -> false),
                () -> c.retainAll(c));
    }

    // Ensures forEach supplies in the same order as the iterator
    private static <T> void testForEachMatch(Collection<T> c) {
        var itr = c.iterator();
        int[] index = {0};
        c.forEach(item -> {
            T itrNext = null;
            if (!itr.hasNext() || !Objects.equals(itrNext = itr.next(), item)) {
                fail("forEach and iterator mismatch at " + index[0] + " forEach: " + item + ", itr: " + itrNext);
            }
            index[0]++;
        });
        if (itr.hasNext()) {
            fail("forEach and iterator mismatch at tail, extras in itr");
        }
    }

    // Ensures spliterator returns in the same order as the iterator
    private static <T> void testSpliteratorMatch(Collection<T> c) {
        var itr = c.iterator();
        var split = c.spliterator();
        int[] index = {0};
        split.forEachRemaining(item -> {
            T itrNext = null;
            if (!itr.hasNext() || !Objects.equals(itrNext = itr.next(), item)) {
                fail("iterator and spliterator mismatch at " + index[0] + " spliterator: " + item + ", itr: " + itrNext);
            }
            index[0]++;
        });
        if (itr.hasNext()) {
            fail("iterator and spliterator mismatch at tail, extra item in itr");
        }
    }

    /**
     * Test that calling a mutator always throws UOE, even if the mutator
     * wouldn't actually do anything on an empty collection.
     *
     * @param c the collection instance to test, must be empty
     */
    private static void testEmptyCollMutatorsAlwaysThrow(Collection<Integer> c) {
        if (! c.isEmpty()) {
            fail("collection is not empty");
        }
        THROWS(UnsupportedOperationException.class,
                () -> c.clear());
    }

    /**
     * As above, for a list.
     *
     * @param c the list instance to test
     */
    private static void testListMutatorsAlwaysThrow(List<Integer> c) {
        testCollMutatorsAlwaysThrow(c);
        THROWS(UnsupportedOperationException.class,
                () -> c.addAll(0, Collections.emptyList()));
    }

    private static void testImmutableListMutatorsAlwaysThrow(List<Integer> c) {
        THROWS(UnsupportedOperationException.class,
                c::removeFirst,
                c::removeLast);
    }

    /**
     * As above, for an empty list.
     *
     * @param c the list instance to test, must be empty
     */
    private static void testEmptyListMutatorsAlwaysThrow(List<Integer> c) {
        if (! c.isEmpty()) {
            fail("list is not empty");
        }
        testEmptyCollMutatorsAlwaysThrow(c);
        THROWS(UnsupportedOperationException.class,
                () -> c.replaceAll(x -> x),
                () -> c.sort(null));
    }

    /**
     * As above, for a map.
     *
     * @param m the map instance to test
     */
    private static void testMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
        THROWS(UnsupportedOperationException.class,
                () -> m.compute(ABSENT_VALUE, (k, v) -> null),
                () -> m.computeIfAbsent(ABSENT_VALUE, k -> null),
                () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null),
                () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null),
                () -> m.putAll(Collections.emptyMap()),
                () -> m.remove(ABSENT_VALUE),
                () -> m.remove(ABSENT_VALUE, 0),
                () -> m.replace(ABSENT_VALUE, 0),
                () -> m.replace(ABSENT_VALUE, 0, 1));
    }

    /**
     * As above, for an empty map.
     *
     * @param map the map instance to test, must be empty
     */
    private static void testEmptyMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
        if (! m.isEmpty()) {
            fail("map is not empty");
        }
        THROWS(UnsupportedOperationException.class,
                () -> m.clear(),
                () -> m.replaceAll((k, v) -> v));
    }

    private static void clear(Collection<Integer> c) {
        try { c.clear(); }
        catch (Throwable t) { unexpected(t); }
        testEmptyCollection(c);
    }

    private static <K,V> void testEmptyMap(final Map<K,V> m) {
        check(m.isEmpty());
        equal(m.size(), 0);
        equal(m.toString(),"{}");
        testEmptySet(m.keySet());
        testEmptySet(m.entrySet());
        testEmptyCollection(m.values());

        try { check(! m.containsValue(null)); }
        catch (NullPointerException ignored) { /* OK */ }
        try { check(! m.containsKey(null)); }
        catch (NullPointerException ignored) { /* OK */ }
        check(! m.containsValue(1));
        check(! m.containsKey(1));
    }

    private static void testImmutableMapEntry(final Map.Entry<Integer,Integer> me) {
        Integer key = me.getKey();
        Integer val = me.getValue();
        THROWS(UnsupportedOperationException.class,
               () -> me.setValue(3));
        equal(key, me.getKey());
        equal(val, me.getValue());
    }

    private static void testImmutableMap(final Map<Integer,Integer> m) {
        THROWS(UnsupportedOperationException.class,
               () -> m.put(1,1),
               () -> m.putAll(singletonMap(1,1)));
        if (! m.isEmpty()) {
            final Integer first = m.keySet().iterator().next();
            THROWS(UnsupportedOperationException.class,
                   () -> m.remove(first),
                   () -> m.clear());
            testImmutableMapEntry(m.entrySet().iterator().next());
        }
        testImmutableSet(m.keySet(), 99);
        testImmutableCollection(m.values(), 99);
        testImmutableSet(m.entrySet(), Map.entry(42, 43));
    }

    private static void testImmutableSeqMap(final SequencedMap<Integer,Integer> m) {
        SequencedMap<Integer,Integer> r = m.reversed();
        testImmutableMap(m);
        testImmutableMap(r);
        THROWS(UnsupportedOperationException.class,
               () -> m.putFirst(0, 0),
               () -> m.putLast(0, 0),
               () -> r.putFirst(0, 0),
               () -> r.putLast(0, 0));
        if (! m.isEmpty()) {
            THROWS(UnsupportedOperationException.class,
                   () -> m.pollFirstEntry(),
                   () -> m.pollLastEntry(),
                   () -> r.pollFirstEntry(),
                   () -> r.pollLastEntry());
            testImmutableMapEntry(m.sequencedEntrySet().getFirst());
            testImmutableMapEntry(r.sequencedEntrySet().getFirst());
            testImmutableMapEntry(m.sequencedEntrySet().reversed().getFirst());
            testImmutableMapEntry(r.sequencedEntrySet().reversed().getFirst());
        }
        testImmutableSeqSet(m.sequencedKeySet(), 99);
        testImmutableSeqColl(m.sequencedValues(), 99);
        testImmutableSeqSet(m.sequencedEntrySet(), Map.entry(42, 43));
        testImmutableSeqSet(r.sequencedKeySet(), 99);
        testImmutableSeqColl(r.sequencedValues(), 99);
        testImmutableSeqSet(r.sequencedEntrySet(), Map.entry(42, 43));
    }

    private static void clear(Map<?,?> m) {
        try { m.clear(); }
        catch (Throwable t) { unexpected(t); }
        testEmptyMap(m);
    }

    private static void oneElement(Collection<Integer> c) {
        clear(c);
        try {
            check(c.add(-42));
            equal(c.toString(), "[-42]");
            if (c instanceof Set) check(! c.add(-42));
        } catch (Throwable t) { unexpected(t); }
        check(! c.isEmpty()); check(c.size() == 1);
    }

    private static boolean supportsAdd(Collection<Integer> c) {
        try { check(c.add(ABSENT_VALUE)); }
        catch (UnsupportedOperationException t) { return false; }
        catch (Throwable t) { unexpected(t); }

        try {
            check(c.contains(ABSENT_VALUE));
            check(c.remove(ABSENT_VALUE));
        } catch (Throwable t) { unexpected(t); }
        return true;
    }

    private static boolean supportsRemove(Collection<Integer> c) {
        try { check(! c.remove(ABSENT_VALUE)); }
        catch (UnsupportedOperationException t) { return false; }
        catch (Throwable t) { unexpected(t); }
        return true;
    }

    // 6260652: (coll) Arrays.asList(x).toArray().getClass()
    //          should be Object[].class
    // Fixed in jdk9, but not jdk8 ...
    static final boolean needToWorkAround6260652 =
        Arrays.asList("").toArray().getClass() != Object[].class;

    private static void checkFunctionalInvariants(Collection<Integer> c) {
        try {
            checkContainsSelf(c);
            checkContainsEmpty(c);
            check(c.size() != 0 ^ c.isEmpty());
            check(! c.contains(ABSENT_VALUE));

            {
                int size = 0;
                for (Integer i : c) size++;
                check(c.size() == size);
            }

            if (c instanceof Set) {
                checkUnique((Set<Integer>)c);
            }

            check(c.toArray().length == c.size());
            check(c.toArray().getClass() == Object[].class
                  ||
                  (needToWorkAround6260652 &&
                   c.getClass().getName().equals("java.util.Arrays$ArrayList")));
            for (int size : new int[]{0,1,c.size(), c.size()+1}) {
                Integer[] a = c.toArray(new Integer[size]);
                check((size > c.size()) || a.length == c.size());
                int i = 0; for (Integer j : c) check(a[i++] == j);
                check((size <= c.size()) || (a[c.size()] == null));
                check(a.getClass() == Integer[].class);
            }

            {
                Integer[] a = c.toArray(Integer[]::new);
                equal(c.size(), a.length);
                check(a.getClass() == Integer[].class);
                check(Arrays.equals(c.toArray(new Integer[0]), a));
            }

            check(c.equals(c));
            if (c instanceof Serializable) {
                //System.out.printf("Serializing %s%n", c.getClass().getName());
                try {
                    Object clone = serialClone(c);
                    equal(c instanceof Serializable,
                          clone instanceof Serializable);
                    equal(c instanceof RandomAccess,
                          clone instanceof RandomAccess);
                    if ((c instanceof List) || (c instanceof Set))
                        equal(c, clone);
                    else
                        equal(new HashSet<Integer>(c),
                              new HashSet<Integer>(serialClone(c)));
                } catch (Error xxx) {
                    if (! (xxx.getCause() instanceof NotSerializableException))
                        throw xxx;
                }
            }
        }
        catch (Throwable t) { unexpected(t); }
    }

    //----------------------------------------------------------------
    // If add(null) succeeds, contains(null) & remove(null) should succeed
    //----------------------------------------------------------------
    private static void testNullElement(Collection<Integer> c) {

        try {
            check(c.add(null));
            if (c.size() == 1)
                equal(c.toString(), "[null]");
            try {
                checkFunctionalInvariants(c);
                check(c.contains(null));
                check(c.remove(null));
            }
            catch (Throwable t) { unexpected(t); }
        }
        catch (NullPointerException e) { /* OK */ }
        catch (Throwable t) { unexpected(t); }
    }

    //----------------------------------------------------------------
    // If add("x") succeeds, contains("x") & remove("x") should succeed
    //----------------------------------------------------------------
    @SuppressWarnings("unchecked")
    private static void testStringElement(Collection<Integer> c) {
        Collection x = (Collection)c; // Make type-unsafe
        try {
            check(x.add("x"));
            try {
                check(x.contains("x"));
                check(x.remove("x"));
            } catch (Throwable t) { unexpected(t); }
        }
        catch (ClassCastException e) { /* OK */ }
        catch (Throwable t) { unexpected(t); }
    }

    private static void testConcurrentCollection(Collection<Integer> c) {
        try {
            c.add(1);
            Iterator<Integer> it = c.iterator();
            check(it.hasNext());
            clear(c);
            check(it.next() instanceof Integer); // No CME
            check(c.isEmpty());
        }
        catch (Throwable t) { unexpected(t); }
    }

    private static void testQueue(Queue<Integer> q) {
        q.clear();
        for (int i = 0; i < 5; i++) {
            testQueueAddRemove(q, null);
            testQueueAddRemove(q, 537);
            q.add(i);
        }
        equal(q.size(), 5);
        checkFunctionalInvariants(q);
        q.poll();
        equal(q.size(), 4);
        checkFunctionalInvariants(q);
        if ((q instanceof LinkedBlockingQueue)   ||
            (q instanceof LinkedBlockingDeque)   ||
            (q instanceof ConcurrentLinkedDeque) ||
            (q instanceof ConcurrentLinkedQueue)) {
            testQueueIteratorRemove(q);
        }
    }

    private static void testQueueAddRemove(final Queue<Integer> q,
                                           final Integer e) {
        final List<Integer> originalContents = new ArrayList<>(q);
        final boolean isEmpty = q.isEmpty();
        final boolean isList = (q instanceof List);
        final List asList = isList ? (List) q : null;
        check(!q.contains(e));
        try {
            q.add(e);
        } catch (NullPointerException npe) {
            check(e == null);
            return;                     // Null elements not supported
        }
        check(q.contains(e));
        check(q.remove(e));
        check(!q.contains(e));
        equal(new ArrayList<Integer>(q), originalContents);

        if (q instanceof Deque<?>) {
            final Deque<Integer> deq = (Deque<Integer>) q;
            final List<Integer> singleton = Collections.singletonList(e);

            // insert, query, remove element at head
            if (isEmpty) {
                THROWS(NoSuchElementException.class,
                       () -> deq.getFirst(),
                       () -> deq.element(),
                       () -> deq.iterator().next());
                check(deq.peekFirst() == null);
                check(deq.peek() == null);
            } else {
                check(deq.getFirst() != e);
                check(deq.element() != e);
                check(deq.iterator().next() != e);
                check(deq.peekFirst() != e);
                check(deq.peek() != e);
            }
            check(!deq.contains(e));
            check(!deq.removeFirstOccurrence(e));
            check(!deq.removeLastOccurrence(e));
            if (isList) {
                check(asList.indexOf(e) == -1);
                check(asList.lastIndexOf(e) == -1);
            }
            switch (rnd.nextInt(isList ? 4 : 3)) {
            case 0: deq.addFirst(e); break;
            case 1: check(deq.offerFirst(e)); break;
            case 2: deq.push(e); break;
            case 3: asList.add(0, e); break;
            default: throw new AssertionError();
            }
            check(deq.peekFirst() == e);
            check(deq.getFirst() == e);
            check(deq.element() == e);
            check(deq.peek() == e);
            check(deq.iterator().next() == e);
            check(deq.contains(e));
            if (isList) {
                check(asList.get(0) == e);
                check(asList.indexOf(e) == 0);
                check(asList.lastIndexOf(e) == 0);
                check(asList.subList(0, 1).equals(singleton));
            }
            switch (rnd.nextInt(isList ? 11 : 9)) {
            case 0: check(deq.pollFirst() == e); break;
            case 1: check(deq.removeFirst() == e); break;
            case 2: check(deq.remove() == e); break;
            case 3: check(deq.pop() == e); break;
            case 4: check(deq.removeFirstOccurrence(e)); break;
            case 5: check(deq.removeLastOccurrence(e)); break;
            case 6: check(deq.remove(e)); break;
            case 7: check(deq.removeAll(singleton)); break;
            case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
            case 9: asList.remove(0); break;
            case 10: asList.subList(0, 1).clear(); break;
            default: throw new AssertionError();
            }
            if (isEmpty) {
                THROWS(NoSuchElementException.class,
                       () -> deq.getFirst(),
                       () -> deq.element(),
                       () -> deq.iterator().next());
                check(deq.peekFirst() == null);
                check(deq.peek() == null);
            } else {
                check(deq.getFirst() != e);
                check(deq.element() != e);
                check(deq.iterator().next() != e);
                check(deq.peekFirst() != e);
                check(deq.peek() != e);
            }
            check(!deq.contains(e));
            check(!deq.removeFirstOccurrence(e));
            check(!deq.removeLastOccurrence(e));
            if (isList) {
                check(isEmpty || asList.get(0) != e);
                check(asList.indexOf(e) == -1);
                check(asList.lastIndexOf(e) == -1);
            }
            equal(new ArrayList<Integer>(deq), originalContents);

            // insert, query, remove element at tail
            if (isEmpty) {
                check(deq.peekLast() == null);
                THROWS(NoSuchElementException.class, () -> deq.getLast());
            } else {
                check(deq.peekLast() != e);
                check(deq.getLast() != e);
            }
            switch (rnd.nextInt(isList ? 6 : 4)) {
            case 0: deq.addLast(e); break;
            case 1: check(deq.offerLast(e)); break;
            case 2: check(deq.add(e)); break;
            case 3: deq.addAll(singleton); break;
            case 4: asList.addAll(deq.size(), singleton); break;
            case 5: asList.add(deq.size(), e); break;
            default: throw new AssertionError();
            }
            check(deq.peekLast() == e);
            check(deq.getLast() == e);
            check(deq.contains(e));
            if (isList) {
                ListIterator it = asList.listIterator(asList.size());
                check(it.previous() == e);
                check(asList.get(asList.size() - 1) == e);
                check(asList.indexOf(e) == asList.size() - 1);
                check(asList.lastIndexOf(e) == asList.size() - 1);
                int size = asList.size();
                check(asList.subList(size - 1, size).equals(singleton));
            }
            switch (rnd.nextInt(isList ? 8 : 6)) {
            case 0: check(deq.pollLast() == e); break;
            case 1: check(deq.removeLast() == e); break;
            case 2: check(deq.removeFirstOccurrence(e)); break;
            case 3: check(deq.removeLastOccurrence(e)); break;
            case 4: check(deq.remove(e)); break;
            case 5: check(deq.removeAll(singleton)); break;
            case 6: asList.remove(asList.size() - 1); break;
            case 7:
                ListIterator it = asList.listIterator(asList.size());
                it.previous();
                it.remove();
                break;
            default: throw new AssertionError();
            }
            if (isEmpty) {
                check(deq.peekLast() == null);
                THROWS(NoSuchElementException.class, () -> deq.getLast());
            } else {
                check(deq.peekLast() != e);
                check(deq.getLast() != e);
            }
            check(!deq.contains(e));
            equal(new ArrayList<Integer>(deq), originalContents);

            // Test operations on empty deque
            switch (rnd.nextInt(isList ? 4 : 2)) {
            case 0: deq.clear(); break;
            case 1:
                Iterator it = deq.iterator();
                while (it.hasNext()) {
                    it.next();
                    it.remove();
                }
                break;
            case 2: asList.subList(0, asList.size()).clear(); break;
            case 3:
                ListIterator lit = asList.listIterator(asList.size());
                while (lit.hasPrevious()) {
                    lit.previous();
                    lit.remove();
                }
                break;
            default: throw new AssertionError();
            }
            testEmptyCollection(deq);
            check(!deq.iterator().hasNext());
            if (isList) {
                check(!asList.listIterator().hasPrevious());
                THROWS(NoSuchElementException.class,
                       () -> asList.listIterator().previous());
            }
            THROWS(NoSuchElementException.class,
                   () -> deq.iterator().next(),
                   () -> deq.element(),
                   () -> deq.getFirst(),
                   () -> deq.getLast(),
                   () -> deq.pop(),
                   () -> deq.remove(),
                   () -> deq.removeFirst(),
                   () -> deq.removeLast());

            check(deq.poll() == null);
            check(deq.pollFirst() == null);
            check(deq.pollLast() == null);
            check(deq.peek() == null);
            check(deq.peekFirst() == null);
            check(deq.peekLast() == null);
            check(!deq.removeFirstOccurrence(e));
            check(!deq.removeLastOccurrence(e));

            check(deq.addAll(originalContents) == !isEmpty);
            equal(new ArrayList<Integer>(deq), originalContents);
            check(!deq.addAll(Collections.<Integer>emptyList()));
            equal(new ArrayList<Integer>(deq), originalContents);
        }
    }

    private static void testQueueIteratorRemove(Queue<Integer> q) {
        System.err.printf("testQueueIteratorRemove %s%n",
                          q.getClass().getSimpleName());
        q.clear();
        for (int i = 0; i < 5; i++)
            q.add(i);
        Iterator<Integer> it = q.iterator();
        check(it.hasNext());
        for (int i = 3; i >= 0; i--)
            q.remove(i);
        equal(it.next(), 0);
        equal(it.next(), 4);

        q.clear();
        for (int i = 0; i < 5; i++)
            q.add(i);
        it = q.iterator();
        equal(it.next(), 0);
        check(it.hasNext());
        for (int i = 1; i < 4; i++)
            q.remove(i);
        equal(it.next(), 1);
        equal(it.next(), 4);
    }

    // for any array of integer values, check that the result of lastIndexOf(1)
    // and indexOf(1) match assumptions for all types of List<Integer> we can
    // construct
    private static void testListIndexOf(final int index,
                                        final int lastIndex,
                                        final Integer ... values) {
        if (values.length == 0) {
            checkListIndexOf(emptyList(), index, lastIndex);
        } else if (values.length == 1) {
            checkListIndexOf(singletonList(values[0]), index, lastIndex);
            checkListIndexOf(nCopies(25, values[0]), index, lastIndex == 0 ? 24 : -1);
        }
        List<Integer> l = List.of(values);
        checkListIndexOf(l, index, lastIndex);
        checkListIndexOf(Arrays.asList(values), index, lastIndex);
        checkListIndexOf(new ArrayList(l), index, lastIndex);
        checkListIndexOf(new LinkedList(l), index, lastIndex);
        checkListIndexOf(new Vector(l), index, lastIndex);
        checkListIndexOf(new CopyOnWriteArrayList(l), index, lastIndex);
    }

    private static void checkListIndexOf(final List<Integer> list,
                                         final int index,
                                         final int lastIndex) {
        String msg = list.getClass().toString();
        equal(list.indexOf(1), index, msg);
        equal(list.lastIndexOf(1), lastIndex, msg);
        equal(list.subList(0, list.size()).indexOf(1), index, msg);
        equal(list.subList(0, list.size()).lastIndexOf(1), lastIndex, msg);
    }

    private static void testList(final List<Integer> l) {
        //----------------------------------------------------------------
        // 4802633: (coll) AbstractList.addAll(-1,emptyCollection)
        // doesn't throw IndexOutOfBoundsException
        //----------------------------------------------------------------
        try {
            l.addAll(-1, Collections.<Integer>emptyList());
            fail("Expected IndexOutOfBoundsException not thrown");
        }
        catch (UnsupportedOperationException ignored) {/* OK */}
        catch (IndexOutOfBoundsException ignored) {/* OK */}
        catch (Throwable t) { unexpected(t); }

//      equal(l instanceof Serializable,
//            l.subList(0,0) instanceof Serializable);
        if (l.subList(0,0) instanceof Serializable)
            check(l instanceof Serializable);

        equal(l instanceof RandomAccess,
              l.subList(0,0) instanceof RandomAccess);

        l.iterator();
        l.listIterator();
        l.listIterator(0);
        l.listIterator(l.size());
        THROWS(IndexOutOfBoundsException.class,
               () -> l.listIterator(-1),
               () -> l.listIterator(l.size() + 1));

        if (l instanceof AbstractList) {
            try {
                int size = l.size();
                AbstractList<Integer> abList = (AbstractList<Integer>) l;
                Method m = AbstractList.class.getDeclaredMethod("removeRange", new Class[] { int.class, int.class });
                m.setAccessible(true);
                m.invoke(abList, new Object[] { 0, 0 });
                m.invoke(abList, new Object[] { size, size });
                equal(size, l.size());
            }
            catch (UnsupportedOperationException ignored) {/* OK */}
            catch (Throwable t) { unexpected(t); }
        }

        int hashCode = 1;
        for (Integer i : l)
            hashCode = 31 * hashCode + (i == null ? 0 : i.hashCode());
        check(l.hashCode() == hashCode);

        var t = new ArrayList<>(l);
        check(t.equals(l));
        check(l.equals(t));
    }

    private static void testCollection(Collection<Integer> c) {
        try { testCollection1(c); }
        catch (Throwable t) { unexpected(t); }
    }

    private static void testCollection1(Collection<Integer> c) {

        System.out.println("\n==> " + c.getClass().getName());

        checkFunctionalInvariants(c);

        if (! supportsAdd(c)) return;
        //System.out.println("add() supported");

        if (c instanceof NavigableSet) {
            System.out.println("NavigableSet tests...");

            NavigableSet<Integer> ns = (NavigableSet<Integer>)c;
            testNavigableSet(ns);
            testNavigableSet(ns.headSet(6, false));
            testNavigableSet(ns.headSet(5, true));
            testNavigableSet(ns.tailSet(0, false));
            testNavigableSet(ns.tailSet(1, true));
            testNavigableSet(ns.subSet(0, false, 5, true));
            testNavigableSet(ns.subSet(1, true, 6, false));
        }

        if (c instanceof Queue)
            testQueue((Queue<Integer>)c);

        if (c instanceof List)
            testList((List<Integer>)c);

        if (c instanceof Set) {
            int hashCode = 0;
            for (Integer i : c)
                hashCode = hashCode + (i == null ? 0 : i.hashCode());
            check(c.hashCode() == hashCode);
        }

        check(supportsRemove(c));

        try {
            oneElement(c);
            checkFunctionalInvariants(c);
        }
        catch (Throwable t) { unexpected(t); }

        clear(c);      testNullElement(c);
        oneElement(c); testNullElement(c);

        clear(c);      testStringElement(c);
        oneElement(c); testStringElement(c);

        if (c.getClass().getName().matches(".*concurrent.*"))
            testConcurrentCollection(c);

        //----------------------------------------------------------------
        // The "all" operations should throw NPE when passed null
        //----------------------------------------------------------------
        {
            clear(c);
            try {
                c.removeAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }

            oneElement(c);
            try {
                c.removeAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }

            clear(c);
            try {
                c.retainAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }

            oneElement(c);
            try {
                c.retainAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }

            oneElement(c);
            try {
                c.addAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }

            oneElement(c);
            try {
                c.containsAll(null);
                fail("Expected NullPointerException");
            }
            catch (NullPointerException e) { pass(); }
            catch (Throwable t) { unexpected(t); }
        }
    }

    //----------------------------------------------------------------
    // Map
    //----------------------------------------------------------------
    private static void checkFunctionalInvariants(Map<Integer,Integer> m) {
        check(m.keySet().size() == m.entrySet().size());
        check(m.keySet().size() == m.size());
        checkFunctionalInvariants(m.keySet());
        checkFunctionalInvariants(m.values());
        check(m.size() != 0 ^ m.isEmpty());
        check(! m.containsKey(ABSENT_VALUE));

        if (m instanceof Serializable) {
            //System.out.printf("Serializing %s%n", m.getClass().getName());
            try {
                Object clone = serialClone(m);
                equal(m instanceof Serializable,
                      clone instanceof Serializable);
                equal(m, clone);
            } catch (Error xxx) {
                if (! (xxx.getCause() instanceof NotSerializableException))
                    throw xxx;
            }
        }
    }

    private static void testMap(Map<Integer,Integer> m) {
        System.out.println("\n==> " + m.getClass().getName());

        int hashCode = 0;
        for (var e : m.entrySet()) {
            int entryHash = (e.getKey() == null ? 0 : e.getKey().hashCode()) ^
                            (e.getValue() == null ? 0 : e.getValue().hashCode());
            check(e.hashCode() == entryHash);
            hashCode += entryHash;
        }
        check(m.hashCode() == hashCode);

        if (m instanceof ConcurrentMap)
            testConcurrentMap((ConcurrentMap<Integer,Integer>) m);

        if (m instanceof NavigableMap) {
            System.out.println("NavigableMap tests...");

            NavigableMap<Integer,Integer> nm =
                (NavigableMap<Integer,Integer>) m;
            testNavigableMapRemovers(nm);
            testNavigableMap(nm);
            testNavigableMap(nm.headMap(6, false));
            testNavigableMap(nm.headMap(5, true));
            testNavigableMap(nm.tailMap(0, false));
            testNavigableMap(nm.tailMap(1, true));
            testNavigableMap(nm.subMap(1, true, 6, false));
            testNavigableMap(nm.subMap(0, false, 5, true));
        }

        checkFunctionalInvariants(m);

        if (supportsClear(m)) {
            try { clear(m); }
            catch (Throwable t) { unexpected(t); }
        }

        if (supportsPut(m)) {
            try {
                check(m.put(3333, 77777) == null);
                check(m.put(9134, 74982) == null);
                check(m.get(9134) == 74982);
                check(m.put(9134, 1382) == 74982);
                check(m.get(9134) == 1382);
                check(m.size() == 2);
                checkFunctionalInvariants(m);
                checkNPEConsistency(m);
            }
            catch (Throwable t) { unexpected(t); }
        }
    }

    private static boolean supportsPut(Map<Integer,Integer> m) {
        // We're asking for .equals(...) semantics
        if (m instanceof IdentityHashMap) return false;

        try { check(m.put(ABSENT_VALUE,12735) == null); }
        catch (UnsupportedOperationException t) { return false; }
        catch (Throwable t) { unexpected(t); }

        try {
            check(m.containsKey(ABSENT_VALUE));
            check(m.remove(ABSENT_VALUE) != null);
        } catch (Throwable t) { unexpected(t); }
        return true;
    }

    private static boolean supportsClear(Map<?,?> m) {
        try { m.clear(); }
        catch (UnsupportedOperationException t) { return false; }
        catch (Throwable t) { unexpected(t); }
        return true;
    }

    //----------------------------------------------------------------
    // ConcurrentMap
    //----------------------------------------------------------------
    private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) {
        System.out.println("ConcurrentMap tests...");

        try {
            clear(m);

            check(m.putIfAbsent(18357,7346) == null);
            check(m.containsKey(18357));
            check(m.putIfAbsent(18357,8263) == 7346);
            try { m.putIfAbsent(18357,null); fail("NPE"); }
            catch (NullPointerException t) { }
            check(m.containsKey(18357));

            check(! m.replace(18357,8888,7777));
            check(m.containsKey(18357));
            try { m.replace(18357,null,7777); fail("NPE"); }
            catch (NullPointerException t) { }
            check(m.containsKey(18357));
            check(m.get(18357) == 7346);
            check(m.replace(18357,7346,5555));
            check(m.replace(18357,5555,7346));
            check(m.get(18357) == 7346);

            check(m.replace(92347,7834) == null);
            try { m.replace(18357,null); fail("NPE"); }
            catch (NullPointerException t) { }
            check(m.replace(18357,7346) == 7346);
            check(m.replace(18357,5555) == 7346);
            check(m.get(18357) == 5555);
            check(m.replace(18357,7346) == 5555);
            check(m.get(18357) == 7346);

            check(! m.remove(18357,9999));
            check(m.get(18357) == 7346);
            check(m.containsKey(18357));
            check(! m.remove(18357,null)); // 6272521
            check(m.get(18357) == 7346);
            check(m.remove(18357,7346));
            check(m.get(18357) == null);
            check(! m.containsKey(18357));
            check(m.isEmpty());

            m.putIfAbsent(1,2);
            check(m.size() == 1);
            check(! m.remove(1,null));
            check(! m.remove(1,null));
            check(! m.remove(1,1));
            check(m.remove(1,2));
            check(m.isEmpty());

            testEmptyMap(m);
        }
        catch (Throwable t) { unexpected(t); }
    }

    private static void throwsConsistently(Class<? extends Throwable> k,
                                           Iterable<Fun> fs) {
        List<Class<? extends Throwable>> threw = new ArrayList<>();
        for (Fun f : fs)
            try { f.f(); threw.add(null); }
            catch (Throwable t) {
                check(k.isAssignableFrom(t.getClass()));
                threw.add(t.getClass());
            }
        if (new HashSet<Object>(threw).size() != 1)
            fail(threw.toString());
    }

    private static <T> void checkNPEConsistency(final Map<T,Integer> m) {
        m.clear();
        final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap)
            ? (ConcurrentMap<T,Integer>) m
            : null;
        List<Fun> fs = new ArrayList<>();
        fs.add(() -> check(! m.containsKey(null)));
        fs.add(() -> equal(m.remove(null), null));
        fs.add(() -> equal(m.get(null), null));
        if (cm != null)
            fs.add(() -> check(! cm.remove(null,null)));
        throwsConsistently(NullPointerException.class, fs);

        fs.clear();
        final Map<T,Integer> sm = singletonMap(null,1);
        fs.add(() -> { equal(m.put(null,1), null); m.clear();});
        fs.add(() -> { m.putAll(sm); m.clear();});
        if (cm != null) {
            fs.add(() -> check(! cm.remove(null,null)));
            fs.add(() -> equal(cm.putIfAbsent(null,1), 1));
            fs.add(() -> equal(cm.replace(null,1), null));
            fs.add(() -> equal(cm.replace(null,1, 1), 1));
        }
        throwsConsistently(NullPointerException.class, fs);
    }

    //----------------------------------------------------------------
    // NavigableMap
    //----------------------------------------------------------------
    private static void
        checkNavigableMapKeys(NavigableMap<Integer,Integer> m,
                              Integer i,
                              Integer lower,
                              Integer floor,
                              Integer ceiling,
                              Integer higher) {
        equal(m.lowerKey(i),   lower);
        equal(m.floorKey(i),   floor);
        equal(m.ceilingKey(i), ceiling);
        equal(m.higherKey(i),  higher);
    }

    private static void
        checkNavigableSetKeys(NavigableSet<Integer> m,
                              Integer i,
                              Integer lower,
                              Integer floor,
                              Integer ceiling,
                              Integer higher) {
        equal(m.lower(i),   lower);
        equal(m.floor(i),   floor);
        equal(m.ceiling(i), ceiling);
        equal(m.higher(i),  higher);
    }

    static final Random rnd = new Random();
    static void equalNext(final Iterator<?> it, Object expected) {
        if (rnd.nextBoolean())
            check(it.hasNext());
        equal(it.next(), expected);
    }

    static void equalMaps(Map m1, Map m2) {
        equal(m1, m2);
        equal(m2, m1);
        equal(m1.size(), m2.size());
        equal(m1.isEmpty(), m2.isEmpty());
        equal(m1.toString(), m2.toString());
        check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray()));
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    static void testNavigableMapRemovers(NavigableMap m)
    {
        final Map emptyMap = new HashMap();

        final Map singletonMap = new HashMap();
        singletonMap.put(1, 2);

        abstract class NavigableMapView {
            abstract NavigableMap view(NavigableMap m);
        }

        NavigableMapView[] views = {
            new NavigableMapView() { NavigableMap view(NavigableMap m) {
                return m; }},
            new NavigableMapView() { NavigableMap view(NavigableMap m) {
                return m.headMap(99, true); }},
            new NavigableMapView() { NavigableMap view(NavigableMap m) {
                return m.tailMap(-99, false); }},
            new NavigableMapView() { NavigableMap view(NavigableMap m) {
                return m.subMap(-99, true, 99, false); }},
        };

        abstract class Remover {
            abstract void remove(NavigableMap m, Object k, Object v);
        }

        Remover[] removers = {
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.remove(k), v); }},

            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.descendingMap().remove(k), v); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.descendingMap().headMap(-86, false).remove(k), v); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.descendingMap().tailMap(86, true).remove(k), v); }},

            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.headMap(86, true).remove(k), v); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.tailMap(-86, true).remove(k), v); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                equal(m.subMap(-86, false, 86, true).remove(k), v); }},

            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.keySet().remove(k)); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.navigableKeySet().remove(k)); }},

            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.navigableKeySet().headSet(86, true).remove(k)); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.navigableKeySet().tailSet(-86, false).remove(k)); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.navigableKeySet().subSet(-86, true, 86, false)
                      .remove(k)); }},

            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.descendingKeySet().headSet(-86, false).remove(k)); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.descendingKeySet().tailSet(86, true).remove(k)); }},
            new Remover() { void remove(NavigableMap m, Object k, Object v) {
                check(m.descendingKeySet().subSet(86, true, -86, false)
                      .remove(k)); }},
        };

        for (NavigableMapView view : views) {
            for (Remover remover : removers) {
                try {
                    m.clear();
                    equalMaps(m, emptyMap);
                    equal(m.put(1, 2), null);
                    equalMaps(m, singletonMap);
                    NavigableMap v = view.view(m);
                    remover.remove(v, 1, 2);
                    equalMaps(m, emptyMap);
                } catch (Throwable t) { unexpected(t); }
            }
        }
    }

    private static void testNavigableMap(NavigableMap<Integer,Integer> m)
    {
        clear(m);
        checkNavigableMapKeys(m, 1, null, null, null, null);

        equal(m.put(1, 2), null);
        equal(m.put(3, 4), null);
        equal(m.put(5, 9), null);

        equal(m.put(1, 2), 2);
        equal(m.put(3, 4), 4);
        equal(m.put(5, 6), 9);

        checkNavigableMapKeys(m, 0, null, null,    1,    1);
        checkNavigableMapKeys(m, 1, null,    1,    1,    3);
        checkNavigableMapKeys(m, 2,    1,    1,    3,    3);
        checkNavigableMapKeys(m, 3,    1,    3,    3,    5);
        checkNavigableMapKeys(m, 5,    3,    5,    5, null);
        checkNavigableMapKeys(m, 6,    5,    5, null, null);

        for (final Iterator<Integer> it :
                 (Iterator<Integer>[])
                 new Iterator<?>[] {
                     m.descendingKeySet().iterator(),
                     m.navigableKeySet().descendingIterator()}) {
            equalNext(it, 5);
            equalNext(it, 3);
            equalNext(it, 1);
            check(! it.hasNext());
            THROWS(NoSuchElementException.class, () -> it.next());
        }

        {
            final Iterator<Map.Entry<Integer,Integer>> it
                = m.descendingMap().entrySet().iterator();
            check(it.hasNext()); equal(it.next().getKey(), 5);
            check(it.hasNext()); equal(it.next().getKey(), 3);
            check(it.hasNext()); equal(it.next().getKey(), 1);
            check(! it.hasNext());
            THROWS(NoSuchElementException.class, () -> it.next());
        }

        prepMapForDescItrTests(m);
        checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator());
        prepMapForDescItrTests(m);
        checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator());
        prepMapForDescItrTests(m);
        checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator());

        prepMapForDescItrTests(m);
        checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator());

        prepMapForDescItrTests(m);
        checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator());

        prepMapForDescItrTests(m);
        checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmMid(m.values(), m.descendingMap().values().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmLast(m.values(), m.descendingMap().values().iterator());

        prepMapForDescItrTests(m);
        checkDescItrRmFirst((Collection)m.entrySet(),
                            m.descendingMap().entrySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmMid((Collection)m.entrySet(),
                          m.descendingMap().entrySet().iterator());
        prepMapForDescItrTests(m);
        checkDescItrRmLast((Collection)m.entrySet(),
                           m.descendingMap().entrySet().iterator());
    }

    private static void testNavigableSet(NavigableSet<Integer> s) {
        clear(s);
        checkNavigableSetKeys(s, 1, null, null, null, null);

        check(s.add(1));
        check(s.add(3));
        check(s.add(5));

        check(! s.add(1));
        check(! s.add(3));
        check(! s.add(5));

        checkNavigableSetKeys(s, 0, null, null,    1,    1);
        checkNavigableSetKeys(s, 1, null,    1,    1,    3);
        checkNavigableSetKeys(s, 2,    1,    1,    3,    3);
        checkNavigableSetKeys(s, 3,    1,    3,    3,    5);
        checkNavigableSetKeys(s, 5,    3,    5,    5, null);
        checkNavigableSetKeys(s, 6,    5,    5, null, null);

        for (final Iterator<Integer> it :
                 (Iterator<Integer>[])
                 new Iterator<?>[] {
                     s.descendingIterator(),
                     s.descendingSet().iterator()}) {
            equalNext(it, 5);
            equalNext(it, 3);
            equalNext(it, 1);
            check(! it.hasNext());
            THROWS(NoSuchElementException.class, () -> it.next());
        }

        prepSetForDescItrTests(s);
        checkDescItrRmFirst(s, s.descendingIterator());
        prepSetForDescItrTests(s);
        checkDescItrRmMid(s, s.descendingIterator());
        prepSetForDescItrTests(s);
        checkDescItrRmLast(s, s.descendingIterator());

        prepSetForDescItrTests(s);
        checkDescItrRmFirst(s, s.descendingSet().iterator());
        prepSetForDescItrTests(s);
        checkDescItrRmMid(s, s.descendingSet().iterator());
        prepSetForDescItrTests(s);
        checkDescItrRmLast(s, s.descendingSet().iterator());
    }

    private static void prepSetForDescItrTests(Set s) {
        clear(s);
        check(s.add(1));
        check(s.add(3));
        check(s.add(5));
    }

    private static void prepMapForDescItrTests(Map m) {
        clear(m);
        equal(m.put(1, 2), null);
        equal(m.put(3, 4), null);
        equal(m.put(5, 9), null);
    }

    //--------------------------------------------------------------------
    // Check behavior of descending iterator when first element is removed
    //--------------------------------------------------------------------
    private static <T> void checkDescItrRmFirst(Collection<T> ascColl,
                                                Iterator<T> descItr) {
        T[] expected = (T[]) ascColl.toArray();
        int idx = expected.length -1;

        equalNext(descItr, expected[idx--]);
        descItr.remove();
        while (idx >= 0 && descItr.hasNext()) {
            equalNext(descItr, expected[idx--]);
        }
        equal(descItr.hasNext(), false);
        equal(idx, -1);
    }

    //-----------------------------------------------------------------------
    // Check behavior of descending iterator when a middle element is removed
    //-----------------------------------------------------------------------
    private static <T> void checkDescItrRmMid(Collection<T> ascColl,
                                              Iterator<T> descItr) {
        T[] expected = (T[]) ascColl.toArray();
        int idx = expected.length -1;

        while (idx >= expected.length / 2) {
            equalNext(descItr, expected[idx--]);
        }
        descItr.remove();
        while (idx >= 0 && descItr.hasNext()) {
            equalNext(descItr, expected[idx--]);
        }
        equal(descItr.hasNext(), false);
        equal(idx, -1);
    }

    //-----------------------------------------------------------------------
    // Check behavior of descending iterator when the last element is removed
    //-----------------------------------------------------------------------
    private static <T> void checkDescItrRmLast(Collection<T> ascColl,
                                               Iterator<T> descItr) {
        T[] expected = (T[]) ascColl.toArray();
        int idx = expected.length -1;

        while (idx >= 0 && descItr.hasNext()) {
            equalNext(descItr, expected[idx--]);
        }
        equal(idx, -1);
        equal(descItr.hasNext(), false);
        descItr.remove();
        equal(ascColl.contains(expected[0]), false);
    }

    //--------------------- Infrastructure ---------------------------
    static volatile int passed = 0, failed = 0;
    static void pass() { passed++; }
    static void fail() { failed++; Thread.dumpStack(); }
    static void fail(String msg) { System.out.println(msg); fail(); }
    static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
    static void check(boolean cond) { if (cond) pass(); else fail(); }
    static void equal(Object x, Object y) {
        if (x == null ? y == null : x.equals(y)) pass();
        else {System.out.println(x + " not equal to " + y); fail();}}
    static void equal(Object x, Object y, String msg) {
        if (x == null ? y == null : x.equals(y)) pass();
        else {System.out.println(x + " not equal to " + y + " : " + msg); fail();}}
    static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}
    public static void main(String[] args) throws Throwable {
        try { realMain(args); } catch (Throwable t) { unexpected(t); }

        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
        if (failed > 0) throw new Exception("Some tests failed");
    }
    interface Fun {void f() throws Throwable;}
    private static void THROWS(Class<? extends Throwable> k, Fun... fs) {
        for (Fun f : fs)
            try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
            catch (Throwable t) {
                if (k.isAssignableFrom(t.getClass())) pass();
                else unexpected(t);}}
    static byte[] serializedForm(Object obj) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            new ObjectOutputStream(baos).writeObject(obj);
            return baos.toByteArray();
        } catch (IOException e) { throw new Error(e); }}
    static Object readObject(byte[] bytes)
        throws IOException, ClassNotFoundException {
        InputStream is = new ByteArrayInputStream(bytes);
        return new ObjectInputStream(is).readObject();}
    @SuppressWarnings("unchecked")
    static <T> T serialClone(T obj) {
        try { return (T) readObject(serializedForm(obj)); }
        catch (Exception e) { throw new Error(e); }}
    private static class NewAbstractCollection<E> extends AbstractCollection<E> {
        ArrayList<E> list = new ArrayList<>();
        public boolean remove(Object obj) {
            return list.remove(obj);
        }
        public boolean add(E e) {
            return list.add(e);
        }
        public Iterator<E> iterator() {
            return list.iterator();
        }
        public int size() {
            return list.size();
        }
    }
    private static class NewAbstractSet<E> extends AbstractSet<E> {
        HashSet<E> set = new HashSet<>();
        public boolean remove(Object obj) {
            return set.remove(obj);
        }
        public boolean add(E e) {
            return set.add(e);
        }
        public Iterator<E> iterator() {
            return set.iterator();
        }
        public int size() {
            return set.size();
        }
    }

}
