ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/jtreg/util/NavigableMap/LockStep.java
Revision: 1.7
Committed: Sat Oct 21 00:42:10 2017 UTC (6 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.6: +5 -5 lines
Log Message:
whitespace

File Contents

# User Rev Content
1 jsr166 1.1 /*
2 jsr166 1.5 * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
3 jsr166 1.1 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4     *
5     * This code is free software; you can redistribute it and/or modify it
6     * under the terms of the GNU General Public License version 2 only, as
7     * published by the Free Software Foundation.
8     *
9     * This code is distributed in the hope that it will be useful, but WITHOUT
10     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12     * version 2 for more details (a copy is included in the LICENSE file that
13     * accompanied this code).
14     *
15     * You should have received a copy of the GNU General Public License version
16     * 2 along with this work; if not, write to the Free Software Foundation,
17     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18     *
19 jsr166 1.2 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20     * or visit www.oracle.com if you need additional information or have any
21     * questions.
22 jsr166 1.1 */
23    
24     /*
25     * @test
26     * @bug 6420753 6242436 6691185
27     * @summary Compare NavigableMap implementations for identical behavior
28 jsr166 1.5 * @run main LockStep
29     * @run main/othervm -XX:+AggressiveOpts LockStep
30     * @run main/othervm -XX:+AggressiveOpts -Dthorough=true LockStep
31 jsr166 1.1 * @author Martin Buchholz
32 jsr166 1.5 * @key randomness
33 jsr166 1.1 */
34    
35     import java.io.*;
36     import java.util.*;
37     import java.util.concurrent.*;
38     import static java.util.Collections.*;
39    
40     @SuppressWarnings("unchecked")
41     public class LockStep {
42     static final int DEFAULT_SIZE = 5;
43     static int size; // Running time is O(size**2)
44    
45     static int intArg(String[] args, int i, int defaultValue) {
46     return args.length > i ? Integer.parseInt(args[i]) : defaultValue;
47     }
48    
49     // Pass -Dthorough=true for more exhaustive testing
50     static final boolean thorough = Boolean.getBoolean("thorough");
51    
52     static boolean maybe(int n) { return rnd.nextInt(n) == 0; }
53    
54     static void realMain(String[] args) {
55     size = intArg(args, 0, DEFAULT_SIZE);
56    
57     lockSteps(new TreeMap(),
58     new ConcurrentSkipListMap());
59 jsr166 1.5 lockSteps(new TreeMap(),
60     Collections.checkedNavigableMap(new TreeMap(), Integer.class, Integer.class));
61     lockSteps(new TreeMap(),
62     Collections.synchronizedNavigableMap(new TreeMap()));
63 jsr166 1.1 lockSteps(new TreeMap(reverseOrder()),
64     new ConcurrentSkipListMap(reverseOrder()));
65    
66     lockSteps(new TreeSet(),
67     new ConcurrentSkipListSet());
68 jsr166 1.5 lockSteps(new TreeSet(),
69     Collections.checkedNavigableSet(new TreeSet(), Integer.class));
70     lockSteps(new TreeSet(),
71     Collections.synchronizedNavigableSet(new TreeSet()));
72 jsr166 1.1 lockSteps(new TreeSet(reverseOrder()),
73     new ConcurrentSkipListSet(reverseOrder()));
74     }
75    
76     static void lockSteps(NavigableMap m1, NavigableMap m2) {
77     if (maybe(4)) m1 = serialClone(m1);
78     if (maybe(4)) m2 = serialClone(m2);
79     lockStep(m1,
80     m2);
81     lockStep(m1.descendingMap(),
82     m2.descendingMap());
83     lockStep(fullSubMap(m1),
84     fullSubMap(m2));
85     lockStep(fullSubMap(m1.descendingMap()),
86     fullSubMap(m2.descendingMap()));
87     lockStep(fullHeadMap(m1),
88     fullHeadMap(m2));
89     lockStep(fullHeadMap(m1.descendingMap()),
90     fullHeadMap(m2.descendingMap()));
91     lockStep(fullTailMap(m1),
92     fullTailMap(m2));
93     lockStep(fullTailMap(m1.descendingMap()),
94     fullTailMap(m2.descendingMap()));
95     }
96    
97     static void lockSteps(NavigableSet s1, NavigableSet s2) {
98     if (maybe(4)) s1 = serialClone(s1);
99     if (maybe(4)) s2 = serialClone(s2);
100     lockStep(s1,
101     s2);
102     lockStep(s1.descendingSet(),
103     s2.descendingSet());
104     lockStep(fullSubSet(s1),
105     fullSubSet(s2));
106     lockStep(fullSubSet(s1.descendingSet()),
107     fullSubSet(s2.descendingSet()));
108     lockStep(fullHeadSet(s1),
109     fullHeadSet(s2));
110     lockStep(fullHeadSet(s1.descendingSet()),
111     fullHeadSet(s2.descendingSet()));
112     lockStep(fullTailSet(s1),
113     fullTailSet(s2));
114     lockStep(fullTailSet(s1.descendingSet()),
115     fullTailSet(s2.descendingSet()));
116     }
117    
118     static boolean isAscending(NavigableMap m) {
119     Comparator cmp = m.comparator();
120     return (cmp == null || cmp.compare(1, 2) < 0);
121     }
122    
123     static NavigableMap fullSubMap(NavigableMap m) {
124     return isAscending(m)
125     ? m.subMap(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true)
126     : m.subMap(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true);
127     }
128    
129     static NavigableMap fullHeadMap(NavigableMap m) {
130     return isAscending(m)
131     ? m.headMap(Integer.MAX_VALUE, true)
132     : m.headMap(Integer.MIN_VALUE, true);
133     }
134    
135     static NavigableMap fullTailMap(NavigableMap m) {
136     return isAscending(m)
137     ? m.tailMap(Integer.MIN_VALUE, true)
138     : m.tailMap(Integer.MAX_VALUE, true);
139     }
140    
141     static boolean isAscending(NavigableSet s) {
142     Comparator cmp = s.comparator();
143     return (cmp == null || cmp.compare(1, 2) < 0);
144     }
145    
146     static NavigableSet fullSubSet(NavigableSet s) {
147     return isAscending(s)
148     ? s.subSet(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true)
149     : s.subSet(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true);
150     }
151    
152     static NavigableSet fullHeadSet(NavigableSet s) {
153     return isAscending(s)
154     ? s.headSet(Integer.MAX_VALUE, true)
155     : s.headSet(Integer.MIN_VALUE, true);
156     }
157    
158     static NavigableSet fullTailSet(NavigableSet s) {
159     return isAscending(s)
160     ? s.tailSet(Integer.MIN_VALUE, true)
161     : s.tailSet(Integer.MAX_VALUE, true);
162     }
163    
164     static void testEmptyCollection(Collection<?> c) {
165     check(c.isEmpty());
166     equal(c.size(), 0);
167     equal(c.toString(),"[]");
168     equal(c.toArray().length, 0);
169     equal(c.toArray(new Object[0]).length, 0);
170    
171     Object[] a = new Object[1]; a[0] = Boolean.TRUE;
172     equal(c.toArray(a), a);
173     equal(a[0], null);
174     check(! c.iterator().hasNext());
175     }
176    
177     static void testEmptySet(Set<?> c) {
178     testEmptyCollection(c);
179     equal(c.hashCode(), 0);
180     equal2(c, Collections.<Integer>emptySet());
181     }
182    
183     static void testEmptyMap(final Map<?,?> m) {
184     check(m.isEmpty());
185     equal(m.size(), 0);
186     equal(m.toString(),"{}");
187     equal(m.hashCode(), 0);
188     testEmptySet(m.keySet());
189     testEmptySet(m.entrySet());
190     testEmptyCollection(m.values());
191     }
192    
193 jsr166 1.5 static final Random rnd;
194    
195     static {
196     // sufficiently random for this test
197     long seed = System.nanoTime();
198     System.out.println(LockStep.class.getCanonicalName() + ": Trial random seed: " + seed );
199    
200     rnd = new Random(seed);
201     }
202 jsr166 1.1
203     static void equalNext(final Iterator<?> it, Object expected) {
204     if (maybe(2))
205     check(it.hasNext());
206     equal(it.next(), expected);
207     }
208    
209     static Comparator comparator(NavigableSet s) {
210     Comparator cmp = s.comparator();
211     return cmp != null ? cmp : new Comparator() {
212     public int compare(Object o1, Object o2) {
213     return ((Comparable) o1).compareTo(o2); }};
214     }
215    
216     static Comparator comparator(NavigableMap m) {
217     Comparator cmp = m.comparator();
218     return cmp != null ? cmp : new Comparator() {
219     public int compare(Object o1, Object o2) {
220     return ((Comparable) o1).compareTo(o2); }};
221     }
222    
223     static void checkNavigableSet(final NavigableSet s) {
224     if (s.comparator() == null)
225     check(s.descendingSet().descendingSet().comparator() == null);
226     equal(s.isEmpty(), s.size() == 0);
227     equal2(s, s.descendingSet());
228 jsr166 1.5 if (maybe(4) && s instanceof Serializable) {
229     try {
230     equal2(s, serialClone(s));
231     } catch (RuntimeException uhoh) {
232     if (!(uhoh.getCause() instanceof NotSerializableException)) {
233     throw uhoh;
234     }
235     }
236     }
237 jsr166 1.1 Comparator cmp = comparator(s);
238     if (s.isEmpty()) {
239     THROWS(NoSuchElementException.class,
240 jsr166 1.5 () -> s.first(),
241     () -> s.last());
242 jsr166 1.1 equal(null, s.lower(1));
243     equal(null, s.floor(1));
244     equal(null, s.ceiling(1));
245     equal(null, s.higher(1));
246     } else {
247     Object a = s.first();
248     Object z = s.last();
249     equal(s.lower(a), null);
250     equal(s.higher(z), null);
251     equal2(s, s.tailSet(a));
252     equal2(s, s.headSet(z, true));
253     equal2(s, s.subSet(a, true, z, true));
254    
255     testEmptySet(s.subSet(a, true, a, false));
256     testEmptySet(s.subSet(z, true, z, false));
257     testEmptySet(s.headSet(a, false));
258     testEmptySet(s.tailSet(z, false));
259    
260     equal2(s.headSet(a, true), singleton(a));
261     equal2(s.tailSet(z, true), singleton(z));
262     }
263     Iterator[] its = new Iterator[] {
264     s.iterator(),
265     s.descendingSet().descendingSet().iterator(),
266     };
267     for (final Iterator it : its)
268     if (maybe(4))
269 jsr166 1.5 THROWS(IllegalStateException.class, () -> it.remove());
270 jsr166 1.1 Object prev = null;
271     for (Object e : s) {
272     check(s.contains(e));
273     for (Iterator it : its) equalNext(it, e);
274     equal(e, s.ceiling(e));
275     equal(e, s.floor(e));
276     check(s.higher(e) == null || cmp.compare(e, s.higher(e)) < 0);
277     equal(s.lower(e), prev);
278     if (prev == null) {
279     } else {
280     check(cmp.compare(prev, e) < 0);
281     }
282     prev = e;
283     }
284     for (final Iterator it : its) {
285     if (maybe(2))
286     check(! it.hasNext());
287 jsr166 1.5 Fun fun = () -> it.next();
288 jsr166 1.1 THROWS(NoSuchElementException.class, fun, fun, fun);
289     }
290     }
291    
292     static void equalIterators(final Iterator<?> it1,
293     final Iterator<?> it2) {
294     while (it1.hasNext()) {
295     if (maybe(2))
296     check(it2.hasNext());
297     equal(it1.next(), it2.next());
298     }
299     check(! it2.hasNext());
300     }
301    
302 jsr166 1.5 static void equalSetsLeaf(final Set s1, final Set s2) {
303     equal2(s1, s2);
304     equal( s1.size(), s2.size());
305     equal( s1.isEmpty(), s2.isEmpty());
306     equal( s1.hashCode(), s2.hashCode());
307     equal( s1.toString(), s2.toString());
308     equal( s1.containsAll(s2), s2.containsAll(s1));
309     }
310    
311 jsr166 1.1 static void equalNavigableSetsLeaf(final NavigableSet s1,
312     final NavigableSet s2) {
313     equal2(s1, s2);
314     equal( s1.size(), s2.size());
315     equal( s1.isEmpty(), s2.isEmpty());
316     equal( s1.hashCode(), s2.hashCode());
317     equal( s1.toString(), s2.toString());
318     if (! s1.isEmpty()) {
319     equal(s1.first(), s2.first());
320     equal(s1.last(), s2.last());
321     }
322     equalIterators(s1.iterator(), s2.iterator());
323     equalIterators(s1.descendingIterator(), s2.descendingIterator());
324     checkNavigableSet(s1);
325     checkNavigableSet(s2);
326     }
327    
328     static void equalNavigableSets(final NavigableSet s1,
329     final NavigableSet s2) {
330     equalNavigableSetsLeaf(s1, s2);
331     equalNavigableSetsLeaf(s1.descendingSet(), s2.descendingSet());
332     equalNavigableSetsLeaf(s1.descendingSet().descendingSet(), s2);
333     Object min = s1.isEmpty() ? Integer.MIN_VALUE : s1.first();
334     Object max = s2.isEmpty() ? Integer.MAX_VALUE : s2.last();
335     if (s1.comparator() != null &&
336     s1.comparator().compare(min, max) > 0) {
337     Object tmp = min; min = max; max = tmp;
338     }
339    
340     equalNavigableSetsLeaf(s1.subSet(min, true, max, true),
341     s2.subSet(min, true, max, true));
342     equalNavigableSetsLeaf(s1.tailSet(min, true),
343     s2.tailSet(min, true));
344     equalNavigableSetsLeaf(s1.headSet(max, true),
345     s2.headSet(max, true));
346     equalNavigableSetsLeaf((NavigableSet) s1.subSet(min, max),
347     (NavigableSet) s2.subSet(min, max));
348     equalNavigableSetsLeaf((NavigableSet) s1.tailSet(min),
349     (NavigableSet) s2.tailSet(min));
350     equalNavigableSetsLeaf((NavigableSet) s1.headSet(max),
351     (NavigableSet) s2.headSet(max));
352     }
353    
354     // Destined for a Collections.java near you?
355     static <T> T[] concat(T[]... arrays) {
356     int len = 0;
357     for (int i = 0; i < arrays.length; i++)
358     len += arrays[i].length;
359     T[] a = (T[])java.lang.reflect.Array
360     .newInstance(arrays[0].getClass().getComponentType(), len);
361     int k = 0;
362     for (int i = 0; i < arrays.length; i++) {
363     T[] array = arrays[i];
364     System.arraycopy(array, 0, a, k, array.length);
365     k += array.length;
366     }
367     return a;
368     }
369    
370     static void checkNavigableMap(final NavigableMap m) {
371     if (m.comparator() == null) {
372     check(m.descendingMap().descendingMap().comparator() == null);
373     check(m.descendingKeySet().descendingSet().comparator() == null);
374     }
375     equal(m.isEmpty(), m.size() == 0);
376     equal2(m, m.descendingMap());
377     if (maybe(4))
378     equal2(m, serialClone(m));
379     equal2(m.keySet(), m.descendingKeySet());
380     Comparator cmp = comparator(m);
381     if (m.isEmpty()) {
382     THROWS(NoSuchElementException.class,
383 jsr166 1.5 () -> m.firstKey(),
384     () -> m.lastKey());
385 jsr166 1.1 equal(null, m.firstEntry());
386     equal(null, m.lastEntry());
387     equal(null, m.pollFirstEntry());
388     equal(null, m.pollLastEntry());
389     equal(null, m.lowerKey(1));
390     equal(null, m.floorKey(1));
391     equal(null, m.ceilingKey(1));
392     equal(null, m.higherKey(1));
393     equal(null, m.lowerEntry(1));
394     equal(null, m.floorEntry(1));
395     equal(null, m.ceilingEntry(1));
396     equal(null, m.higherEntry(1));
397     } else {
398     Object a = m.firstKey();
399     Object z = m.lastKey();
400     equal(m.lowerKey(a), null);
401     equal(m.higherKey(z), null);
402     equal(a, m.firstEntry().getKey());
403     equal(z, m.lastEntry().getKey());
404     equal2(m, m.tailMap(a));
405     equal2(m, m.headMap(z, true));
406     equal2(m, m.subMap(a, true, z, true));
407    
408     testEmptyMap(m.subMap(a, true, a, false));
409     testEmptyMap(m.subMap(z, true, z, false));
410     testEmptyMap(m.headMap(a, false));
411     testEmptyMap(m.tailMap(z, false));
412    
413     equal2(m.headMap(a, true), singletonMap(a, m.get(a)));
414     equal2(m.tailMap(z, true), singletonMap(z, m.get(z)));
415     }
416    
417     Iterator[] kits = new Iterator[] {
418     m.keySet().iterator(),
419     m.descendingMap().descendingKeySet().iterator(),
420     m.descendingKeySet().descendingSet().iterator(),
421     };
422     Iterator[] vits = new Iterator[] {
423     m.values().iterator(),
424     m.descendingMap().descendingMap().values().iterator(),
425     };
426     Iterator[] eits = new Iterator[] {
427     m.entrySet().iterator(),
428     m.descendingMap().descendingMap().entrySet().iterator(),
429     };
430     Iterator[] its = concat(kits, vits, eits);
431     for (final Iterator it : its)
432     if (maybe(4))
433 jsr166 1.5 THROWS(IllegalStateException.class, () -> it.remove());
434 jsr166 1.1 Map.Entry prev = null;
435     for (Map.Entry e : (Set<Map.Entry>) m.entrySet()) {
436     Object k = e.getKey();
437     Object v = e.getValue();
438     check(m.containsKey(k));
439     check(m.containsValue(v));
440     for (Iterator kit : kits) equalNext(kit, k);
441     for (Iterator vit : vits) equalNext(vit, v);
442     for (Iterator eit : eits) equalNext(eit, e);
443     equal(k, m.ceilingKey(k));
444     equal(k, m.ceilingEntry(k).getKey());
445     equal(k, m.floorKey(k));
446     equal(k, m.floorEntry(k).getKey());
447     check(m.higherKey(k) == null || cmp.compare(k, m.higherKey(k)) < 0);
448     check(m.lowerKey(k) == null || cmp.compare(k, m.lowerKey(k)) > 0);
449     equal(m.lowerEntry(k), prev);
450     if (prev == null) {
451     equal(m.lowerKey(k), null);
452     } else {
453     equal(m.lowerKey(k), prev.getKey());
454     check(cmp.compare(prev.getKey(), e.getKey()) < 0);
455     }
456     prev = e;
457     }
458     for (final Iterator it : its) {
459     if (maybe(2))
460     check(! it.hasNext());
461 jsr166 1.5 Fun fun = () -> it.next();
462 jsr166 1.1 THROWS(NoSuchElementException.class, fun, fun, fun);
463     }
464     }
465    
466     static void equalNavigableMapsLeaf(final NavigableMap m1,
467     final NavigableMap m2) {
468     equal2(m1, m2);
469     equal( m1.size(), m2.size());
470     equal( m1.isEmpty(), m2.isEmpty());
471     equal( m1.hashCode(), m2.hashCode());
472     equal( m1.toString(), m2.toString());
473     equal2(m1.firstEntry(), m2.firstEntry());
474     equal2(m1.lastEntry(), m2.lastEntry());
475     checkNavigableMap(m1);
476     checkNavigableMap(m2);
477     }
478    
479     static void equalNavigableMaps(NavigableMap m1,
480     NavigableMap m2) {
481     equalNavigableMapsLeaf(m1, m2);
482 jsr166 1.5 equalSetsLeaf(m1.keySet(), m2.keySet());
483 jsr166 1.1 equalNavigableSets(m1.navigableKeySet(),
484     m2.navigableKeySet());
485     equalNavigableSets(m1.descendingKeySet(),
486     m2.descendingKeySet());
487     equal2(m1.entrySet(),
488     m2.entrySet());
489     equalNavigableMapsLeaf(m1.descendingMap(),
490     m2.descendingMap());
491     equalNavigableMapsLeaf(m1.descendingMap().descendingMap(),
492     m2);
493     equalNavigableSetsLeaf((NavigableSet) m1.descendingMap().keySet(),
494     (NavigableSet) m2.descendingMap().keySet());
495     equalNavigableSetsLeaf(m1.descendingMap().descendingKeySet(),
496     m2.descendingMap().descendingKeySet());
497     equal2(m1.descendingMap().entrySet(),
498     m2.descendingMap().entrySet());
499    
500     //----------------------------------------------------------------
501     // submaps
502     //----------------------------------------------------------------
503     Object min = Integer.MIN_VALUE;
504     Object max = Integer.MAX_VALUE;
505     if (m1.comparator() != null
506     && m1.comparator().compare(min, max) > 0) {
507     Object tmp = min; min = max; max = tmp;
508     }
509     switch (rnd.nextInt(6)) {
510     case 0:
511     equalNavigableMapsLeaf(m1.subMap(min, true, max, true),
512     m2.subMap(min, true, max, true));
513     break;
514     case 1:
515     equalNavigableMapsLeaf(m1.tailMap(min, true),
516     m2.tailMap(min, true));
517     break;
518     case 2:
519     equalNavigableMapsLeaf(m1.headMap(max, true),
520     m2.headMap(max, true));
521     break;
522     case 3:
523     equalNavigableMapsLeaf((NavigableMap) m1.subMap(min, max),
524     (NavigableMap) m2.subMap(min, max));
525     break;
526     case 4:
527     equalNavigableMapsLeaf((NavigableMap) m1.tailMap(min),
528     (NavigableMap) m2.tailMap(min));
529     break;
530     case 5:
531     equalNavigableMapsLeaf((NavigableMap) m1.headMap(max),
532     (NavigableMap) m2.headMap(max));
533     break;
534     }
535     }
536    
537 jsr166 1.3 abstract static class MapFrobber { abstract void frob(NavigableMap m); }
538     abstract static class SetFrobber { abstract void frob(NavigableSet m); }
539 jsr166 1.1
540     static MapFrobber randomAdder(NavigableMap m) {
541     final Integer k = unusedKey(m);
542     final MapFrobber[] randomAdders = {
543     new MapFrobber() {void frob(NavigableMap m) {
544     equal(m.put(k, k+1), null);
545     equal(m.get(k), k+1);
546     if (maybe(4)) {
547     equal(m.put(k, k+1), k+1);
548     equal(m.get(k), k+1);}}},
549     new MapFrobber() {void frob(NavigableMap m) {
550     m.descendingMap().put(k, k+1);
551     equal(m.get(k), k+1);}},
552     new MapFrobber() {void frob(NavigableMap m) {
553     m.tailMap(k,true).headMap(k,true).put(k,k+1);}},
554     new MapFrobber() {void frob(NavigableMap m) {
555     m.tailMap(k,true).headMap(k,true).descendingMap().put(k,k+1);}}
556     };
557     return new MapFrobber() {void frob(NavigableMap m) {
558     randomAdders[rnd.nextInt(randomAdders.length)].frob(m);
559     if (maybe(2)) equal(m.get(k), k+1);
560     if (maybe(4)) {
561     equal(m.put(k, k+1), k+1);
562     equal(m.get(k), k+1);}}};
563     }
564    
565     static SetFrobber randomAdder(NavigableSet s) {
566     final Integer e = unusedElt(s);
567     final SetFrobber[] randomAdders = {
568     new SetFrobber() {void frob(NavigableSet s) {
569     check(s.add(e));}},
570     new SetFrobber() {void frob(NavigableSet s) {
571     s.descendingSet().add(e);}},
572     new SetFrobber() {void frob(NavigableSet s) {
573     s.tailSet(e,true).headSet(e,true).add(e);}},
574     new SetFrobber() {void frob(NavigableSet s) {
575     s.descendingSet().tailSet(e,true).headSet(e,true).add(e);}}
576     };
577     return new SetFrobber() {void frob(NavigableSet s) {
578     if (maybe(2)) check(! s.contains(e));
579     randomAdders[rnd.nextInt(randomAdders.length)].frob(s);
580     if (maybe(2)) check(! s.add(e));
581     if (maybe(2)) check(s.contains(e));}};
582     }
583    
584     static Integer unusedElt(NavigableSet s) {
585     Integer e;
586     do { e = rnd.nextInt(1024); }
587     while (s.contains(e));
588     return e;
589     }
590    
591     static Integer unusedKey(NavigableMap m) {
592     Integer k;
593     do { k = rnd.nextInt(1024); }
594     while (m.containsKey(k));
595     return k;
596     }
597    
598     static Integer usedKey(NavigableMap m) {
599     Integer x = rnd.nextInt(1024);
600     Integer floor = (Integer) m.floorKey(x);
601     Integer ceiling = (Integer) m.ceilingKey(x);
602     if (floor != null) return floor;
603     check(ceiling != null);
604     return ceiling;
605     }
606    
607     static Integer usedElt(NavigableSet s) {
608     Integer x = rnd.nextInt(1024);
609     Integer floor = (Integer) s.floor(x);
610     Integer ceiling = (Integer) s.ceiling(x);
611     if (floor != null) return floor;
612     check(ceiling != null);
613     return ceiling;
614     }
615    
616     static void checkUnusedKey(NavigableMap m, Object k) {
617     check(! m.containsKey(k));
618     equal(m.get(k), null);
619     if (maybe(2))
620     equal(m.remove(k), null);
621     }
622    
623     static void checkUnusedElt(NavigableSet s, Object e) {
624     if (maybe(2))
625     check(! s.contains(e));
626     if (maybe(2)) {
627     check(s.ceiling(e) != e);
628     check(s.floor(e) != e);
629     }
630     if (maybe(2))
631     check(! s.remove(e));
632     }
633    
634     static Fun remover(final Iterator it) {
635 jsr166 1.5 return () -> it.remove();
636 jsr166 1.1 }
637    
638     static MapFrobber randomRemover(NavigableMap m) {
639     final Integer k = usedKey(m);
640     final MapFrobber[] randomRemovers = {
641     new MapFrobber() {void frob(NavigableMap m) {
642     Map.Entry e = m.firstEntry();
643     equal(m.pollFirstEntry(), e);
644     checkUnusedKey(m, e.getKey());}},
645     new MapFrobber() {void frob(NavigableMap m) {
646     Map.Entry e = m.lastEntry();
647     equal(m.pollLastEntry(), e);
648     checkUnusedKey(m, e.getKey());}},
649     new MapFrobber() {void frob(NavigableMap m) {
650     check(m.remove(k) != null);
651     checkUnusedKey(m, k);}},
652     new MapFrobber() {void frob(NavigableMap m) {
653     m.subMap(k, true, k, true).clear();
654     checkUnusedKey(m, k);}},
655     new MapFrobber() {void frob(NavigableMap m) {
656     m.descendingMap().subMap(k, true, k, true).clear();
657     checkUnusedKey(m, k);}},
658     new MapFrobber() {void frob(NavigableMap m) {
659     final Iterator it = m.keySet().iterator();
660     while (it.hasNext())
661     if (it.next().equals(k)) {
662     it.remove();
663     if (maybe(2))
664     THROWS(IllegalStateException.class,
665 jsr166 1.5 () -> it.remove());
666 jsr166 1.1 }
667     checkUnusedKey(m, k);}},
668     new MapFrobber() {void frob(NavigableMap m) {
669     final Iterator it = m.navigableKeySet().descendingIterator();
670     while (it.hasNext())
671     if (it.next().equals(k)) {
672     it.remove();
673     if (maybe(2))
674     THROWS(IllegalStateException.class,
675 jsr166 1.5 () -> it.remove());
676 jsr166 1.1 }
677     checkUnusedKey(m, k);}},
678     new MapFrobber() {void frob(NavigableMap m) {
679     final Iterator<Map.Entry> it = m.entrySet().iterator();
680     while (it.hasNext())
681     if (it.next().getKey().equals(k)) {
682     it.remove();
683     if (maybe(2))
684     THROWS(IllegalStateException.class, remover(it));
685     }
686     checkUnusedKey(m, k);}},
687     };
688    
689     return randomRemovers[rnd.nextInt(randomRemovers.length)];
690     }
691    
692     static SetFrobber randomRemover(NavigableSet s) {
693     final Integer e = usedElt(s);
694    
695     final SetFrobber[] randomRemovers = {
696     new SetFrobber() {void frob(NavigableSet s) {
697     Object e = s.first();
698     equal(s.pollFirst(), e);
699     checkUnusedElt(s, e);}},
700     new SetFrobber() {void frob(NavigableSet s) {
701     Object e = s.last();
702     equal(s.pollLast(), e);
703     checkUnusedElt(s, e);}},
704     new SetFrobber() {void frob(NavigableSet s) {
705     check(s.remove(e));
706     checkUnusedElt(s, e);}},
707     new SetFrobber() {void frob(NavigableSet s) {
708     s.subSet(e, true, e, true).clear();
709     checkUnusedElt(s, e);}},
710     new SetFrobber() {void frob(NavigableSet s) {
711     s.descendingSet().subSet(e, true, e, true).clear();
712     checkUnusedElt(s, e);}},
713     new SetFrobber() {void frob(NavigableSet s) {
714     final Iterator it = s.iterator();
715     while (it.hasNext())
716     if (it.next().equals(e)) {
717     it.remove();
718     if (maybe(2))
719     THROWS(IllegalStateException.class,
720 jsr166 1.5 () -> it.remove());
721 jsr166 1.1 }
722     checkUnusedElt(s, e);}},
723     new SetFrobber() {void frob(NavigableSet s) {
724     final Iterator it = s.descendingSet().iterator();
725     while (it.hasNext())
726     if (it.next().equals(e)) {
727     it.remove();
728     if (maybe(2))
729     THROWS(IllegalStateException.class,
730 jsr166 1.5 () -> it.remove());
731 jsr166 1.1 }
732     checkUnusedElt(s, e);}},
733     new SetFrobber() {void frob(NavigableSet s) {
734     final Iterator it = s.descendingIterator();
735     while (it.hasNext())
736     if (it.next().equals(e)) {
737     it.remove();
738     if (maybe(2))
739     THROWS(IllegalStateException.class,
740 jsr166 1.5 () -> it.remove());
741 jsr166 1.1 }
742     checkUnusedElt(s, e);}}
743     };
744    
745     return randomRemovers[rnd.nextInt(randomRemovers.length)];
746     }
747    
748     static void lockStep(NavigableMap m1,
749     NavigableMap m2) {
750     if (! (thorough || maybe(3))) return;
751     if (maybe(4)) m1 = serialClone(m1);
752     if (maybe(4)) m2 = serialClone(m2);
753    
754     List<NavigableMap> maps = Arrays.asList(m1, m2);
755     for (NavigableMap m : maps) testEmptyMap(m);
756 jsr166 1.6 final Set<Integer> ints = new HashSet<>();
757 jsr166 1.1 while (ints.size() < size)
758     ints.add(rnd.nextInt(1024));
759     final Integer[] elts = ints.toArray(new Integer[size]);
760     for (int i = 0; i < size; i++) {
761     MapFrobber adder = randomAdder(m1);
762     for (final NavigableMap m : maps) {
763     adder.frob(m);
764     equal(m.size(), i+1);
765     }
766     equalNavigableMaps(m1, m2);
767     }
768     for (final NavigableMap m : maps) {
769     final Object e = usedKey(m);
770     THROWS(IllegalArgumentException.class,
771 jsr166 1.5 () -> {m.subMap(e,true,e,false)
772     .subMap(e,true,e,true);},
773     () -> {m.subMap(e,false,e,true)
774     .subMap(e,true,e,true);},
775     () -> m.tailMap(e,false).tailMap(e,true),
776     () -> m.headMap(e,false).headMap(e,true));
777 jsr166 1.1 }
778     //System.out.printf("%s%n", m1);
779     for (int i = size; i > 0; i--) {
780     MapFrobber remover = randomRemover(m1);
781     for (final NavigableMap m : maps) {
782     remover.frob(m);
783     equal(m.size(), i-1);
784     }
785     equalNavigableMaps(m1, m2);
786     }
787     for (NavigableMap m : maps) testEmptyMap(m);
788     }
789    
790     static void lockStep(NavigableSet s1,
791     NavigableSet s2) {
792     if (! (thorough || maybe(3))) return;
793     if (maybe(4)) s1 = serialClone(s1);
794     if (maybe(4)) s2 = serialClone(s2);
795    
796     List<NavigableSet> sets = Arrays.asList(s1, s2);
797     for (NavigableSet s : sets) testEmptySet(s);
798 jsr166 1.6 final Set<Integer> ints = new HashSet<>();
799 jsr166 1.1 while (ints.size() < size)
800     ints.add(rnd.nextInt(1024));
801     final Integer[] elts = ints.toArray(new Integer[size]);
802     for (int i = 0; i < size; i++) {
803     SetFrobber adder = randomAdder(s1);
804     for (final NavigableSet s : sets) {
805     adder.frob(s);
806     equal(s.size(), i+1);
807     }
808     equalNavigableSets(s1, s2);
809     }
810     for (final NavigableSet s : sets) {
811     final Object e = usedElt(s);
812     THROWS(IllegalArgumentException.class,
813 jsr166 1.5 () -> {s.subSet(e,true,e,false)
814     .subSet(e,true,e,true);},
815     () -> {s.subSet(e,false,e,true)
816     .subSet(e,true,e,true);},
817     () -> s.tailSet(e,false).tailSet(e,true),
818     () -> s.headSet(e,false).headSet(e,true));
819 jsr166 1.1 }
820     //System.out.printf("%s%n", s1);
821     for (int i = size; i > 0; i--) {
822     SetFrobber remover = randomRemover(s1);
823     for (final NavigableSet s : sets) {
824     remover.frob(s);
825     equal(s.size(), i-1);
826     }
827     equalNavigableSets(s1, s2);
828     }
829     for (NavigableSet s : sets) testEmptySet(s);
830     }
831    
832     //--------------------- Infrastructure ---------------------------
833     static volatile int passed = 0, failed = 0;
834     static void pass() { passed++; }
835     static void fail() { failed++; Thread.dumpStack(); }
836     static void fail(String msg) { System.out.println(msg); fail(); }
837     static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
838     static void check(boolean cond) { if (cond) pass(); else fail(); }
839     static void equal(Object x, Object y) {
840     if (x == null ? y == null : x.equals(y)) pass();
841     else {System.out.println(x + " not equal to " + y); fail();}}
842     static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}
843     public static void main(String[] args) throws Throwable {
844     try { realMain(args); } catch (Throwable t) { unexpected(t); }
845    
846     System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
847     if (failed > 0) throw new Exception("Some tests failed");
848     }
849 jsr166 1.5 interface Fun {void f() throws Throwable;}
850 jsr166 1.1 static void THROWS(Class<? extends Throwable> k, Fun... fs) {
851 jsr166 1.7 for (Fun f : fs)
852     try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
853     catch (Throwable t) {
854     if (k.isAssignableFrom(t.getClass())) pass();
855     else unexpected(t);}}
856 jsr166 1.1 static byte[] serializedForm(Object obj) {
857     try {
858     ByteArrayOutputStream baos = new ByteArrayOutputStream();
859     new ObjectOutputStream(baos).writeObject(obj);
860     return baos.toByteArray();
861     } catch (IOException e) { throw new RuntimeException(e); }}
862     static Object readObject(byte[] bytes)
863     throws IOException, ClassNotFoundException {
864     InputStream is = new ByteArrayInputStream(bytes);
865     return new ObjectInputStream(is).readObject();}
866     @SuppressWarnings("unchecked")
867     static <T> T serialClone(T obj) {
868     try { return (T) readObject(serializedForm(obj)); }
869 jsr166 1.5 catch (Error|RuntimeException e) { throw e; }
870     catch (Throwable e) { throw new RuntimeException(e); }
871     }
872 jsr166 1.1 }