Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/Collection/MOAT.java
38811 views
/*1* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 6207984 6272521 6192552 6269713 6197726 6260652 5073546 413746426* 4155650 4216399 4294891 6282555 6318622 6355327 6383475 642075327* 6431845 4802633 6570566 6570575 6570631 6570924 6691185 669121528* 4802647 7123424 802470929* @summary Run many tests on many Collection and Map implementations30* @author Martin Buchholz31* @run main MOAT32* @key randomness33*/3435/* Mother Of All (Collection) Tests36*37* Testing of collection classes is often spotty, because many tests38* need to be performed on many implementations, but the onus on39* writing the tests falls on the engineer introducing the new40* implementation.41*42* The idea of this mega-test is that:43*44* An engineer adding a new collection implementation could simply add45* their new implementation to a list of implementations in this46* test's main method. Any general purpose Collection<Integer> or47* Map<Integer,Integer> class is appropriate.48*49* An engineer fixing a regression could add their regression test here and50* simultaneously test all other implementations.51*/5253import java.io.*;54import java.util.*;55import java.util.concurrent.*;56import static java.util.Collections.*;5758public class MOAT {59public static void realMain(String[] args) {6061testCollection(new NewAbstractCollection<Integer>());62testCollection(new NewAbstractSet<Integer>());63testCollection(new LinkedHashSet<Integer>());64testCollection(new HashSet<Integer>());65testCollection(new Vector<Integer>());66testCollection(new Vector<Integer>().subList(0,0));67testCollection(new ArrayDeque<Integer>());68testCollection(new ArrayList<Integer>());69testCollection(new ArrayList<Integer>().subList(0,0));70testCollection(new LinkedList<Integer>());71testCollection(new LinkedList<Integer>().subList(0,0));72testCollection(new TreeSet<Integer>());73testCollection(Collections.checkedList(new ArrayList<Integer>(), Integer.class));74testCollection(Collections.synchronizedList(new ArrayList<Integer>()));75testCollection(Collections.checkedSet(new HashSet<Integer>(), Integer.class));76testCollection(Collections.checkedSortedSet(new TreeSet<Integer>(), Integer.class));77testCollection(Collections.checkedNavigableSet(new TreeSet<Integer>(), Integer.class));78testCollection(Collections.synchronizedSet(new HashSet<Integer>()));79testCollection(Collections.synchronizedSortedSet(new TreeSet<Integer>()));80testCollection(Collections.synchronizedNavigableSet(new TreeSet<Integer>()));8182testCollection(new CopyOnWriteArrayList<Integer>());83testCollection(new CopyOnWriteArrayList<Integer>().subList(0,0));84testCollection(new CopyOnWriteArraySet<Integer>());85testCollection(new PriorityQueue<Integer>());86testCollection(new PriorityBlockingQueue<Integer>());87testCollection(new ArrayBlockingQueue<Integer>(20));88testCollection(new LinkedBlockingQueue<Integer>(20));89testCollection(new LinkedBlockingDeque<Integer>(20));90testCollection(new ConcurrentLinkedDeque<Integer>());91testCollection(new ConcurrentLinkedQueue<Integer>());92testCollection(new LinkedTransferQueue<Integer>());93testCollection(new ConcurrentSkipListSet<Integer>());94testCollection(Arrays.asList(new Integer(42)));95testCollection(Arrays.asList(1,2,3));96testCollection(nCopies(25,1));97testImmutableList(nCopies(25,1));98testImmutableList(unmodifiableList(Arrays.asList(1,2,3)));99100testMap(new HashMap<Integer,Integer>());101testMap(new LinkedHashMap<Integer,Integer>());102testMap(new WeakHashMap<Integer,Integer>());103testMap(new IdentityHashMap<Integer,Integer>());104testMap(new TreeMap<Integer,Integer>());105testMap(new Hashtable<Integer,Integer>());106testMap(new ConcurrentHashMap<Integer,Integer>(10, 0.5f));107testMap(new ConcurrentSkipListMap<Integer,Integer>());108testMap(Collections.checkedMap(new HashMap<Integer,Integer>(), Integer.class, Integer.class));109testMap(Collections.checkedSortedMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));110testMap(Collections.checkedNavigableMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));111testMap(Collections.synchronizedMap(new HashMap<Integer,Integer>()));112testMap(Collections.synchronizedSortedMap(new TreeMap<Integer,Integer>()));113testMap(Collections.synchronizedNavigableMap(new TreeMap<Integer,Integer>()));114115// Empty collections116final List<Integer> emptyArray = Arrays.asList(new Integer[]{});117testCollection(emptyArray);118testEmptyList(emptyArray);119THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1));120THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1));121122List<Integer> noOne = nCopies(0,1);123testCollection(noOne);124testEmptyList(noOne);125testImmutableList(noOne);126127Set<Integer> emptySet = emptySet();128testCollection(emptySet);129testEmptySet(emptySet);130testEmptySet(EMPTY_SET);131testEmptySet(Collections.emptySet());132testEmptySet(Collections.emptySortedSet());133testEmptySet(Collections.emptyNavigableSet());134testImmutableSet(emptySet);135136List<Integer> emptyList = emptyList();137testCollection(emptyList);138testEmptyList(emptyList);139testEmptyList(EMPTY_LIST);140testEmptyList(Collections.emptyList());141testImmutableList(emptyList);142143Map<Integer,Integer> emptyMap = emptyMap();144testMap(emptyMap);145testEmptyMap(emptyMap);146testEmptyMap(EMPTY_MAP);147testEmptyMap(Collections.emptyMap());148testEmptyMap(Collections.emptySortedMap());149testEmptyMap(Collections.emptyNavigableMap());150testImmutableMap(emptyMap);151testImmutableMap(Collections.emptyMap());152testImmutableMap(Collections.emptySortedMap());153testImmutableMap(Collections.emptyNavigableMap());154155// Singleton collections156Set<Integer> singletonSet = singleton(1);157equal(singletonSet.size(), 1);158testCollection(singletonSet);159testImmutableSet(singletonSet);160161List<Integer> singletonList = singletonList(1);162equal(singletonList.size(), 1);163testCollection(singletonList);164testImmutableList(singletonList);165testImmutableList(singletonList.subList(0,1));166testImmutableList(singletonList.subList(0,1).subList(0,1));167testEmptyList(singletonList.subList(0,0));168testEmptyList(singletonList.subList(0,0).subList(0,0));169170Map<Integer,Integer> singletonMap = singletonMap(1,2);171equal(singletonMap.size(), 1);172testMap(singletonMap);173testImmutableMap(singletonMap);174}175176private static void checkContainsSelf(Collection<Integer> c) {177check(c.containsAll(c));178check(c.containsAll(Arrays.asList(c.toArray())));179check(c.containsAll(Arrays.asList(c.toArray(new Integer[0]))));180}181182private static void checkContainsEmpty(Collection<Integer> c) {183check(c.containsAll(new ArrayList<Integer>()));184}185186private static <T> void testEmptyCollection(Collection<T> c) {187check(c.isEmpty());188equal(c.size(), 0);189equal(c.toString(),"[]");190equal(c.toArray().length, 0);191equal(c.toArray(new Object[0]).length, 0);192check(c.toArray(new Object[]{42})[0] == null);193194Object[] a = new Object[1]; a[0] = Boolean.TRUE;195equal(c.toArray(a), a);196equal(a[0], null);197testEmptyIterator(c.iterator());198}199200static <T> void testEmptyIterator(final Iterator<T> it) {201if (rnd.nextBoolean())202check(! it.hasNext());203204THROWS(NoSuchElementException.class, () -> it.next());205206try { it.remove(); }207catch (IllegalStateException ignored) { pass(); }208catch (UnsupportedOperationException ignored) { pass(); }209catch (Throwable t) { unexpected(t); }210211if (rnd.nextBoolean())212check(! it.hasNext());213}214215private static void testEmptyList(List<?> c) {216testEmptyCollection(c);217equal(c.hashCode(), 1);218equal2(c, Collections.<Integer>emptyList());219}220221private static <T> void testEmptySet(Set<T> c) {222testEmptyCollection(c);223equal(c.hashCode(), 0);224equal2(c, Collections.<Integer>emptySet());225if (c instanceof NavigableSet<?>)226testEmptyIterator(((NavigableSet<T>)c).descendingIterator());227}228229private static void testImmutableCollection(final Collection<Integer> c) {230THROWS(UnsupportedOperationException.class,231() -> c.add(99),232() -> c.addAll(singleton(99)));233if (! c.isEmpty()) {234final Integer first = c.iterator().next();235THROWS(UnsupportedOperationException.class,236() -> c.clear(),237() -> c.remove(first),238() -> c.removeAll(singleton(first)),239() -> c.retainAll(emptyList()));240}241}242243private static void testImmutableSet(final Set<Integer> c) {244testImmutableCollection(c);245}246247private static void testImmutableList(final List<Integer> c) {248testList(c);249testImmutableCollection(c);250THROWS(UnsupportedOperationException.class,251() -> c.set(0,42),252() -> c.add(0,42),253() -> c.addAll(0,singleton(86)));254if (! c.isEmpty())255THROWS(UnsupportedOperationException.class,256() -> { Iterator<Integer> it = c.iterator();257it.next();258it.remove(); },259() -> { ListIterator<Integer> it = c.listIterator();260it.next();261it.remove(); });262}263264private static void clear(Collection<Integer> c) {265try { c.clear(); }266catch (Throwable t) { unexpected(t); }267testEmptyCollection(c);268}269270private static <K,V> void testEmptyMap(final Map<K,V> m) {271check(m.isEmpty());272equal(m.size(), 0);273equal(m.toString(),"{}");274testEmptySet(m.keySet());275testEmptySet(m.entrySet());276testEmptyCollection(m.values());277278try { check(! m.containsValue(null)); }279catch (NullPointerException ignored) { /* OK */ }280try { check(! m.containsKey(null)); }281catch (NullPointerException ignored) { /* OK */ }282check(! m.containsValue(1));283check(! m.containsKey(1));284}285286private static void testImmutableMap(final Map<Integer,Integer> m) {287THROWS(UnsupportedOperationException.class,288() -> m.put(1,1),289() -> m.putAll(singletonMap(1,1)));290if (! m.isEmpty()) {291final Integer first = m.keySet().iterator().next();292THROWS(UnsupportedOperationException.class,293() -> m.remove(first),294() -> m.clear());295final Map.Entry<Integer,Integer> me296= m.entrySet().iterator().next();297Integer key = me.getKey();298Integer val = me.getValue();299THROWS(UnsupportedOperationException.class,300() -> me.setValue(3));301equal(key, me.getKey());302equal(val, me.getValue());303}304testImmutableSet(m.keySet());305testImmutableCollection(m.values());306//testImmutableSet(m.entrySet());307}308309private static void clear(Map<?,?> m) {310try { m.clear(); }311catch (Throwable t) { unexpected(t); }312testEmptyMap(m);313}314315private static void oneElement(Collection<Integer> c) {316clear(c);317try {318check(c.add(-42));319equal(c.toString(), "[-42]");320if (c instanceof Set) check(! c.add(-42));321} catch (Throwable t) { unexpected(t); }322check(! c.isEmpty()); check(c.size() == 1);323}324325private static boolean supportsAdd(Collection<Integer> c) {326try { check(c.add(778347983)); }327catch (UnsupportedOperationException t) { return false; }328catch (Throwable t) { unexpected(t); }329330try {331check(c.contains(778347983));332check(c.remove(778347983));333} catch (Throwable t) { unexpected(t); }334return true;335}336337private static boolean supportsRemove(Collection<Integer> c) {338try { check(! c.remove(19134032)); }339catch (UnsupportedOperationException t) { return false; }340catch (Throwable t) { unexpected(t); }341return true;342}343344private static void checkFunctionalInvariants(Collection<Integer> c) {345try {346checkContainsSelf(c);347checkContainsEmpty(c);348check(c.size() != 0 ^ c.isEmpty());349350{351int size = 0;352for (Integer i : c) size++;353check(c.size() == size);354}355356check(c.toArray().length == c.size());357check(c.toArray().getClass() == Object[].class358||359// !!!!360// 6260652: (coll) Arrays.asList(x).toArray().getClass()361// should be Object[].class362(c.getClass().getName().equals("java.util.Arrays$ArrayList"))363);364for (int size : new int[]{0,1,c.size(), c.size()+1}) {365Integer[] a = c.toArray(new Integer[size]);366check((size > c.size()) || a.length == c.size());367int i = 0; for (Integer j : c) check(a[i++] == j);368check((size <= c.size()) || (a[c.size()] == null));369check(a.getClass() == Integer[].class);370}371372check(c.equals(c));373if (c instanceof Serializable) {374//System.out.printf("Serializing %s%n", c.getClass().getName());375try {376Object clone = serialClone(c);377equal(c instanceof Serializable,378clone instanceof Serializable);379equal(c instanceof RandomAccess,380clone instanceof RandomAccess);381if ((c instanceof List) || (c instanceof Set))382equal(c, clone);383else384equal(new HashSet<Integer>(c),385new HashSet<Integer>(serialClone(c)));386} catch (Error xxx) {387if (! (xxx.getCause() instanceof NotSerializableException))388throw xxx;389}390}391}392catch (Throwable t) { unexpected(t); }393}394395//----------------------------------------------------------------396// If add(null) succeeds, contains(null) & remove(null) should succeed397//----------------------------------------------------------------398private static void testNullElement(Collection<Integer> c) {399400try {401check(c.add(null));402if (c.size() == 1)403equal(c.toString(), "[null]");404try {405checkFunctionalInvariants(c);406check(c.contains(null));407check(c.remove(null));408}409catch (Throwable t) { unexpected(t); }410}411catch (NullPointerException e) { /* OK */ }412catch (Throwable t) { unexpected(t); }413}414415416//----------------------------------------------------------------417// If add("x") succeeds, contains("x") & remove("x") should succeed418//----------------------------------------------------------------419@SuppressWarnings("unchecked")420private static void testStringElement(Collection<Integer> c) {421Collection x = (Collection)c; // Make type-unsafe422try {423check(x.add("x"));424try {425check(x.contains("x"));426check(x.remove("x"));427} catch (Throwable t) { unexpected(t); }428}429catch (ClassCastException e) { /* OK */ }430catch (Throwable t) { unexpected(t); }431}432433private static void testConcurrentCollection(Collection<Integer> c) {434try {435c.add(1);436Iterator<Integer> it = c.iterator();437check(it.hasNext());438clear(c);439check(it.next() instanceof Integer); // No CME440check(c.isEmpty());441}442catch (Throwable t) { unexpected(t); }443}444445private static void testQueue(Queue<Integer> q) {446q.clear();447for (int i = 0; i < 5; i++) {448testQueueAddRemove(q, null);449testQueueAddRemove(q, 537);450q.add(i);451}452equal(q.size(), 5);453checkFunctionalInvariants(q);454q.poll();455equal(q.size(), 4);456checkFunctionalInvariants(q);457if ((q instanceof LinkedBlockingQueue) ||458(q instanceof LinkedBlockingDeque) ||459(q instanceof ConcurrentLinkedDeque) ||460(q instanceof ConcurrentLinkedQueue)) {461testQueueIteratorRemove(q);462}463}464465private static void testQueueAddRemove(final Queue<Integer> q,466final Integer e) {467final List<Integer> originalContents = new ArrayList<Integer>(q);468final boolean isEmpty = q.isEmpty();469final boolean isList = (q instanceof List);470final List asList = isList ? (List) q : null;471check(!q.contains(e));472try {473q.add(e);474} catch (NullPointerException npe) {475check(e == null);476return; // Null elements not supported477}478check(q.contains(e));479check(q.remove(e));480check(!q.contains(e));481equal(new ArrayList<Integer>(q), originalContents);482483if (q instanceof Deque<?>) {484final Deque<Integer> deq = (Deque<Integer>) q;485final List<Integer> singleton = Collections.singletonList(e);486487// insert, query, remove element at head488if (isEmpty) {489THROWS(NoSuchElementException.class,490() -> deq.getFirst(),491() -> deq.element(),492() -> deq.iterator().next());493check(deq.peekFirst() == null);494check(deq.peek() == null);495} else {496check(deq.getFirst() != e);497check(deq.element() != e);498check(deq.iterator().next() != e);499check(deq.peekFirst() != e);500check(deq.peek() != e);501}502check(!deq.contains(e));503check(!deq.removeFirstOccurrence(e));504check(!deq.removeLastOccurrence(e));505if (isList) {506check(asList.indexOf(e) == -1);507check(asList.lastIndexOf(e) == -1);508}509switch (rnd.nextInt(isList ? 4 : 3)) {510case 0: deq.addFirst(e); break;511case 1: check(deq.offerFirst(e)); break;512case 2: deq.push(e); break;513case 3: asList.add(0, e); break;514default: throw new AssertionError();515}516check(deq.peekFirst() == e);517check(deq.getFirst() == e);518check(deq.element() == e);519check(deq.peek() == e);520check(deq.iterator().next() == e);521check(deq.contains(e));522if (isList) {523check(asList.get(0) == e);524check(asList.indexOf(e) == 0);525check(asList.lastIndexOf(e) == 0);526check(asList.subList(0, 1).equals(singleton));527}528switch (rnd.nextInt(isList ? 11 : 9)) {529case 0: check(deq.pollFirst() == e); break;530case 1: check(deq.removeFirst() == e); break;531case 2: check(deq.remove() == e); break;532case 3: check(deq.pop() == e); break;533case 4: check(deq.removeFirstOccurrence(e)); break;534case 5: check(deq.removeLastOccurrence(e)); break;535case 6: check(deq.remove(e)); break;536case 7: check(deq.removeAll(singleton)); break;537case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;538case 9: asList.remove(0); break;539case 10: asList.subList(0, 1).clear(); break;540default: throw new AssertionError();541}542if (isEmpty) {543THROWS(NoSuchElementException.class,544() -> deq.getFirst(),545() -> deq.element(),546() -> deq.iterator().next());547check(deq.peekFirst() == null);548check(deq.peek() == null);549} else {550check(deq.getFirst() != e);551check(deq.element() != e);552check(deq.iterator().next() != e);553check(deq.peekFirst() != e);554check(deq.peek() != e);555}556check(!deq.contains(e));557check(!deq.removeFirstOccurrence(e));558check(!deq.removeLastOccurrence(e));559if (isList) {560check(isEmpty || asList.get(0) != e);561check(asList.indexOf(e) == -1);562check(asList.lastIndexOf(e) == -1);563}564equal(new ArrayList<Integer>(deq), originalContents);565566// insert, query, remove element at tail567if (isEmpty) {568check(deq.peekLast() == null);569THROWS(NoSuchElementException.class, () -> deq.getLast());570} else {571check(deq.peekLast() != e);572check(deq.getLast() != e);573}574switch (rnd.nextInt(isList ? 6 : 4)) {575case 0: deq.addLast(e); break;576case 1: check(deq.offerLast(e)); break;577case 2: check(deq.add(e)); break;578case 3: deq.addAll(singleton); break;579case 4: asList.addAll(deq.size(), singleton); break;580case 5: asList.add(deq.size(), e); break;581default: throw new AssertionError();582}583check(deq.peekLast() == e);584check(deq.getLast() == e);585check(deq.contains(e));586if (isList) {587ListIterator it = asList.listIterator(asList.size());588check(it.previous() == e);589check(asList.get(asList.size() - 1) == e);590check(asList.indexOf(e) == asList.size() - 1);591check(asList.lastIndexOf(e) == asList.size() - 1);592int size = asList.size();593check(asList.subList(size - 1, size).equals(singleton));594}595switch (rnd.nextInt(isList ? 8 : 6)) {596case 0: check(deq.pollLast() == e); break;597case 1: check(deq.removeLast() == e); break;598case 2: check(deq.removeFirstOccurrence(e)); break;599case 3: check(deq.removeLastOccurrence(e)); break;600case 4: check(deq.remove(e)); break;601case 5: check(deq.removeAll(singleton)); break;602case 6: asList.remove(asList.size() - 1); break;603case 7:604ListIterator it = asList.listIterator(asList.size());605it.previous();606it.remove();607break;608default: throw new AssertionError();609}610if (isEmpty) {611check(deq.peekLast() == null);612THROWS(NoSuchElementException.class, () -> deq.getLast());613} else {614check(deq.peekLast() != e);615check(deq.getLast() != e);616}617check(!deq.contains(e));618equal(new ArrayList<Integer>(deq), originalContents);619620// Test operations on empty deque621switch (rnd.nextInt(isList ? 4 : 2)) {622case 0: deq.clear(); break;623case 1:624Iterator it = deq.iterator();625while (it.hasNext()) {626it.next();627it.remove();628}629break;630case 2: asList.subList(0, asList.size()).clear(); break;631case 3:632ListIterator lit = asList.listIterator(asList.size());633while (lit.hasPrevious()) {634lit.previous();635lit.remove();636}637break;638default: throw new AssertionError();639}640testEmptyCollection(deq);641check(!deq.iterator().hasNext());642if (isList) {643check(!asList.listIterator().hasPrevious());644THROWS(NoSuchElementException.class,645() -> asList.listIterator().previous());646}647THROWS(NoSuchElementException.class,648() -> deq.iterator().next(),649() -> deq.element(),650() -> deq.getFirst(),651() -> deq.getLast(),652() -> deq.pop(),653() -> deq.remove(),654() -> deq.removeFirst(),655() -> deq.removeLast());656657check(deq.poll() == null);658check(deq.pollFirst() == null);659check(deq.pollLast() == null);660check(deq.peek() == null);661check(deq.peekFirst() == null);662check(deq.peekLast() == null);663check(!deq.removeFirstOccurrence(e));664check(!deq.removeLastOccurrence(e));665666check(deq.addAll(originalContents) == !isEmpty);667equal(new ArrayList<Integer>(deq), originalContents);668check(!deq.addAll(Collections.<Integer>emptyList()));669equal(new ArrayList<Integer>(deq), originalContents);670}671}672673private static void testQueueIteratorRemove(Queue<Integer> q) {674System.err.printf("testQueueIteratorRemove %s%n",675q.getClass().getSimpleName());676q.clear();677for (int i = 0; i < 5; i++)678q.add(i);679Iterator<Integer> it = q.iterator();680check(it.hasNext());681for (int i = 3; i >= 0; i--)682q.remove(i);683equal(it.next(), 0);684equal(it.next(), 4);685686q.clear();687for (int i = 0; i < 5; i++)688q.add(i);689it = q.iterator();690equal(it.next(), 0);691check(it.hasNext());692for (int i = 1; i < 4; i++)693q.remove(i);694equal(it.next(), 1);695equal(it.next(), 4);696}697698private static void testList(final List<Integer> l) {699//----------------------------------------------------------------700// 4802633: (coll) AbstractList.addAll(-1,emptyCollection)701// doesn't throw IndexOutOfBoundsException702//----------------------------------------------------------------703try {704l.addAll(-1, Collections.<Integer>emptyList());705fail("Expected IndexOutOfBoundsException not thrown");706}707catch (UnsupportedOperationException ignored) {/* OK */}708catch (IndexOutOfBoundsException ignored) {/* OK */}709catch (Throwable t) { unexpected(t); }710711// equal(l instanceof Serializable,712// l.subList(0,0) instanceof Serializable);713if (l.subList(0,0) instanceof Serializable)714check(l instanceof Serializable);715716equal(l instanceof RandomAccess,717l.subList(0,0) instanceof RandomAccess);718}719720private static void testCollection(Collection<Integer> c) {721try { testCollection1(c); }722catch (Throwable t) { unexpected(t); }723}724725private static void testCollection1(Collection<Integer> c) {726727System.out.println("\n==> " + c.getClass().getName());728729checkFunctionalInvariants(c);730731if (! supportsAdd(c)) return;732//System.out.println("add() supported");733734if (c instanceof NavigableSet) {735System.out.println("NavigableSet tests...");736737NavigableSet<Integer> ns = (NavigableSet<Integer>)c;738testNavigableSet(ns);739testNavigableSet(ns.headSet(6, false));740testNavigableSet(ns.headSet(5, true));741testNavigableSet(ns.tailSet(0, false));742testNavigableSet(ns.tailSet(1, true));743testNavigableSet(ns.subSet(0, false, 5, true));744testNavigableSet(ns.subSet(1, true, 6, false));745}746747if (c instanceof Queue)748testQueue((Queue<Integer>)c);749750if (c instanceof List)751testList((List<Integer>)c);752753check(supportsRemove(c));754755try {756oneElement(c);757checkFunctionalInvariants(c);758}759catch (Throwable t) { unexpected(t); }760761clear(c); testNullElement(c);762oneElement(c); testNullElement(c);763764clear(c); testStringElement(c);765oneElement(c); testStringElement(c);766767if (c.getClass().getName().matches(".*concurrent.*"))768testConcurrentCollection(c);769770//----------------------------------------------------------------771// The "all" operations should throw NPE when passed null772//----------------------------------------------------------------773{774clear(c);775try {776c.removeAll(null);777fail("Expected NullPointerException");778}779catch (NullPointerException e) { pass(); }780catch (Throwable t) { unexpected(t); }781782oneElement(c);783try {784c.removeAll(null);785fail("Expected NullPointerException");786}787catch (NullPointerException e) { pass(); }788catch (Throwable t) { unexpected(t); }789790clear(c);791try {792c.retainAll(null);793fail("Expected NullPointerException");794}795catch (NullPointerException e) { pass(); }796catch (Throwable t) { unexpected(t); }797798oneElement(c);799try {800c.retainAll(null);801fail("Expected NullPointerException");802}803catch (NullPointerException e) { pass(); }804catch (Throwable t) { unexpected(t); }805806oneElement(c);807try {808c.addAll(null);809fail("Expected NullPointerException");810}811catch (NullPointerException e) { pass(); }812catch (Throwable t) { unexpected(t); }813814oneElement(c);815try {816c.containsAll(null);817fail("Expected NullPointerException");818}819catch (NullPointerException e) { pass(); }820catch (Throwable t) { unexpected(t); }821}822}823824//----------------------------------------------------------------825// Map826//----------------------------------------------------------------827private static void checkFunctionalInvariants(Map<Integer,Integer> m) {828check(m.keySet().size() == m.entrySet().size());829check(m.keySet().size() == m.size());830checkFunctionalInvariants(m.keySet());831checkFunctionalInvariants(m.values());832check(m.size() != 0 ^ m.isEmpty());833}834835private static void testMap(Map<Integer,Integer> m) {836System.out.println("\n==> " + m.getClass().getName());837838if (m instanceof ConcurrentMap)839testConcurrentMap((ConcurrentMap<Integer,Integer>) m);840841if (m instanceof NavigableMap) {842System.out.println("NavigableMap tests...");843844NavigableMap<Integer,Integer> nm =845(NavigableMap<Integer,Integer>) m;846testNavigableMapRemovers(nm);847testNavigableMap(nm);848testNavigableMap(nm.headMap(6, false));849testNavigableMap(nm.headMap(5, true));850testNavigableMap(nm.tailMap(0, false));851testNavigableMap(nm.tailMap(1, true));852testNavigableMap(nm.subMap(1, true, 6, false));853testNavigableMap(nm.subMap(0, false, 5, true));854}855856checkFunctionalInvariants(m);857858if (supportsClear(m)) {859try { clear(m); }860catch (Throwable t) { unexpected(t); }861}862863if (supportsPut(m)) {864try {865check(m.put(3333, 77777) == null);866check(m.put(9134, 74982) == null);867check(m.get(9134) == 74982);868check(m.put(9134, 1382) == 74982);869check(m.get(9134) == 1382);870check(m.size() == 2);871checkFunctionalInvariants(m);872checkNPEConsistency(m);873}874catch (Throwable t) { unexpected(t); }875}876}877878private static boolean supportsPut(Map<Integer,Integer> m) {879// We're asking for .equals(...) semantics880if (m instanceof IdentityHashMap) return false;881882try { check(m.put(778347983,12735) == null); }883catch (UnsupportedOperationException t) { return false; }884catch (Throwable t) { unexpected(t); }885886try {887check(m.containsKey(778347983));888check(m.remove(778347983) != null);889} catch (Throwable t) { unexpected(t); }890return true;891}892893private static boolean supportsClear(Map<?,?> m) {894try { m.clear(); }895catch (UnsupportedOperationException t) { return false; }896catch (Throwable t) { unexpected(t); }897return true;898}899900//----------------------------------------------------------------901// ConcurrentMap902//----------------------------------------------------------------903private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) {904System.out.println("ConcurrentMap tests...");905906try {907clear(m);908909check(m.putIfAbsent(18357,7346) == null);910check(m.containsKey(18357));911check(m.putIfAbsent(18357,8263) == 7346);912try { m.putIfAbsent(18357,null); fail("NPE"); }913catch (NullPointerException t) { }914check(m.containsKey(18357));915916check(! m.replace(18357,8888,7777));917check(m.containsKey(18357));918try { m.replace(18357,null,7777); fail("NPE"); }919catch (NullPointerException t) { }920check(m.containsKey(18357));921check(m.get(18357) == 7346);922check(m.replace(18357,7346,5555));923check(m.replace(18357,5555,7346));924check(m.get(18357) == 7346);925926check(m.replace(92347,7834) == null);927try { m.replace(18357,null); fail("NPE"); }928catch (NullPointerException t) { }929check(m.replace(18357,7346) == 7346);930check(m.replace(18357,5555) == 7346);931check(m.get(18357) == 5555);932check(m.replace(18357,7346) == 5555);933check(m.get(18357) == 7346);934935check(! m.remove(18357,9999));936check(m.get(18357) == 7346);937check(m.containsKey(18357));938check(! m.remove(18357,null)); // 6272521939check(m.get(18357) == 7346);940check(m.remove(18357,7346));941check(m.get(18357) == null);942check(! m.containsKey(18357));943check(m.isEmpty());944945m.putIfAbsent(1,2);946check(m.size() == 1);947check(! m.remove(1,null));948check(! m.remove(1,null));949check(! m.remove(1,1));950check(m.remove(1,2));951check(m.isEmpty());952953testEmptyMap(m);954}955catch (Throwable t) { unexpected(t); }956}957958private static void throwsConsistently(Class<? extends Throwable> k,959Iterable<Fun> fs) {960List<Class<? extends Throwable>> threw961= new ArrayList<Class<? extends Throwable>>();962for (Fun f : fs)963try { f.f(); threw.add(null); }964catch (Throwable t) {965check(k.isAssignableFrom(t.getClass()));966threw.add(t.getClass());967}968if (new HashSet<Object>(threw).size() != 1)969fail(threw.toString());970}971972private static <T> void checkNPEConsistency(final Map<T,Integer> m) {973m.clear();974final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap)975? (ConcurrentMap<T,Integer>) m976: null;977List<Fun> fs = new ArrayList<Fun>();978fs.add(() -> check(! m.containsKey(null)));979fs.add(() -> equal(m.remove(null), null));980fs.add(() -> equal(m.get(null), null));981if (cm != null)982fs.add(() -> check(! cm.remove(null,null)));983throwsConsistently(NullPointerException.class, fs);984985fs.clear();986final Map<T,Integer> sm = singletonMap(null,1);987fs.add(() -> { equal(m.put(null,1), null); m.clear();});988fs.add(() -> { m.putAll(sm); m.clear();});989if (cm != null) {990fs.add(() -> check(! cm.remove(null,null)));991fs.add(() -> equal(cm.putIfAbsent(null,1), 1));992fs.add(() -> equal(cm.replace(null,1), null));993fs.add(() -> equal(cm.replace(null,1, 1), 1));994}995throwsConsistently(NullPointerException.class, fs);996}997998//----------------------------------------------------------------999// NavigableMap1000//----------------------------------------------------------------1001private static void1002checkNavigableMapKeys(NavigableMap<Integer,Integer> m,1003Integer i,1004Integer lower,1005Integer floor,1006Integer ceiling,1007Integer higher) {1008equal(m.lowerKey(i), lower);1009equal(m.floorKey(i), floor);1010equal(m.ceilingKey(i), ceiling);1011equal(m.higherKey(i), higher);1012}10131014private static void1015checkNavigableSetKeys(NavigableSet<Integer> m,1016Integer i,1017Integer lower,1018Integer floor,1019Integer ceiling,1020Integer higher) {1021equal(m.lower(i), lower);1022equal(m.floor(i), floor);1023equal(m.ceiling(i), ceiling);1024equal(m.higher(i), higher);1025}10261027static final Random rnd = new Random();1028static void equalNext(final Iterator<?> it, Object expected) {1029if (rnd.nextBoolean())1030check(it.hasNext());1031equal(it.next(), expected);1032}10331034static void equalMaps(Map m1, Map m2) {1035equal(m1, m2);1036equal(m2, m1);1037equal(m1.size(), m2.size());1038equal(m1.isEmpty(), m2.isEmpty());1039equal(m1.toString(), m2.toString());1040check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray()));1041}10421043@SuppressWarnings({"unchecked", "rawtypes"})1044static void testNavigableMapRemovers(NavigableMap m)1045{1046final Map emptyMap = new HashMap();10471048final Map singletonMap = new HashMap();1049singletonMap.put(1, 2);10501051abstract class NavigableMapView {1052abstract NavigableMap view(NavigableMap m);1053}10541055NavigableMapView[] views = {1056new NavigableMapView() { NavigableMap view(NavigableMap m) {1057return m; }},1058new NavigableMapView() { NavigableMap view(NavigableMap m) {1059return m.headMap(99, true); }},1060new NavigableMapView() { NavigableMap view(NavigableMap m) {1061return m.tailMap(-99, false); }},1062new NavigableMapView() { NavigableMap view(NavigableMap m) {1063return m.subMap(-99, true, 99, false); }},1064};10651066abstract class Remover {1067abstract void remove(NavigableMap m, Object k, Object v);1068}10691070Remover[] removers = {1071new Remover() { void remove(NavigableMap m, Object k, Object v) {1072equal(m.remove(k), v); }},10731074new Remover() { void remove(NavigableMap m, Object k, Object v) {1075equal(m.descendingMap().remove(k), v); }},1076new Remover() { void remove(NavigableMap m, Object k, Object v) {1077equal(m.descendingMap().headMap(-86, false).remove(k), v); }},1078new Remover() { void remove(NavigableMap m, Object k, Object v) {1079equal(m.descendingMap().tailMap(86, true).remove(k), v); }},10801081new Remover() { void remove(NavigableMap m, Object k, Object v) {1082equal(m.headMap(86, true).remove(k), v); }},1083new Remover() { void remove(NavigableMap m, Object k, Object v) {1084equal(m.tailMap(-86, true).remove(k), v); }},1085new Remover() { void remove(NavigableMap m, Object k, Object v) {1086equal(m.subMap(-86, false, 86, true).remove(k), v); }},10871088new Remover() { void remove(NavigableMap m, Object k, Object v) {1089check(m.keySet().remove(k)); }},1090new Remover() { void remove(NavigableMap m, Object k, Object v) {1091check(m.navigableKeySet().remove(k)); }},10921093new Remover() { void remove(NavigableMap m, Object k, Object v) {1094check(m.navigableKeySet().headSet(86, true).remove(k)); }},1095new Remover() { void remove(NavigableMap m, Object k, Object v) {1096check(m.navigableKeySet().tailSet(-86, false).remove(k)); }},1097new Remover() { void remove(NavigableMap m, Object k, Object v) {1098check(m.navigableKeySet().subSet(-86, true, 86, false)1099.remove(k)); }},11001101new Remover() { void remove(NavigableMap m, Object k, Object v) {1102check(m.descendingKeySet().headSet(-86, false).remove(k)); }},1103new Remover() { void remove(NavigableMap m, Object k, Object v) {1104check(m.descendingKeySet().tailSet(86, true).remove(k)); }},1105new Remover() { void remove(NavigableMap m, Object k, Object v) {1106check(m.descendingKeySet().subSet(86, true, -86, false)1107.remove(k)); }},1108};11091110for (NavigableMapView view : views) {1111for (Remover remover : removers) {1112try {1113m.clear();1114equalMaps(m, emptyMap);1115equal(m.put(1, 2), null);1116equalMaps(m, singletonMap);1117NavigableMap v = view.view(m);1118remover.remove(v, 1, 2);1119equalMaps(m, emptyMap);1120} catch (Throwable t) { unexpected(t); }1121}1122}1123}11241125private static void testNavigableMap(NavigableMap<Integer,Integer> m)1126{1127clear(m);1128checkNavigableMapKeys(m, 1, null, null, null, null);11291130equal(m.put(1, 2), null);1131equal(m.put(3, 4), null);1132equal(m.put(5, 9), null);11331134equal(m.put(1, 2), 2);1135equal(m.put(3, 4), 4);1136equal(m.put(5, 6), 9);11371138checkNavigableMapKeys(m, 0, null, null, 1, 1);1139checkNavigableMapKeys(m, 1, null, 1, 1, 3);1140checkNavigableMapKeys(m, 2, 1, 1, 3, 3);1141checkNavigableMapKeys(m, 3, 1, 3, 3, 5);1142checkNavigableMapKeys(m, 5, 3, 5, 5, null);1143checkNavigableMapKeys(m, 6, 5, 5, null, null);11441145for (final Iterator<Integer> it :1146(Iterator<Integer>[])1147new Iterator<?>[] {1148m.descendingKeySet().iterator(),1149m.navigableKeySet().descendingIterator()}) {1150equalNext(it, 5);1151equalNext(it, 3);1152equalNext(it, 1);1153check(! it.hasNext());1154THROWS(NoSuchElementException.class, () -> it.next());1155}11561157{1158final Iterator<Map.Entry<Integer,Integer>> it1159= m.descendingMap().entrySet().iterator();1160check(it.hasNext()); equal(it.next().getKey(), 5);1161check(it.hasNext()); equal(it.next().getKey(), 3);1162check(it.hasNext()); equal(it.next().getKey(), 1);1163check(! it.hasNext());1164THROWS(NoSuchElementException.class, () -> it.next());1165}11661167prepMapForDescItrTests(m);1168checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator());1169prepMapForDescItrTests(m);1170checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator());1171prepMapForDescItrTests(m);1172checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator());11731174prepMapForDescItrTests(m);1175checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator());1176prepMapForDescItrTests(m);1177checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator());1178prepMapForDescItrTests(m);1179checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator());11801181prepMapForDescItrTests(m);1182checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator());1183prepMapForDescItrTests(m);1184checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator());1185prepMapForDescItrTests(m);1186checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator());11871188prepMapForDescItrTests(m);1189checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator());1190prepMapForDescItrTests(m);1191checkDescItrRmMid(m.values(), m.descendingMap().values().iterator());1192prepMapForDescItrTests(m);1193checkDescItrRmLast(m.values(), m.descendingMap().values().iterator());11941195prepMapForDescItrTests(m);1196checkDescItrRmFirst((Collection)m.entrySet(),1197m.descendingMap().entrySet().iterator());1198prepMapForDescItrTests(m);1199checkDescItrRmMid((Collection)m.entrySet(),1200m.descendingMap().entrySet().iterator());1201prepMapForDescItrTests(m);1202checkDescItrRmLast((Collection)m.entrySet(),1203m.descendingMap().entrySet().iterator());1204}12051206private static void testNavigableSet(NavigableSet<Integer> s) {1207clear(s);1208checkNavigableSetKeys(s, 1, null, null, null, null);12091210check(s.add(1));1211check(s.add(3));1212check(s.add(5));12131214check(! s.add(1));1215check(! s.add(3));1216check(! s.add(5));12171218checkNavigableSetKeys(s, 0, null, null, 1, 1);1219checkNavigableSetKeys(s, 1, null, 1, 1, 3);1220checkNavigableSetKeys(s, 2, 1, 1, 3, 3);1221checkNavigableSetKeys(s, 3, 1, 3, 3, 5);1222checkNavigableSetKeys(s, 5, 3, 5, 5, null);1223checkNavigableSetKeys(s, 6, 5, 5, null, null);12241225for (final Iterator<Integer> it :1226(Iterator<Integer>[])1227new Iterator<?>[] {1228s.descendingIterator(),1229s.descendingSet().iterator()}) {1230equalNext(it, 5);1231equalNext(it, 3);1232equalNext(it, 1);1233check(! it.hasNext());1234THROWS(NoSuchElementException.class, () -> it.next());1235}12361237prepSetForDescItrTests(s);1238checkDescItrRmFirst(s, s.descendingIterator());1239prepSetForDescItrTests(s);1240checkDescItrRmMid(s, s.descendingIterator());1241prepSetForDescItrTests(s);1242checkDescItrRmLast(s, s.descendingIterator());12431244prepSetForDescItrTests(s);1245checkDescItrRmFirst(s, s.descendingSet().iterator());1246prepSetForDescItrTests(s);1247checkDescItrRmMid(s, s.descendingSet().iterator());1248prepSetForDescItrTests(s);1249checkDescItrRmLast(s, s.descendingSet().iterator());1250}12511252private static void prepSetForDescItrTests(Set s) {1253clear(s);1254check(s.add(1));1255check(s.add(3));1256check(s.add(5));1257}12581259private static void prepMapForDescItrTests(Map m) {1260clear(m);1261equal(m.put(1, 2), null);1262equal(m.put(3, 4), null);1263equal(m.put(5, 9), null);1264}12651266//--------------------------------------------------------------------1267// Check behavior of descending iterator when first element is removed1268//--------------------------------------------------------------------1269private static <T> void checkDescItrRmFirst(Collection<T> ascColl,1270Iterator<T> descItr) {1271T[] expected = (T[]) ascColl.toArray();1272int idx = expected.length -1;12731274equalNext(descItr, expected[idx--]);1275descItr.remove();1276while(idx >= 0 && descItr.hasNext()) {1277equalNext(descItr, expected[idx--]);1278}1279equal(descItr.hasNext(), false);1280equal(idx, -1);1281}12821283//-----------------------------------------------------------------------1284// Check behavior of descending iterator when a middle element is removed1285//-----------------------------------------------------------------------1286private static <T> void checkDescItrRmMid(Collection<T> ascColl,1287Iterator<T> descItr) {1288T[] expected = (T[]) ascColl.toArray();1289int idx = expected.length -1;12901291while (idx >= expected.length / 2) {1292equalNext(descItr, expected[idx--]);1293}1294descItr.remove();1295while (idx >= 0 && descItr.hasNext()) {1296equalNext(descItr, expected[idx--]);1297}1298equal(descItr.hasNext(), false);1299equal(idx, -1);1300}13011302//-----------------------------------------------------------------------1303// Check behavior of descending iterator when the last element is removed1304//-----------------------------------------------------------------------1305private static <T> void checkDescItrRmLast(Collection<T> ascColl,1306Iterator<T> descItr) {1307T[] expected = (T[]) ascColl.toArray();1308int idx = expected.length -1;13091310while (idx >= 0 && descItr.hasNext()) {1311equalNext(descItr, expected[idx--]);1312}1313equal(idx, -1);1314equal(descItr.hasNext(), false);1315descItr.remove();1316equal(ascColl.contains(expected[0]), false);1317}13181319//--------------------- Infrastructure ---------------------------1320static volatile int passed = 0, failed = 0;1321static void pass() { passed++; }1322static void fail() { failed++; Thread.dumpStack(); }1323static void fail(String msg) { System.out.println(msg); fail(); }1324static void unexpected(Throwable t) { failed++; t.printStackTrace(); }1325static void check(boolean cond) { if (cond) pass(); else fail(); }1326static void equal(Object x, Object y) {1327if (x == null ? y == null : x.equals(y)) pass();1328else {System.out.println(x + " not equal to " + y); fail();}}1329static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}1330public static void main(String[] args) throws Throwable {1331try { realMain(args); } catch (Throwable t) { unexpected(t); }13321333System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);1334if (failed > 0) throw new Exception("Some tests failed");1335}1336interface Fun {void f() throws Throwable;}1337private static void THROWS(Class<? extends Throwable> k, Fun... fs) {1338for (Fun f : fs)1339try { f.f(); fail("Expected " + k.getName() + " not thrown"); }1340catch (Throwable t) {1341if (k.isAssignableFrom(t.getClass())) pass();1342else unexpected(t);}}1343static byte[] serializedForm(Object obj) {1344try {1345ByteArrayOutputStream baos = new ByteArrayOutputStream();1346new ObjectOutputStream(baos).writeObject(obj);1347return baos.toByteArray();1348} catch (IOException e) { throw new Error(e); }}1349static Object readObject(byte[] bytes)1350throws IOException, ClassNotFoundException {1351InputStream is = new ByteArrayInputStream(bytes);1352return new ObjectInputStream(is).readObject();}1353@SuppressWarnings("unchecked")1354static <T> T serialClone(T obj) {1355try { return (T) readObject(serializedForm(obj)); }1356catch (Exception e) { throw new Error(e); }}1357private static class NewAbstractCollection<E> extends AbstractCollection<E> {1358ArrayList<E> list = new ArrayList<>();1359public boolean remove(Object obj) {1360return list.remove(obj);1361}1362public boolean add(E e) {1363return list.add(e);1364}1365public Iterator<E> iterator() {1366return list.iterator();1367}1368public int size() {1369return list.size();1370}1371}1372private static class NewAbstractSet<E> extends AbstractSet<E> {1373HashSet<E> set = new HashSet<>();1374public boolean remove(Object obj) {1375return set.remove(obj);1376}1377public boolean add(E e) {1378return set.add(e);1379}1380public Iterator<E> iterator() {1381return set.iterator();1382}1383public int size() {1384return set.size();1385}1386}13871388}138913901391