ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/jtreg/util/NavigableMap/LockStep.java
Revision: 1.4
Committed: Tue Sep 8 19:48:05 2015 UTC (8 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.3: +5 -5 lines
Log Message:
whitespace

File Contents

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