ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/jtreg/util/NavigableMap/LockStep.java
Revision: 1.1
Committed: Tue Sep 1 01:26:47 2009 UTC (14 years, 9 months ago) by jsr166
Branch: MAIN
Log Message:
import tests from openjdk

File Contents

# Content
1 /*
2 * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
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 static abstract class MapFrobber { abstract void frob(NavigableMap m); }
505 static abstract class SetFrobber { abstract void frob(NavigableSet m); }
506
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 static abstract class Fun {abstract void f() throws Throwable;}
817 static void THROWS(Class<? extends Throwable> k, Fun... fs) {
818 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 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 }