Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/util/NavigableMap/LockStep.java
40083 views
/*1* Copyright (c) 2006, 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 6420753 6242436 669118526* @summary Compare NavigableMap implementations for identical behavior27* @run main LockStep28* @run main/othervm -XX:+AggressiveOpts LockStep29* @run main/othervm -XX:+AggressiveOpts -Dthorough=true LockStep30* @author Martin Buchholz31* @key randomness32*/3334import java.io.*;35import java.util.*;36import java.util.concurrent.*;37import static java.util.Collections.*;3839@SuppressWarnings("unchecked")40public class LockStep {41static final int DEFAULT_SIZE = 5;42static int size; // Running time is O(size**2)4344static int intArg(String[] args, int i, int defaultValue) {45return args.length > i ? Integer.parseInt(args[i]) : defaultValue;46}4748// Pass -Dthorough=true for more exhaustive testing49static final boolean thorough = Boolean.getBoolean("thorough");5051static boolean maybe(int n) { return rnd.nextInt(n) == 0; }5253static void realMain(String[] args) {54size = intArg(args, 0, DEFAULT_SIZE);5556lockSteps(new TreeMap(),57new ConcurrentSkipListMap());58lockSteps(new TreeMap(),59Collections.checkedNavigableMap(new TreeMap(), Integer.class, Integer.class));60lockSteps(new TreeMap(),61Collections.synchronizedNavigableMap(new TreeMap()));62lockSteps(new TreeMap(reverseOrder()),63new ConcurrentSkipListMap(reverseOrder()));6465lockSteps(new TreeSet(),66new ConcurrentSkipListSet());67lockSteps(new TreeSet(),68Collections.checkedNavigableSet(new TreeSet(), Integer.class));69lockSteps(new TreeSet(),70Collections.synchronizedNavigableSet(new TreeSet()));71lockSteps(new TreeSet(reverseOrder()),72new ConcurrentSkipListSet(reverseOrder()));73}7475static void lockSteps(NavigableMap m1, NavigableMap m2) {76if (maybe(4)) m1 = serialClone(m1);77if (maybe(4)) m2 = serialClone(m2);78lockStep(m1,79m2);80lockStep(m1.descendingMap(),81m2.descendingMap());82lockStep(fullSubMap(m1),83fullSubMap(m2));84lockStep(fullSubMap(m1.descendingMap()),85fullSubMap(m2.descendingMap()));86lockStep(fullHeadMap(m1),87fullHeadMap(m2));88lockStep(fullHeadMap(m1.descendingMap()),89fullHeadMap(m2.descendingMap()));90lockStep(fullTailMap(m1),91fullTailMap(m2));92lockStep(fullTailMap(m1.descendingMap()),93fullTailMap(m2.descendingMap()));94}9596static void lockSteps(NavigableSet s1, NavigableSet s2) {97if (maybe(4)) s1 = serialClone(s1);98if (maybe(4)) s2 = serialClone(s2);99lockStep(s1,100s2);101lockStep(s1.descendingSet(),102s2.descendingSet());103lockStep(fullSubSet(s1),104fullSubSet(s2));105lockStep(fullSubSet(s1.descendingSet()),106fullSubSet(s2.descendingSet()));107lockStep(fullHeadSet(s1),108fullHeadSet(s2));109lockStep(fullHeadSet(s1.descendingSet()),110fullHeadSet(s2.descendingSet()));111lockStep(fullTailSet(s1),112fullTailSet(s2));113lockStep(fullTailSet(s1.descendingSet()),114fullTailSet(s2.descendingSet()));115}116117static boolean isAscending(NavigableMap m) {118Comparator cmp = m.comparator();119return (cmp == null || cmp.compare(1, 2) < 0);120}121122static NavigableMap fullSubMap(NavigableMap m) {123return isAscending(m)124? m.subMap(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true)125: m.subMap(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true);126}127128static NavigableMap fullHeadMap(NavigableMap m) {129return isAscending(m)130? m.headMap(Integer.MAX_VALUE, true)131: m.headMap(Integer.MIN_VALUE, true);132}133134static NavigableMap fullTailMap(NavigableMap m) {135return isAscending(m)136? m.tailMap(Integer.MIN_VALUE, true)137: m.tailMap(Integer.MAX_VALUE, true);138}139140static boolean isAscending(NavigableSet s) {141Comparator cmp = s.comparator();142return (cmp == null || cmp.compare(1, 2) < 0);143}144145static NavigableSet fullSubSet(NavigableSet s) {146return isAscending(s)147? s.subSet(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true)148: s.subSet(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true);149}150151static NavigableSet fullHeadSet(NavigableSet s) {152return isAscending(s)153? s.headSet(Integer.MAX_VALUE, true)154: s.headSet(Integer.MIN_VALUE, true);155}156157static NavigableSet fullTailSet(NavigableSet s) {158return isAscending(s)159? s.tailSet(Integer.MIN_VALUE, true)160: s.tailSet(Integer.MAX_VALUE, true);161}162163static void testEmptyCollection(Collection<?> c) {164check(c.isEmpty());165equal(c.size(), 0);166equal(c.toString(),"[]");167equal(c.toArray().length, 0);168equal(c.toArray(new Object[0]).length, 0);169170Object[] a = new Object[1]; a[0] = Boolean.TRUE;171equal(c.toArray(a), a);172equal(a[0], null);173check(! c.iterator().hasNext());174}175176static void testEmptySet(Set<?> c) {177testEmptyCollection(c);178equal(c.hashCode(), 0);179equal2(c, Collections.<Integer>emptySet());180}181182static void testEmptyMap(final Map<?,?> m) {183check(m.isEmpty());184equal(m.size(), 0);185equal(m.toString(),"{}");186equal(m.hashCode(), 0);187testEmptySet(m.keySet());188testEmptySet(m.entrySet());189testEmptyCollection(m.values());190}191192static final Random rnd;193194static {195// sufficiently random for this test196long seed = System.nanoTime();197System.out.println(LockStep.class.getCanonicalName() + ": Trial random seed: " + seed );198199rnd = new Random(seed);200}201202static void equalNext(final Iterator<?> it, Object expected) {203if (maybe(2))204check(it.hasNext());205equal(it.next(), expected);206}207208static Comparator comparator(NavigableSet s) {209Comparator cmp = s.comparator();210return cmp != null ? cmp : new Comparator() {211public int compare(Object o1, Object o2) {212return ((Comparable) o1).compareTo(o2); }};213}214215static Comparator comparator(NavigableMap m) {216Comparator cmp = m.comparator();217return cmp != null ? cmp : new Comparator() {218public int compare(Object o1, Object o2) {219return ((Comparable) o1).compareTo(o2); }};220}221222static void checkNavigableSet(final NavigableSet s) {223if (s.comparator() == null)224check(s.descendingSet().descendingSet().comparator() == null);225equal(s.isEmpty(), s.size() == 0);226equal2(s, s.descendingSet());227if (maybe(4) && s instanceof Serializable) {228try {229equal2(s, serialClone(s));230} catch(RuntimeException uhoh) {231if(!(uhoh.getCause() instanceof NotSerializableException)) {232throw uhoh;233}234}235}236Comparator cmp = comparator(s);237if (s.isEmpty()) {238THROWS(NoSuchElementException.class,239() -> s.first(),240() -> s.last());241equal(null, s.lower(1));242equal(null, s.floor(1));243equal(null, s.ceiling(1));244equal(null, s.higher(1));245} else {246Object a = s.first();247Object z = s.last();248equal(s.lower(a), null);249equal(s.higher(z), null);250equal2(s, s.tailSet(a));251equal2(s, s.headSet(z, true));252equal2(s, s.subSet(a, true, z, true));253254testEmptySet(s.subSet(a, true, a, false));255testEmptySet(s.subSet(z, true, z, false));256testEmptySet(s.headSet(a, false));257testEmptySet(s.tailSet(z, false));258259equal2(s.headSet(a, true), singleton(a));260equal2(s.tailSet(z, true), singleton(z));261}262Iterator[] its = new Iterator[] {263s.iterator(),264s.descendingSet().descendingSet().iterator(),265};266for (final Iterator it : its)267if (maybe(4))268THROWS(IllegalStateException.class, () -> it.remove());269Object prev = null;270for (Object e : s) {271check(s.contains(e));272for (Iterator it : its) equalNext(it, e);273equal(e, s.ceiling(e));274equal(e, s.floor(e));275check(s.higher(e) == null || cmp.compare(e, s.higher(e)) < 0);276equal(s.lower(e), prev);277if (prev == null) {278} else {279check(cmp.compare(prev, e) < 0);280}281prev = e;282}283for (final Iterator it : its) {284if (maybe(2))285check(! it.hasNext());286Fun fun = () -> it.next();287THROWS(NoSuchElementException.class, fun, fun, fun);288}289}290291static void equalIterators(final Iterator<?> it1,292final Iterator<?> it2) {293while (it1.hasNext()) {294if (maybe(2))295check(it2.hasNext());296equal(it1.next(), it2.next());297}298check(! it2.hasNext());299}300301static void equalSetsLeaf(final Set s1, final Set s2) {302equal2(s1, s2);303equal( s1.size(), s2.size());304equal( s1.isEmpty(), s2.isEmpty());305equal( s1.hashCode(), s2.hashCode());306equal( s1.toString(), s2.toString());307equal( s1.containsAll(s2), s2.containsAll(s1));308}309310static void equalNavigableSetsLeaf(final NavigableSet s1,311final NavigableSet s2) {312equal2(s1, s2);313equal( s1.size(), s2.size());314equal( s1.isEmpty(), s2.isEmpty());315equal( s1.hashCode(), s2.hashCode());316equal( s1.toString(), s2.toString());317if (! s1.isEmpty()) {318equal(s1.first(), s2.first());319equal(s1.last(), s2.last());320}321equalIterators(s1.iterator(), s2.iterator());322equalIterators(s1.descendingIterator(), s2.descendingIterator());323checkNavigableSet(s1);324checkNavigableSet(s2);325}326327static void equalNavigableSets(final NavigableSet s1,328final NavigableSet s2) {329equalNavigableSetsLeaf(s1, s2);330equalNavigableSetsLeaf(s1.descendingSet(), s2.descendingSet());331equalNavigableSetsLeaf(s1.descendingSet().descendingSet(), s2);332Object min = s1.isEmpty() ? Integer.MIN_VALUE : s1.first();333Object max = s2.isEmpty() ? Integer.MAX_VALUE : s2.last();334if (s1.comparator() != null &&335s1.comparator().compare(min, max) > 0) {336Object tmp = min; min = max; max = tmp;337}338339equalNavigableSetsLeaf(s1.subSet(min, true, max, true),340s2.subSet(min, true, max, true));341equalNavigableSetsLeaf(s1.tailSet(min, true),342s2.tailSet(min, true));343equalNavigableSetsLeaf(s1.headSet(max, true),344s2.headSet(max, true));345equalNavigableSetsLeaf((NavigableSet) s1.subSet(min, max),346(NavigableSet) s2.subSet(min, max));347equalNavigableSetsLeaf((NavigableSet) s1.tailSet(min),348(NavigableSet) s2.tailSet(min));349equalNavigableSetsLeaf((NavigableSet) s1.headSet(max),350(NavigableSet) s2.headSet(max));351}352353// Destined for a Collections.java near you?354static <T> T[] concat(T[]... arrays) {355int len = 0;356for (int i = 0; i < arrays.length; i++)357len += arrays[i].length;358T[] a = (T[])java.lang.reflect.Array359.newInstance(arrays[0].getClass().getComponentType(), len);360int k = 0;361for (int i = 0; i < arrays.length; i++) {362T[] array = arrays[i];363System.arraycopy(array, 0, a, k, array.length);364k += array.length;365}366return a;367}368369static void checkNavigableMap(final NavigableMap m) {370if (m.comparator() == null) {371check(m.descendingMap().descendingMap().comparator() == null);372check(m.descendingKeySet().descendingSet().comparator() == null);373}374equal(m.isEmpty(), m.size() == 0);375equal2(m, m.descendingMap());376if (maybe(4))377equal2(m, serialClone(m));378equal2(m.keySet(), m.descendingKeySet());379Comparator cmp = comparator(m);380if (m.isEmpty()) {381THROWS(NoSuchElementException.class,382() -> m.firstKey(),383() -> m.lastKey());384equal(null, m.firstEntry());385equal(null, m.lastEntry());386equal(null, m.pollFirstEntry());387equal(null, m.pollLastEntry());388equal(null, m.lowerKey(1));389equal(null, m.floorKey(1));390equal(null, m.ceilingKey(1));391equal(null, m.higherKey(1));392equal(null, m.lowerEntry(1));393equal(null, m.floorEntry(1));394equal(null, m.ceilingEntry(1));395equal(null, m.higherEntry(1));396} else {397Object a = m.firstKey();398Object z = m.lastKey();399equal(m.lowerKey(a), null);400equal(m.higherKey(z), null);401equal(a, m.firstEntry().getKey());402equal(z, m.lastEntry().getKey());403equal2(m, m.tailMap(a));404equal2(m, m.headMap(z, true));405equal2(m, m.subMap(a, true, z, true));406407testEmptyMap(m.subMap(a, true, a, false));408testEmptyMap(m.subMap(z, true, z, false));409testEmptyMap(m.headMap(a, false));410testEmptyMap(m.tailMap(z, false));411412equal2(m.headMap(a, true), singletonMap(a, m.get(a)));413equal2(m.tailMap(z, true), singletonMap(z, m.get(z)));414}415416Iterator[] kits = new Iterator[] {417m.keySet().iterator(),418m.descendingMap().descendingKeySet().iterator(),419m.descendingKeySet().descendingSet().iterator(),420};421Iterator[] vits = new Iterator[] {422m.values().iterator(),423m.descendingMap().descendingMap().values().iterator(),424};425Iterator[] eits = new Iterator[] {426m.entrySet().iterator(),427m.descendingMap().descendingMap().entrySet().iterator(),428};429Iterator[] its = concat(kits, vits, eits);430for (final Iterator it : its)431if (maybe(4))432THROWS(IllegalStateException.class, () -> it.remove());433Map.Entry prev = null;434for (Map.Entry e : (Set<Map.Entry>) m.entrySet()) {435Object k = e.getKey();436Object v = e.getValue();437check(m.containsKey(k));438check(m.containsValue(v));439for (Iterator kit : kits) equalNext(kit, k);440for (Iterator vit : vits) equalNext(vit, v);441for (Iterator eit : eits) equalNext(eit, e);442equal(k, m.ceilingKey(k));443equal(k, m.ceilingEntry(k).getKey());444equal(k, m.floorKey(k));445equal(k, m.floorEntry(k).getKey());446check(m.higherKey(k) == null || cmp.compare(k, m.higherKey(k)) < 0);447check(m.lowerKey(k) == null || cmp.compare(k, m.lowerKey(k)) > 0);448equal(m.lowerEntry(k), prev);449if (prev == null) {450equal(m.lowerKey(k), null);451} else {452equal(m.lowerKey(k), prev.getKey());453check(cmp.compare(prev.getKey(), e.getKey()) < 0);454}455prev = e;456}457for (final Iterator it : its) {458if (maybe(2))459check(! it.hasNext());460Fun fun = () -> it.next();461THROWS(NoSuchElementException.class, fun, fun, fun);462}463}464465static void equalNavigableMapsLeaf(final NavigableMap m1,466final NavigableMap m2) {467equal2(m1, m2);468equal( m1.size(), m2.size());469equal( m1.isEmpty(), m2.isEmpty());470equal( m1.hashCode(), m2.hashCode());471equal( m1.toString(), m2.toString());472equal2(m1.firstEntry(), m2.firstEntry());473equal2(m1.lastEntry(), m2.lastEntry());474checkNavigableMap(m1);475checkNavigableMap(m2);476}477478static void equalNavigableMaps(NavigableMap m1,479NavigableMap m2) {480equalNavigableMapsLeaf(m1, m2);481equalSetsLeaf(m1.keySet(), m2.keySet());482equalNavigableSets(m1.navigableKeySet(),483m2.navigableKeySet());484equalNavigableSets(m1.descendingKeySet(),485m2.descendingKeySet());486equal2(m1.entrySet(),487m2.entrySet());488equalNavigableMapsLeaf(m1.descendingMap(),489m2.descendingMap());490equalNavigableMapsLeaf(m1.descendingMap().descendingMap(),491m2);492equalNavigableSetsLeaf((NavigableSet) m1.descendingMap().keySet(),493(NavigableSet) m2.descendingMap().keySet());494equalNavigableSetsLeaf(m1.descendingMap().descendingKeySet(),495m2.descendingMap().descendingKeySet());496equal2(m1.descendingMap().entrySet(),497m2.descendingMap().entrySet());498499//----------------------------------------------------------------500// submaps501//----------------------------------------------------------------502Object min = Integer.MIN_VALUE;503Object max = Integer.MAX_VALUE;504if (m1.comparator() != null505&& m1.comparator().compare(min, max) > 0) {506Object tmp = min; min = max; max = tmp;507}508switch (rnd.nextInt(6)) {509case 0:510equalNavigableMapsLeaf(m1.subMap(min, true, max, true),511m2.subMap(min, true, max, true));512break;513case 1:514equalNavigableMapsLeaf(m1.tailMap(min, true),515m2.tailMap(min, true));516break;517case 2:518equalNavigableMapsLeaf(m1.headMap(max, true),519m2.headMap(max, true));520break;521case 3:522equalNavigableMapsLeaf((NavigableMap) m1.subMap(min, max),523(NavigableMap) m2.subMap(min, max));524break;525case 4:526equalNavigableMapsLeaf((NavigableMap) m1.tailMap(min),527(NavigableMap) m2.tailMap(min));528break;529case 5:530equalNavigableMapsLeaf((NavigableMap) m1.headMap(max),531(NavigableMap) m2.headMap(max));532break;533}534}535536static abstract class MapFrobber { abstract void frob(NavigableMap m); }537static abstract class SetFrobber { abstract void frob(NavigableSet m); }538539static MapFrobber randomAdder(NavigableMap m) {540final Integer k = unusedKey(m);541final MapFrobber[] randomAdders = {542new MapFrobber() {void frob(NavigableMap m) {543equal(m.put(k, k+1), null);544equal(m.get(k), k+1);545if (maybe(4)) {546equal(m.put(k, k+1), k+1);547equal(m.get(k), k+1);}}},548new MapFrobber() {void frob(NavigableMap m) {549m.descendingMap().put(k, k+1);550equal(m.get(k), k+1);}},551new MapFrobber() {void frob(NavigableMap m) {552m.tailMap(k,true).headMap(k,true).put(k,k+1);}},553new MapFrobber() {void frob(NavigableMap m) {554m.tailMap(k,true).headMap(k,true).descendingMap().put(k,k+1);}}555};556return new MapFrobber() {void frob(NavigableMap m) {557randomAdders[rnd.nextInt(randomAdders.length)].frob(m);558if (maybe(2)) equal(m.get(k), k+1);559if (maybe(4)) {560equal(m.put(k, k+1), k+1);561equal(m.get(k), k+1);}}};562}563564static SetFrobber randomAdder(NavigableSet s) {565final Integer e = unusedElt(s);566final SetFrobber[] randomAdders = {567new SetFrobber() {void frob(NavigableSet s) {568check(s.add(e));}},569new SetFrobber() {void frob(NavigableSet s) {570s.descendingSet().add(e);}},571new SetFrobber() {void frob(NavigableSet s) {572s.tailSet(e,true).headSet(e,true).add(e);}},573new SetFrobber() {void frob(NavigableSet s) {574s.descendingSet().tailSet(e,true).headSet(e,true).add(e);}}575};576return new SetFrobber() {void frob(NavigableSet s) {577if (maybe(2)) check(! s.contains(e));578randomAdders[rnd.nextInt(randomAdders.length)].frob(s);579if (maybe(2)) check(! s.add(e));580if (maybe(2)) check(s.contains(e));}};581}582583static Integer unusedElt(NavigableSet s) {584Integer e;585do { e = rnd.nextInt(1024); }586while (s.contains(e));587return e;588}589590static Integer unusedKey(NavigableMap m) {591Integer k;592do { k = rnd.nextInt(1024); }593while (m.containsKey(k));594return k;595}596597static Integer usedKey(NavigableMap m) {598Integer x = rnd.nextInt(1024);599Integer floor = (Integer) m.floorKey(x);600Integer ceiling = (Integer) m.ceilingKey(x);601if (floor != null) return floor;602check(ceiling != null);603return ceiling;604}605606static Integer usedElt(NavigableSet s) {607Integer x = rnd.nextInt(1024);608Integer floor = (Integer) s.floor(x);609Integer ceiling = (Integer) s.ceiling(x);610if (floor != null) return floor;611check(ceiling != null);612return ceiling;613}614615static void checkUnusedKey(NavigableMap m, Object k) {616check(! m.containsKey(k));617equal(m.get(k), null);618if (maybe(2))619equal(m.remove(k), null);620}621622static void checkUnusedElt(NavigableSet s, Object e) {623if (maybe(2))624check(! s.contains(e));625if (maybe(2)) {626check(s.ceiling(e) != e);627check(s.floor(e) != e);628}629if (maybe(2))630check(! s.remove(e));631}632633static Fun remover(final Iterator it) {634return () -> it.remove();635}636637static MapFrobber randomRemover(NavigableMap m) {638final Integer k = usedKey(m);639final MapFrobber[] randomRemovers = {640new MapFrobber() {void frob(NavigableMap m) {641Map.Entry e = m.firstEntry();642equal(m.pollFirstEntry(), e);643checkUnusedKey(m, e.getKey());}},644new MapFrobber() {void frob(NavigableMap m) {645Map.Entry e = m.lastEntry();646equal(m.pollLastEntry(), e);647checkUnusedKey(m, e.getKey());}},648new MapFrobber() {void frob(NavigableMap m) {649check(m.remove(k) != null);650checkUnusedKey(m, k);}},651new MapFrobber() {void frob(NavigableMap m) {652m.subMap(k, true, k, true).clear();653checkUnusedKey(m, k);}},654new MapFrobber() {void frob(NavigableMap m) {655m.descendingMap().subMap(k, true, k, true).clear();656checkUnusedKey(m, k);}},657new MapFrobber() {void frob(NavigableMap m) {658final Iterator it = m.keySet().iterator();659while (it.hasNext())660if (it.next().equals(k)) {661it.remove();662if (maybe(2))663THROWS(IllegalStateException.class,664() -> it.remove());665}666checkUnusedKey(m, k);}},667new MapFrobber() {void frob(NavigableMap m) {668final Iterator it = m.navigableKeySet().descendingIterator();669while (it.hasNext())670if (it.next().equals(k)) {671it.remove();672if (maybe(2))673THROWS(IllegalStateException.class,674() -> it.remove());675}676checkUnusedKey(m, k);}},677new MapFrobber() {void frob(NavigableMap m) {678final Iterator<Map.Entry> it = m.entrySet().iterator();679while (it.hasNext())680if (it.next().getKey().equals(k)) {681it.remove();682if (maybe(2))683THROWS(IllegalStateException.class, remover(it));684}685checkUnusedKey(m, k);}},686};687688return randomRemovers[rnd.nextInt(randomRemovers.length)];689}690691static SetFrobber randomRemover(NavigableSet s) {692final Integer e = usedElt(s);693694final SetFrobber[] randomRemovers = {695new SetFrobber() {void frob(NavigableSet s) {696Object e = s.first();697equal(s.pollFirst(), e);698checkUnusedElt(s, e);}},699new SetFrobber() {void frob(NavigableSet s) {700Object e = s.last();701equal(s.pollLast(), e);702checkUnusedElt(s, e);}},703new SetFrobber() {void frob(NavigableSet s) {704check(s.remove(e));705checkUnusedElt(s, e);}},706new SetFrobber() {void frob(NavigableSet s) {707s.subSet(e, true, e, true).clear();708checkUnusedElt(s, e);}},709new SetFrobber() {void frob(NavigableSet s) {710s.descendingSet().subSet(e, true, e, true).clear();711checkUnusedElt(s, e);}},712new SetFrobber() {void frob(NavigableSet s) {713final Iterator it = s.iterator();714while (it.hasNext())715if (it.next().equals(e)) {716it.remove();717if (maybe(2))718THROWS(IllegalStateException.class,719() -> it.remove());720}721checkUnusedElt(s, e);}},722new SetFrobber() {void frob(NavigableSet s) {723final Iterator it = s.descendingSet().iterator();724while (it.hasNext())725if (it.next().equals(e)) {726it.remove();727if (maybe(2))728THROWS(IllegalStateException.class,729() -> it.remove());730}731checkUnusedElt(s, e);}},732new SetFrobber() {void frob(NavigableSet s) {733final Iterator it = s.descendingIterator();734while (it.hasNext())735if (it.next().equals(e)) {736it.remove();737if (maybe(2))738THROWS(IllegalStateException.class,739() -> it.remove());740}741checkUnusedElt(s, e);}}742};743744return randomRemovers[rnd.nextInt(randomRemovers.length)];745}746747static void lockStep(NavigableMap m1,748NavigableMap m2) {749if (! (thorough || maybe(3))) return;750if (maybe(4)) m1 = serialClone(m1);751if (maybe(4)) m2 = serialClone(m2);752753List<NavigableMap> maps = Arrays.asList(m1, m2);754for (NavigableMap m : maps) testEmptyMap(m);755final Set<Integer> ints = new HashSet<Integer>();756while (ints.size() < size)757ints.add(rnd.nextInt(1024));758final Integer[] elts = ints.toArray(new Integer[size]);759for (int i = 0; i < size; i++) {760MapFrobber adder = randomAdder(m1);761for (final NavigableMap m : maps) {762adder.frob(m);763equal(m.size(), i+1);764}765equalNavigableMaps(m1, m2);766}767for (final NavigableMap m : maps) {768final Object e = usedKey(m);769THROWS(IllegalArgumentException.class,770() -> {m.subMap(e,true,e,false)771.subMap(e,true,e,true);},772() -> {m.subMap(e,false,e,true)773.subMap(e,true,e,true);},774() -> m.tailMap(e,false).tailMap(e,true),775() -> m.headMap(e,false).headMap(e,true));776}777//System.out.printf("%s%n", m1);778for (int i = size; i > 0; i--) {779MapFrobber remover = randomRemover(m1);780for (final NavigableMap m : maps) {781remover.frob(m);782equal(m.size(), i-1);783}784equalNavigableMaps(m1, m2);785}786for (NavigableMap m : maps) testEmptyMap(m);787}788789static void lockStep(NavigableSet s1,790NavigableSet s2) {791if (! (thorough || maybe(3))) return;792if (maybe(4)) s1 = serialClone(s1);793if (maybe(4)) s2 = serialClone(s2);794795List<NavigableSet> sets = Arrays.asList(s1, s2);796for (NavigableSet s : sets) testEmptySet(s);797final Set<Integer> ints = new HashSet<Integer>();798while (ints.size() < size)799ints.add(rnd.nextInt(1024));800final Integer[] elts = ints.toArray(new Integer[size]);801for (int i = 0; i < size; i++) {802SetFrobber adder = randomAdder(s1);803for (final NavigableSet s : sets) {804adder.frob(s);805equal(s.size(), i+1);806}807equalNavigableSets(s1, s2);808}809for (final NavigableSet s : sets) {810final Object e = usedElt(s);811THROWS(IllegalArgumentException.class,812() -> {s.subSet(e,true,e,false)813.subSet(e,true,e,true);},814() -> {s.subSet(e,false,e,true)815.subSet(e,true,e,true);},816() -> s.tailSet(e,false).tailSet(e,true),817() -> s.headSet(e,false).headSet(e,true));818}819//System.out.printf("%s%n", s1);820for (int i = size; i > 0; i--) {821SetFrobber remover = randomRemover(s1);822for (final NavigableSet s : sets) {823remover.frob(s);824equal(s.size(), i-1);825}826equalNavigableSets(s1, s2);827}828for (NavigableSet s : sets) testEmptySet(s);829}830831//--------------------- Infrastructure ---------------------------832static volatile int passed = 0, failed = 0;833static void pass() { passed++; }834static void fail() { failed++; Thread.dumpStack(); }835static void fail(String msg) { System.out.println(msg); fail(); }836static void unexpected(Throwable t) { failed++; t.printStackTrace(); }837static void check(boolean cond) { if (cond) pass(); else fail(); }838static void equal(Object x, Object y) {839if (x == null ? y == null : x.equals(y)) pass();840else {System.out.println(x + " not equal to " + y); fail();}}841static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}842public static void main(String[] args) throws Throwable {843try { realMain(args); } catch (Throwable t) { unexpected(t); }844845System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);846if (failed > 0) throw new Exception("Some tests failed");847}848interface Fun {void f() throws Throwable;}849static void THROWS(Class<? extends Throwable> k, Fun... fs) {850for (Fun f : fs)851try { f.f(); fail("Expected " + k.getName() + " not thrown"); }852catch (Throwable t) {853if (k.isAssignableFrom(t.getClass())) pass();854else unexpected(t);}}855static byte[] serializedForm(Object obj) {856try {857ByteArrayOutputStream baos = new ByteArrayOutputStream();858new ObjectOutputStream(baos).writeObject(obj);859return baos.toByteArray();860} catch (IOException e) { throw new RuntimeException(e); }}861static Object readObject(byte[] bytes)862throws IOException, ClassNotFoundException {863InputStream is = new ByteArrayInputStream(bytes);864return new ObjectInputStream(is).readObject();}865@SuppressWarnings("unchecked")866static <T> T serialClone(T obj) {867try { return (T) readObject(serializedForm(obj)); }868catch (Error|RuntimeException e) { throw e; }869catch (Throwable e) { throw new RuntimeException(e); }870}871}872873874