1 /*
2 * Copyright (c) 2005, 2025, Oracle and/or its affiliates. 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 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 */
23
24 /*
25 * @test
26 * @bug 6207984 6272521 6192552 6269713 6197726 6260652 5073546 4137464
27 * 4155650 4216399 4294891 6282555 6318622 6355327 6383475 6420753
28 * 6431845 4802633 6570566 6570575 6570631 6570924 6691185 6691215
29 * 4802647 7123424 8024709 8193128 8327858
30 * @summary Run many tests on many Collection and Map implementations
31 * @author Martin Buchholz
32 * @modules java.base/java.util:open
33 * @enablePreview
34 * @run main MOAT
35 * @key randomness
36 */
37
38 /* Mother Of All (Collection) Tests
39 *
40 * Testing of collection classes is often spotty, because many tests
41 * need to be performed on many implementations, but the onus on
42 * writing the tests falls on the engineer introducing the new
43 * implementation.
44 *
45 * The idea of this mega-test is that:
46 *
47 * An engineer adding a new collection implementation could simply add
48 * their new implementation to a list of implementations in this
49 * test's main method. Any general purpose Collection<Integer> or
50 * Map<Integer,Integer> class is appropriate.
51 *
52 * An engineer fixing a regression could add their regression test here and
53 * simultaneously test all other implementations.
54 */
55
56 import java.io.*;
57 import java.util.*;
58 import java.util.concurrent.*;
59 import static java.util.Collections.*;
60 import java.lang.reflect.*;
61 import java.util.stream.Collectors;
62 import java.util.stream.Stream;
63
64 public class MOAT {
65 // Collections under test must not be initialized to contain this value,
66 // and maps under test must not contain this value as a key.
67 // It's used as a sentinel for absent-element testing.
68 static final int ABSENT_VALUE = 778347983;
69
70 static final Integer[] integerArray;
71 static {
72 Integer[] ia = new Integer[20];
73 // fill with 1..20 inclusive
74 for (int i = 0; i < ia.length; i++) {
75 ia[i] = i + 1;
76 }
77 integerArray = ia;
78 }
79
80 public static void realMain(String[] args) {
81
82 testCollection(new NewAbstractCollection<Integer>());
83 testCollection(new NewAbstractSet<Integer>());
84 testCollection(new LinkedHashSet<Integer>());
85 testCollection(new HashSet<Integer>());
86 testCollection(new Vector<Integer>());
87 testCollection(new Vector<Integer>().subList(0,0));
88 testCollection(new ArrayDeque<Integer>());
89 testCollection(new ArrayList<Integer>());
90 testCollection(new ArrayList<Integer>().subList(0,0));
91 testCollection(new LinkedList<Integer>());
92 testCollection(new LinkedList<Integer>().subList(0,0));
93 testCollection(new TreeSet<Integer>());
94 testCollection(Collections.checkedList(new ArrayList<Integer>(), Integer.class));
95 testCollection(Collections.synchronizedList(new ArrayList<Integer>()));
96 testCollection(Collections.checkedSet(new HashSet<Integer>(), Integer.class));
97 testCollection(Collections.checkedSortedSet(new TreeSet<Integer>(), Integer.class));
98 testCollection(Collections.checkedNavigableSet(new TreeSet<Integer>(), Integer.class));
99 testCollection(Collections.synchronizedSet(new HashSet<Integer>()));
100 testCollection(Collections.synchronizedSortedSet(new TreeSet<Integer>()));
101 testCollection(Collections.synchronizedNavigableSet(new TreeSet<Integer>()));
102
103 testCollection(new CopyOnWriteArrayList<Integer>());
104 testCollection(new CopyOnWriteArrayList<Integer>().subList(0,0));
105 testCollection(new CopyOnWriteArraySet<Integer>());
106 testCollection(new PriorityQueue<Integer>());
107 testCollection(new PriorityBlockingQueue<Integer>());
108 testCollection(new ArrayBlockingQueue<Integer>(20));
109 testCollection(new LinkedBlockingQueue<Integer>(20));
110 testCollection(new LinkedBlockingDeque<Integer>(20));
111 testCollection(new ConcurrentLinkedDeque<Integer>());
112 testCollection(new ConcurrentLinkedQueue<Integer>());
113 testCollection(new LinkedTransferQueue<Integer>());
114 testCollection(new ConcurrentSkipListSet<Integer>());
115 testCollection(Arrays.asList(new Integer(42)));
116 testCollection(Arrays.asList(1,2,3));
117 testCollection(nCopies(25,1));
118 testImmutableList(nCopies(25,1));
119
120 testMap(new HashMap<Integer,Integer>());
121 testMap(new LinkedHashMap<Integer,Integer>());
122
123 // TODO: Add reliable support for WeakHashMap.
124 // This test is subject to very rare failures because the GC
125 // may remove unreferenced-keys from the map at any time.
126 // testMap(new WeakHashMap<Integer,Integer>());
127
128 testMap(new IdentityHashMap<Integer,Integer>());
129 testMap(new TreeMap<Integer,Integer>());
130 testMap(new Hashtable<Integer,Integer>());
131 testMap(new ConcurrentHashMap<Integer,Integer>(10, 0.5f));
132 testMap(new ConcurrentSkipListMap<Integer,Integer>());
133 testMap(Collections.checkedMap(new HashMap<Integer,Integer>(), Integer.class, Integer.class));
134 testMap(Collections.checkedSortedMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
135 testMap(Collections.checkedNavigableMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
136 testMap(Collections.synchronizedMap(new HashMap<Integer,Integer>()));
137 testMap(Collections.synchronizedSortedMap(new TreeMap<Integer,Integer>()));
138 testMap(Collections.synchronizedNavigableMap(new TreeMap<Integer,Integer>()));
139
140 // Unmodifiable wrappers
141 testImmutableSet(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))), 99);
142 testImmutableSet(AccessFlag.maskToAccessFlags(0, AccessFlag.Location.CLASS), AccessFlag.ABSTRACT);
143 testImmutableSet(AccessFlag.maskToAccessFlags(Modifier.PUBLIC | Modifier.STATIC | Modifier.SYNCHRONIZED, AccessFlag.Location.METHOD), AccessFlag.ABSTRACT);
144 testImmutableList(unmodifiableList(Arrays.asList(1,2,3)));
145 testImmutableMap(unmodifiableMap(Collections.singletonMap(1,2)));
146 testImmutableSeqColl(unmodifiableSequencedCollection(Arrays.asList(1,2,3)), 99);
147 testImmutableSeqColl(unmodifiableSequencedSet(new LinkedHashSet<>(Arrays.asList(1,2,3))), 99);
148 var lhm = new LinkedHashMap<Integer,Integer>(); lhm.put(1,2); lhm.put(3, 4);
149 testImmutableSeqMap(unmodifiableSequencedMap(lhm));
150 testCollMutatorsAlwaysThrow(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))));
151 testCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
152 testEmptyCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
153 testListMutatorsAlwaysThrow(unmodifiableList(Arrays.asList(1,2,3)));
154 testListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
155 testEmptyListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
156 testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.singletonMap(1,2)));
157 testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));
158 testEmptyMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));
159
160 // Empty collections
161 final List<Integer> emptyArray = Arrays.asList(new Integer[]{});
162 testCollection(emptyArray);
163 testEmptyList(emptyArray);
164 THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1));
165 THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1));
166
167 List<Integer> noOne = nCopies(0,1);
168 testCollection(noOne);
169 testEmptyList(noOne);
170 testImmutableList(noOne);
171
172 Set<Integer> emptySet = emptySet();
173 testCollection(emptySet);
174 testEmptySet(emptySet);
175 testEmptySet(EMPTY_SET);
176 testEmptySet(Collections.emptySet());
177 testEmptySet(Collections.emptySortedSet());
178 testEmptySet(Collections.emptyNavigableSet());
179 testImmutableSet(emptySet, 99);
180
181 List<Integer> emptyList = emptyList();
182 testCollection(emptyList);
183 testEmptyList(emptyList);
184 testEmptyList(EMPTY_LIST);
185 testEmptyList(Collections.emptyList());
186 testImmutableList(emptyList);
187
188 Map<Integer,Integer> emptyMap = emptyMap();
189 testMap(emptyMap);
190 testEmptyMap(emptyMap);
191 testEmptyMap(EMPTY_MAP);
192 testEmptyMap(Collections.emptyMap());
193 testEmptyMap(Collections.emptySortedMap());
194 testEmptyMap(Collections.emptyNavigableMap());
195 testImmutableMap(emptyMap);
196 testImmutableMap(Collections.emptyMap());
197 testImmutableMap(Collections.emptySortedMap());
198 testImmutableMap(Collections.emptyNavigableMap());
199
200 // Singleton collections
201 Set<Integer> singletonSet = singleton(1);
202 equal(singletonSet.size(), 1);
203 testCollection(singletonSet);
204 testImmutableSet(singletonSet, 99);
205
206 List<Integer> singletonList = singletonList(1);
207 equal(singletonList.size(), 1);
208 testCollection(singletonList);
209 testImmutableList(singletonList);
210 testImmutableList(singletonList.subList(0,1));
211 testImmutableList(singletonList.subList(0,1).subList(0,1));
212 testEmptyList(singletonList.subList(0,0));
213 testEmptyList(singletonList.subList(0,0).subList(0,0));
214
215 Map<Integer,Integer> singletonMap = singletonMap(1,2);
216 equal(singletonMap.size(), 1);
217 testMap(singletonMap);
218 testImmutableMap(singletonMap);
219
220 // Immutable List
221 testEmptyList(List.of());
222 testEmptyList(List.of().subList(0,0));
223 testEmptyList(StableValue.list(0, i -> i));
224 testEmptyList(StableValue.list(3, i -> i).subList(0, 0));
225 testListMutatorsAlwaysThrow(List.of());
226 testListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
227 testListMutatorsAlwaysThrow(StableValue.list(0, i -> i));
228 testEmptyListMutatorsAlwaysThrow(List.of());
229 testEmptyListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
230 testEmptyListMutatorsAlwaysThrow(StableValue.list(0, i -> i));
231 testEmptyListMutatorsAlwaysThrow(StableValue.list(3, i -> i).subList(0, 0));
232 for (List<Integer> list : Arrays.asList(
233 List.<Integer>of(),
234 List.of(1),
235 List.of(1, 2),
236 List.of(1, 2, 3),
237 List.of(1, 2, 3, 4),
238 List.of(1, 2, 3, 4, 5),
239 List.of(1, 2, 3, 4, 5, 6),
240 List.of(1, 2, 3, 4, 5, 6, 7),
241 List.of(1, 2, 3, 4, 5, 6, 7, 8),
242 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
243 List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
244 List.of(integerArray),
245 Stream.<Integer>empty().toList(),
246 Stream.of(1).toList(),
247 Stream.of(1, 2).toList(),
248 Stream.of(1, 2, 3).toList(),
249 Stream.of(1, 2, 3, 4).toList(),
250 Stream.of((Integer)null).toList(),
251 Stream.of(1, null).toList(),
252 Stream.of(1, null, 3).toList(),
253 Stream.of(1, null, 3, 4).toList(),
254 StableValue.list(0, i -> i),
255 StableValue.list(3, i -> i),
256 StableValue.list(10, i -> i))) {
257 testCollection(list);
258 testImmutableList(list);
259 testListMutatorsAlwaysThrow(list);
260 testImmutableListMutatorsAlwaysThrow(list);
261 if (list.size() >= 1) {
262 // test subLists
263 List<Integer> headList = list.subList(0, list.size() - 1);
264 List<Integer> tailList = list.subList(1, list.size());
265 testCollection(headList);
266 testCollection(tailList);
267 testImmutableList(headList);
268 testImmutableList(tailList);
269 testListMutatorsAlwaysThrow(headList);
270 testListMutatorsAlwaysThrow(tailList);
271 }
272 }
273
274 List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3));
275 testCollection(listCopy);
276 testImmutableList(listCopy);
277 testListMutatorsAlwaysThrow(listCopy);
278
279 List<Integer> listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList());
280 equal(listCollected, List.of(1, 2, 3));
281 testCollection(listCollected);
282 testImmutableList(listCollected);
283 testListMutatorsAlwaysThrow(listCollected);
284
285 // List indexOf / lastIndexOf
286
287 // 0 element
288 System.out.println("testListIndexOf size 0");
289 testListIndexOf(-1, -1);
290
291 System.out.println("testListIndexOf size 1");
292 testListIndexOf(-1, -1, 0);
293 testListIndexOf(0, 0, 1);
294
295 System.out.println("testListIndexOf size 2");
296 testListIndexOf(-1, -1, 0, 0);
297 testListIndexOf(0, 0, 1, 0);
298 testListIndexOf(0, 1, 1, 1);
299 testListIndexOf(1, 1, 0, 1);
300
301
302 System.out.println("testListIndexOf size 3");
303 testListIndexOf(-1, -1, 0, 0, 0);
304 testListIndexOf(0, 0, 1, 0, 0);
305 testListIndexOf(0, 1, 1, 1, 0);
306 testListIndexOf(1, 2, 0, 1, 1);
307 testListIndexOf(2, 2, 0, 0, 1);
308
309 System.out.println("testListIndexOf size N");
310 testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0);
311 testListIndexOf(2, 6, 0, 0, 1, 0, 1, 0, 1);
312 testListIndexOf(4, 4, 0, 0, 0, 0, 1, 0, 0);
313 testListIndexOf(0, 6, 1, 1, 1, 1, 1, 1, 1);
314 testListIndexOf(0, 7, 1, 1, 1, 1, 1, 1, 1, 1);
315 testListIndexOf(0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1);
316 testListIndexOf(0, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
317 testListIndexOf(0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
318 testListIndexOf(0, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
319 testListIndexOf(0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
320 testListIndexOf(12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
321 testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
322
323 // Immutable Set
324 testEmptySet(Set.of());
325 testCollMutatorsAlwaysThrow(Set.of());
326 testEmptyCollMutatorsAlwaysThrow(Set.of());
327 for (Set<Integer> set : Arrays.asList(
328 Set.<Integer>of(),
329 Set.of(1),
330 Set.of(1, 2),
331 Set.of(1, 2, 3),
332 Set.of(1, 2, 3, 4),
333 Set.of(1, 2, 3, 4, 5),
334 Set.of(1, 2, 3, 4, 5, 6),
335 Set.of(1, 2, 3, 4, 5, 6, 7),
336 Set.of(1, 2, 3, 4, 5, 6, 7, 8),
337 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
338 Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
339 Set.of(integerArray))) {
340 testCollection(set);
341 testImmutableSet(set, 99);
342 testCollMutatorsAlwaysThrow(set);
343 }
344
345 Set<Integer> setCopy = Set.copyOf(Arrays.asList(1, 2, 3));
346 testCollection(setCopy);
347 testImmutableSet(setCopy, 99);
348 testCollMutatorsAlwaysThrow(setCopy);
349
350 Set<Integer> setCollected = Stream.of(1, 1, 2, 3, 2, 3)
351 .collect(Collectors.toUnmodifiableSet());
352 equal(setCollected, Set.of(1, 2, 3));
353 testCollection(setCollected);
354 testImmutableSet(setCollected, 99);
355 testCollMutatorsAlwaysThrow(setCollected);
356
357 // Immutable Map
358
359 @SuppressWarnings("unchecked")
360 Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20];
361 for (int i = 0; i < ea.length; i++) {
362 ea[i] = Map.entry(i+1, i+101);
363 }
364
365 testEmptyMap(Map.of());
366 testMapMutatorsAlwaysThrow(Map.of());
367 testEmptyMapMutatorsAlwaysThrow(Map.of());
368 testEmptyMap(StableValue.map(Set.of(), k -> k));
369 testMapMutatorsAlwaysThrow(StableValue.map(Set.of(), k -> k));
370 testEmptyMapMutatorsAlwaysThrow(StableValue.map(Set.of(), k -> k));
371 for (Map<Integer,Integer> map : Arrays.asList(
372 Map.<Integer,Integer>of(),
373 Map.of(1, 101),
374 Map.of(1, 101, 2, 202),
375 Map.of(1, 101, 2, 202, 3, 303),
376 Map.of(1, 101, 2, 202, 3, 303, 4, 404),
377 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505),
378 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606),
379 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707),
380 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808),
381 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909),
382 Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010),
383 Map.ofEntries(ea),
384 StableValue.map(Set.<Integer>of(), k -> k),
385 StableValue.map(Set.of(1), k -> k),
386 StableValue.map(Set.of(1, 2, 3), k -> k))) {
387 testMap(map);
388 testImmutableMap(map);
389 testMapMutatorsAlwaysThrow(map);
390 }
391
392 Map<Integer,Integer> mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303)));
393 testMap(mapCopy);
394 testImmutableMap(mapCopy);
395 testMapMutatorsAlwaysThrow(mapCopy);
396
397 Map<Integer,Integer> mapCollected1 =
398 Stream.of(1, 2, 3)
399 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
400 equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303));
401 testMap(mapCollected1);
402 testImmutableMap(mapCollected1);
403 testMapMutatorsAlwaysThrow(mapCollected1);
404
405 try {
406 Stream.of(1, 1, 2, 3, 2, 3)
407 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
408 fail("duplicates should have thrown an exception");
409 } catch (IllegalStateException ise) {
410 pass();
411 }
412
413 Map<Integer,Integer> mapCollected2 =
414 Stream.of(1, 1, 2, 3, 2, 3)
415 .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum));
416 equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606));
417 testMap(mapCollected2);
418 testImmutableMap(mapCollected2);
419 testMapMutatorsAlwaysThrow(mapCollected2);
420 }
421
422 private static void checkContainsSelf(Collection<Integer> c) {
423 check(c.containsAll(c));
424 check(c.containsAll(Arrays.asList(c.toArray())));
425 check(c.containsAll(Arrays.asList(c.toArray(new Integer[0]))));
426 }
427
428 private static void checkContainsEmpty(Collection<Integer> c) {
429 check(c.containsAll(new ArrayList<Integer>()));
430 }
431
432 private static void checkUnique(Set<Integer> s) {
433 for (Integer i : s) {
434 int count = 0;
435 for (Integer j : s) {
436 if (Objects.equals(i,j))
437 ++count;
438 }
439 check(count == 1);
440 }
441 }
442
443 private static <T> void testEmptyCollection(Collection<T> c) {
444 check(c.isEmpty());
445 equal(c.size(), 0);
446 equal(c.toString(),"[]");
447 equal(c.toArray().length, 0);
448 equal(c.toArray(new Object[0]).length, 0);
449 equal(c.toArray(Object[]::new).length, 0);
450 check(c.toArray(new Object[]{42})[0] == null);
451
452 Object[] a = new Object[1]; a[0] = Boolean.TRUE;
453 equal(c.toArray(a), a);
454 equal(a[0], null);
455 testEmptyIterator(c.iterator());
456 }
457
458 static <T> void testEmptyIterator(final Iterator<T> it) {
459 if (rnd.nextBoolean())
460 check(! it.hasNext());
461
462 THROWS(NoSuchElementException.class, () -> it.next());
463
464 try { it.remove(); }
465 catch (IllegalStateException ignored) { pass(); }
466 catch (UnsupportedOperationException ignored) { pass(); }
467 catch (Throwable t) { unexpected(t); }
468
469 if (rnd.nextBoolean())
470 check(! it.hasNext());
471 }
472
473 private static void testEmptyList(List<?> c) {
474 testEmptyCollection(c);
475 equal(c.hashCode(), 1);
476 equal2(c, Collections.<Integer>emptyList());
477 }
478
479 private static <T> void testEmptySet(Set<T> c) {
480 testEmptyCollection(c);
481 equal(c.hashCode(), 0);
482 equal2(c, Collections.<Integer>emptySet());
483 if (c instanceof NavigableSet<?>)
484 testEmptyIterator(((NavigableSet<T>)c).descendingIterator());
485 }
486
487 private static <T> void testImmutableCollection(final Collection<T> c, T t) {
488 THROWS(UnsupportedOperationException.class,
489 () -> c.add(t),
490 () -> c.addAll(singleton(t)));
491 if (! c.isEmpty()) {
492 final T first = c.iterator().next();
493 THROWS(UnsupportedOperationException.class,
494 () -> c.clear(),
495 () -> c.remove(first),
496 () -> c.removeAll(singleton(first)),
497 () -> c.retainAll(emptyList()));
498 } else {
499 testEmptyIterator(c.iterator());
500 }
501 testForEachMatch(c);
502 testSpliteratorMatch(c);
503 }
504
505 private static <T> void testImmutableSeqColl(final SequencedCollection<T> c, T t) {
506 SequencedCollection<T> r = c.reversed();
507 testImmutableCollection(c, t);
508 testImmutableCollection(r, t);
509 THROWS(UnsupportedOperationException.class,
510 () -> c.addFirst(t),
511 () -> c.addLast(t),
512 () -> r.addFirst(t),
513 () -> r.addLast(t));
514 if (! c.isEmpty()) {
515 THROWS(UnsupportedOperationException.class,
516 () -> c.removeFirst(),
517 () -> c.removeLast(),
518 () -> r.removeFirst(),
519 () -> r.removeLast());
520 }
521 }
522
523 private static <T> void testImmutableSet(final Set<T> c, T t) {
524 testImmutableCollection(c, t);
525 }
526
527 private static <T> void testImmutableSeqSet(final SequencedSet<T> c, T t) {
528 testImmutableSeqColl(c, t);
529 }
530
531 private static void testImmutableList(final List<Integer> c) {
532 testList(c);
533 testImmutableCollection(c, 42);
534 testImmutableSeqColl(c, 42);
535 THROWS(UnsupportedOperationException.class,
536 () -> c.set(0,42),
537 () -> c.add(0,42),
538 () -> c.addAll(0,singleton(86)));
539 if (! c.isEmpty())
540 THROWS(UnsupportedOperationException.class,
541 () -> { Iterator<Integer> it = c.iterator();
542 it.next();
543 it.remove(); },
544 () -> { ListIterator<Integer> it = c.listIterator();
545 it.next();
546 it.remove(); });
547 }
548
549 /**
550 * Test that calling a mutator always throws UOE, even if the mutator
551 * wouldn't actually do anything, given its arguments.
552 *
553 * @param c the collection instance to test
554 */
555 private static void testCollMutatorsAlwaysThrow(Collection<Integer> c) {
556 THROWS(UnsupportedOperationException.class,
557 () -> c.addAll(Collections.emptyList()),
558 () -> c.remove(ABSENT_VALUE),
559 () -> c.removeAll(Collections.emptyList()),
560 () -> c.removeIf(x -> false),
561 () -> c.retainAll(c));
562 }
563
564 // Ensures forEach supplies in the same order as the iterator
565 private static <T> void testForEachMatch(Collection<T> c) {
566 var itr = c.iterator();
567 int[] index = {0};
568 c.forEach(item -> {
569 T itrNext = null;
570 if (!itr.hasNext() || !Objects.equals(itrNext = itr.next(), item)) {
571 fail("forEach and iterator mismatch at " + index[0] + " forEach: " + item + ", itr: " + itrNext);
572 }
573 index[0]++;
574 });
575 if (itr.hasNext()) {
576 fail("forEach and iterator mismatch at tail, extras in itr");
577 }
578 }
579
580 // Ensures spliterator returns in the same order as the iterator
581 private static <T> void testSpliteratorMatch(Collection<T> c) {
582 var itr = c.iterator();
583 var split = c.spliterator();
584 int[] index = {0};
585 split.forEachRemaining(item -> {
586 T itrNext = null;
587 if (!itr.hasNext() || !Objects.equals(itrNext = itr.next(), item)) {
588 fail("iterator and spliterator mismatch at " + index[0] + " spliterator: " + item + ", itr: " + itrNext);
589 }
590 index[0]++;
591 });
592 if (itr.hasNext()) {
593 fail("iterator and spliterator mismatch at tail, extra item in itr");
594 }
595 }
596
597 /**
598 * Test that calling a mutator always throws UOE, even if the mutator
599 * wouldn't actually do anything on an empty collection.
600 *
601 * @param c the collection instance to test, must be empty
602 */
603 private static void testEmptyCollMutatorsAlwaysThrow(Collection<Integer> c) {
604 if (! c.isEmpty()) {
605 fail("collection is not empty");
606 }
607 THROWS(UnsupportedOperationException.class,
608 () -> c.clear());
609 }
610
611 /**
612 * As above, for a list.
613 *
614 * @param c the list instance to test
615 */
616 private static void testListMutatorsAlwaysThrow(List<Integer> c) {
617 testCollMutatorsAlwaysThrow(c);
618 THROWS(UnsupportedOperationException.class,
619 () -> c.addAll(0, Collections.emptyList()));
620 }
621
622 private static void testImmutableListMutatorsAlwaysThrow(List<Integer> c) {
623 THROWS(UnsupportedOperationException.class,
624 c::removeFirst,
625 c::removeLast);
626 }
627
628 /**
629 * As above, for an empty list.
630 *
631 * @param c the list instance to test, must be empty
632 */
633 private static void testEmptyListMutatorsAlwaysThrow(List<Integer> c) {
634 if (! c.isEmpty()) {
635 fail("list is not empty");
636 }
637 testEmptyCollMutatorsAlwaysThrow(c);
638 THROWS(UnsupportedOperationException.class,
639 () -> c.replaceAll(x -> x),
640 () -> c.sort(null));
641 }
642
643 /**
644 * As above, for a map.
645 *
646 * @param m the map instance to test
647 */
648 private static void testMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
649 THROWS(UnsupportedOperationException.class,
650 () -> m.compute(ABSENT_VALUE, (k, v) -> null),
651 () -> m.computeIfAbsent(ABSENT_VALUE, k -> null),
652 () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null),
653 () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null),
654 () -> m.putAll(Collections.emptyMap()),
655 () -> m.remove(ABSENT_VALUE),
656 () -> m.remove(ABSENT_VALUE, 0),
657 () -> m.replace(ABSENT_VALUE, 0),
658 () -> m.replace(ABSENT_VALUE, 0, 1));
659 }
660
661 /**
662 * As above, for an empty map.
663 *
664 * @param map the map instance to test, must be empty
665 */
666 private static void testEmptyMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
667 if (! m.isEmpty()) {
668 fail("map is not empty");
669 }
670 THROWS(UnsupportedOperationException.class,
671 () -> m.clear(),
672 () -> m.replaceAll((k, v) -> v));
673 }
674
675 private static void clear(Collection<Integer> c) {
676 try { c.clear(); }
677 catch (Throwable t) { unexpected(t); }
678 testEmptyCollection(c);
679 }
680
681 private static <K,V> void testEmptyMap(final Map<K,V> m) {
682 check(m.isEmpty());
683 equal(m.size(), 0);
684 equal(m.toString(),"{}");
685 testEmptySet(m.keySet());
686 testEmptySet(m.entrySet());
687 testEmptyCollection(m.values());
688
689 try { check(! m.containsValue(null)); }
690 catch (NullPointerException ignored) { /* OK */ }
691 try { check(! m.containsKey(null)); }
692 catch (NullPointerException ignored) { /* OK */ }
693 check(! m.containsValue(1));
694 check(! m.containsKey(1));
695 }
696
697 private static void testImmutableMapEntry(final Map.Entry<Integer,Integer> me) {
698 Integer key = me.getKey();
699 Integer val = me.getValue();
700 THROWS(UnsupportedOperationException.class,
701 () -> me.setValue(3));
702 equal(key, me.getKey());
703 equal(val, me.getValue());
704 }
705
706 private static void testImmutableMap(final Map<Integer,Integer> m) {
707 THROWS(UnsupportedOperationException.class,
708 () -> m.put(1,1),
709 () -> m.putAll(singletonMap(1,1)));
710 if (! m.isEmpty()) {
711 final Integer first = m.keySet().iterator().next();
712 THROWS(UnsupportedOperationException.class,
713 () -> m.remove(first),
714 () -> m.clear());
715 testImmutableMapEntry(m.entrySet().iterator().next());
716 }
717 testImmutableSet(m.keySet(), 99);
718 testImmutableCollection(m.values(), 99);
719 testImmutableSet(m.entrySet(), Map.entry(42, 43));
720 }
721
722 private static void testImmutableSeqMap(final SequencedMap<Integer,Integer> m) {
723 SequencedMap<Integer,Integer> r = m.reversed();
724 testImmutableMap(m);
725 testImmutableMap(r);
726 THROWS(UnsupportedOperationException.class,
727 () -> m.putFirst(0, 0),
728 () -> m.putLast(0, 0),
729 () -> r.putFirst(0, 0),
730 () -> r.putLast(0, 0));
731 if (! m.isEmpty()) {
732 THROWS(UnsupportedOperationException.class,
733 () -> m.pollFirstEntry(),
734 () -> m.pollLastEntry(),
735 () -> r.pollFirstEntry(),
736 () -> r.pollLastEntry());
737 testImmutableMapEntry(m.sequencedEntrySet().getFirst());
738 testImmutableMapEntry(r.sequencedEntrySet().getFirst());
739 testImmutableMapEntry(m.sequencedEntrySet().reversed().getFirst());
740 testImmutableMapEntry(r.sequencedEntrySet().reversed().getFirst());
741 }
742 testImmutableSeqSet(m.sequencedKeySet(), 99);
743 testImmutableSeqColl(m.sequencedValues(), 99);
744 testImmutableSeqSet(m.sequencedEntrySet(), Map.entry(42, 43));
745 testImmutableSeqSet(r.sequencedKeySet(), 99);
746 testImmutableSeqColl(r.sequencedValues(), 99);
747 testImmutableSeqSet(r.sequencedEntrySet(), Map.entry(42, 43));
748 }
749
750 private static void clear(Map<?,?> m) {
751 try { m.clear(); }
752 catch (Throwable t) { unexpected(t); }
753 testEmptyMap(m);
754 }
755
756 private static void oneElement(Collection<Integer> c) {
757 clear(c);
758 try {
759 check(c.add(-42));
760 equal(c.toString(), "[-42]");
761 if (c instanceof Set) check(! c.add(-42));
762 } catch (Throwable t) { unexpected(t); }
763 check(! c.isEmpty()); check(c.size() == 1);
764 }
765
766 private static boolean supportsAdd(Collection<Integer> c) {
767 try { check(c.add(ABSENT_VALUE)); }
768 catch (UnsupportedOperationException t) { return false; }
769 catch (Throwable t) { unexpected(t); }
770
771 try {
772 check(c.contains(ABSENT_VALUE));
773 check(c.remove(ABSENT_VALUE));
774 } catch (Throwable t) { unexpected(t); }
775 return true;
776 }
777
778 private static boolean supportsRemove(Collection<Integer> c) {
779 try { check(! c.remove(ABSENT_VALUE)); }
780 catch (UnsupportedOperationException t) { return false; }
781 catch (Throwable t) { unexpected(t); }
782 return true;
783 }
784
785 // 6260652: (coll) Arrays.asList(x).toArray().getClass()
786 // should be Object[].class
787 // Fixed in jdk9, but not jdk8 ...
788 static final boolean needToWorkAround6260652 =
789 Arrays.asList("").toArray().getClass() != Object[].class;
790
791 private static void checkFunctionalInvariants(Collection<Integer> c) {
792 try {
793 checkContainsSelf(c);
794 checkContainsEmpty(c);
795 check(c.size() != 0 ^ c.isEmpty());
796 check(! c.contains(ABSENT_VALUE));
797
798 {
799 int size = 0;
800 for (Integer i : c) size++;
801 check(c.size() == size);
802 }
803
804 if (c instanceof Set) {
805 checkUnique((Set<Integer>)c);
806 }
807
808 check(c.toArray().length == c.size());
809 check(c.toArray().getClass() == Object[].class
810 ||
811 (needToWorkAround6260652 &&
812 c.getClass().getName().equals("java.util.Arrays$ArrayList")));
813 for (int size : new int[]{0,1,c.size(), c.size()+1}) {
814 Integer[] a = c.toArray(new Integer[size]);
815 check((size > c.size()) || a.length == c.size());
816 int i = 0; for (Integer j : c) check(a[i++] == j);
817 check((size <= c.size()) || (a[c.size()] == null));
818 check(a.getClass() == Integer[].class);
819 }
820
821 {
822 Integer[] a = c.toArray(Integer[]::new);
823 equal(c.size(), a.length);
824 check(a.getClass() == Integer[].class);
825 check(Arrays.equals(c.toArray(new Integer[0]), a));
826 }
827
828 check(c.equals(c));
829 if (c instanceof Serializable) {
830 //System.out.printf("Serializing %s%n", c.getClass().getName());
831 try {
832 Object clone = serialClone(c);
833 equal(c instanceof Serializable,
834 clone instanceof Serializable);
835 equal(c instanceof RandomAccess,
836 clone instanceof RandomAccess);
837 if ((c instanceof List) || (c instanceof Set))
838 equal(c, clone);
839 else
840 equal(new HashSet<Integer>(c),
841 new HashSet<Integer>(serialClone(c)));
842 } catch (Error xxx) {
843 if (! (xxx.getCause() instanceof NotSerializableException))
844 throw xxx;
845 }
846 }
847 }
848 catch (Throwable t) { unexpected(t); }
849 }
850
851 //----------------------------------------------------------------
852 // If add(null) succeeds, contains(null) & remove(null) should succeed
853 //----------------------------------------------------------------
854 private static void testNullElement(Collection<Integer> c) {
855
856 try {
857 check(c.add(null));
858 if (c.size() == 1)
859 equal(c.toString(), "[null]");
860 try {
861 checkFunctionalInvariants(c);
862 check(c.contains(null));
863 check(c.remove(null));
864 }
865 catch (Throwable t) { unexpected(t); }
866 }
867 catch (NullPointerException e) { /* OK */ }
868 catch (Throwable t) { unexpected(t); }
869 }
870
871 //----------------------------------------------------------------
872 // If add("x") succeeds, contains("x") & remove("x") should succeed
873 //----------------------------------------------------------------
874 @SuppressWarnings("unchecked")
875 private static void testStringElement(Collection<Integer> c) {
876 Collection x = (Collection)c; // Make type-unsafe
877 try {
878 check(x.add("x"));
879 try {
880 check(x.contains("x"));
881 check(x.remove("x"));
882 } catch (Throwable t) { unexpected(t); }
883 }
884 catch (ClassCastException e) { /* OK */ }
885 catch (Throwable t) { unexpected(t); }
886 }
887
888 private static void testConcurrentCollection(Collection<Integer> c) {
889 try {
890 c.add(1);
891 Iterator<Integer> it = c.iterator();
892 check(it.hasNext());
893 clear(c);
894 check(it.next() instanceof Integer); // No CME
895 check(c.isEmpty());
896 }
897 catch (Throwable t) { unexpected(t); }
898 }
899
900 private static void testQueue(Queue<Integer> q) {
901 q.clear();
902 for (int i = 0; i < 5; i++) {
903 testQueueAddRemove(q, null);
904 testQueueAddRemove(q, 537);
905 q.add(i);
906 }
907 equal(q.size(), 5);
908 checkFunctionalInvariants(q);
909 q.poll();
910 equal(q.size(), 4);
911 checkFunctionalInvariants(q);
912 if ((q instanceof LinkedBlockingQueue) ||
913 (q instanceof LinkedBlockingDeque) ||
914 (q instanceof ConcurrentLinkedDeque) ||
915 (q instanceof ConcurrentLinkedQueue)) {
916 testQueueIteratorRemove(q);
917 }
918 }
919
920 private static void testQueueAddRemove(final Queue<Integer> q,
921 final Integer e) {
922 final List<Integer> originalContents = new ArrayList<>(q);
923 final boolean isEmpty = q.isEmpty();
924 final boolean isList = (q instanceof List);
925 final List asList = isList ? (List) q : null;
926 check(!q.contains(e));
927 try {
928 q.add(e);
929 } catch (NullPointerException npe) {
930 check(e == null);
931 return; // Null elements not supported
932 }
933 check(q.contains(e));
934 check(q.remove(e));
935 check(!q.contains(e));
936 equal(new ArrayList<Integer>(q), originalContents);
937
938 if (q instanceof Deque<?>) {
939 final Deque<Integer> deq = (Deque<Integer>) q;
940 final List<Integer> singleton = Collections.singletonList(e);
941
942 // insert, query, remove element at head
943 if (isEmpty) {
944 THROWS(NoSuchElementException.class,
945 () -> deq.getFirst(),
946 () -> deq.element(),
947 () -> deq.iterator().next());
948 check(deq.peekFirst() == null);
949 check(deq.peek() == null);
950 } else {
951 check(deq.getFirst() != e);
952 check(deq.element() != e);
953 check(deq.iterator().next() != e);
954 check(deq.peekFirst() != e);
955 check(deq.peek() != e);
956 }
957 check(!deq.contains(e));
958 check(!deq.removeFirstOccurrence(e));
959 check(!deq.removeLastOccurrence(e));
960 if (isList) {
961 check(asList.indexOf(e) == -1);
962 check(asList.lastIndexOf(e) == -1);
963 }
964 switch (rnd.nextInt(isList ? 4 : 3)) {
965 case 0: deq.addFirst(e); break;
966 case 1: check(deq.offerFirst(e)); break;
967 case 2: deq.push(e); break;
968 case 3: asList.add(0, e); break;
969 default: throw new AssertionError();
970 }
971 check(deq.peekFirst() == e);
972 check(deq.getFirst() == e);
973 check(deq.element() == e);
974 check(deq.peek() == e);
975 check(deq.iterator().next() == e);
976 check(deq.contains(e));
977 if (isList) {
978 check(asList.get(0) == e);
979 check(asList.indexOf(e) == 0);
980 check(asList.lastIndexOf(e) == 0);
981 check(asList.subList(0, 1).equals(singleton));
982 }
983 switch (rnd.nextInt(isList ? 11 : 9)) {
984 case 0: check(deq.pollFirst() == e); break;
985 case 1: check(deq.removeFirst() == e); break;
986 case 2: check(deq.remove() == e); break;
987 case 3: check(deq.pop() == e); break;
988 case 4: check(deq.removeFirstOccurrence(e)); break;
989 case 5: check(deq.removeLastOccurrence(e)); break;
990 case 6: check(deq.remove(e)); break;
991 case 7: check(deq.removeAll(singleton)); break;
992 case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
993 case 9: asList.remove(0); break;
994 case 10: asList.subList(0, 1).clear(); break;
995 default: throw new AssertionError();
996 }
997 if (isEmpty) {
998 THROWS(NoSuchElementException.class,
999 () -> deq.getFirst(),
1000 () -> deq.element(),
1001 () -> deq.iterator().next());
1002 check(deq.peekFirst() == null);
1003 check(deq.peek() == null);
1004 } else {
1005 check(deq.getFirst() != e);
1006 check(deq.element() != e);
1007 check(deq.iterator().next() != e);
1008 check(deq.peekFirst() != e);
1009 check(deq.peek() != e);
1010 }
1011 check(!deq.contains(e));
1012 check(!deq.removeFirstOccurrence(e));
1013 check(!deq.removeLastOccurrence(e));
1014 if (isList) {
1015 check(isEmpty || asList.get(0) != e);
1016 check(asList.indexOf(e) == -1);
1017 check(asList.lastIndexOf(e) == -1);
1018 }
1019 equal(new ArrayList<Integer>(deq), originalContents);
1020
1021 // insert, query, remove element at tail
1022 if (isEmpty) {
1023 check(deq.peekLast() == null);
1024 THROWS(NoSuchElementException.class, () -> deq.getLast());
1025 } else {
1026 check(deq.peekLast() != e);
1027 check(deq.getLast() != e);
1028 }
1029 switch (rnd.nextInt(isList ? 6 : 4)) {
1030 case 0: deq.addLast(e); break;
1031 case 1: check(deq.offerLast(e)); break;
1032 case 2: check(deq.add(e)); break;
1033 case 3: deq.addAll(singleton); break;
1034 case 4: asList.addAll(deq.size(), singleton); break;
1035 case 5: asList.add(deq.size(), e); break;
1036 default: throw new AssertionError();
1037 }
1038 check(deq.peekLast() == e);
1039 check(deq.getLast() == e);
1040 check(deq.contains(e));
1041 if (isList) {
1042 ListIterator it = asList.listIterator(asList.size());
1043 check(it.previous() == e);
1044 check(asList.get(asList.size() - 1) == e);
1045 check(asList.indexOf(e) == asList.size() - 1);
1046 check(asList.lastIndexOf(e) == asList.size() - 1);
1047 int size = asList.size();
1048 check(asList.subList(size - 1, size).equals(singleton));
1049 }
1050 switch (rnd.nextInt(isList ? 8 : 6)) {
1051 case 0: check(deq.pollLast() == e); break;
1052 case 1: check(deq.removeLast() == e); break;
1053 case 2: check(deq.removeFirstOccurrence(e)); break;
1054 case 3: check(deq.removeLastOccurrence(e)); break;
1055 case 4: check(deq.remove(e)); break;
1056 case 5: check(deq.removeAll(singleton)); break;
1057 case 6: asList.remove(asList.size() - 1); break;
1058 case 7:
1059 ListIterator it = asList.listIterator(asList.size());
1060 it.previous();
1061 it.remove();
1062 break;
1063 default: throw new AssertionError();
1064 }
1065 if (isEmpty) {
1066 check(deq.peekLast() == null);
1067 THROWS(NoSuchElementException.class, () -> deq.getLast());
1068 } else {
1069 check(deq.peekLast() != e);
1070 check(deq.getLast() != e);
1071 }
1072 check(!deq.contains(e));
1073 equal(new ArrayList<Integer>(deq), originalContents);
1074
1075 // Test operations on empty deque
1076 switch (rnd.nextInt(isList ? 4 : 2)) {
1077 case 0: deq.clear(); break;
1078 case 1:
1079 Iterator it = deq.iterator();
1080 while (it.hasNext()) {
1081 it.next();
1082 it.remove();
1083 }
1084 break;
1085 case 2: asList.subList(0, asList.size()).clear(); break;
1086 case 3:
1087 ListIterator lit = asList.listIterator(asList.size());
1088 while (lit.hasPrevious()) {
1089 lit.previous();
1090 lit.remove();
1091 }
1092 break;
1093 default: throw new AssertionError();
1094 }
1095 testEmptyCollection(deq);
1096 check(!deq.iterator().hasNext());
1097 if (isList) {
1098 check(!asList.listIterator().hasPrevious());
1099 THROWS(NoSuchElementException.class,
1100 () -> asList.listIterator().previous());
1101 }
1102 THROWS(NoSuchElementException.class,
1103 () -> deq.iterator().next(),
1104 () -> deq.element(),
1105 () -> deq.getFirst(),
1106 () -> deq.getLast(),
1107 () -> deq.pop(),
1108 () -> deq.remove(),
1109 () -> deq.removeFirst(),
1110 () -> deq.removeLast());
1111
1112 check(deq.poll() == null);
1113 check(deq.pollFirst() == null);
1114 check(deq.pollLast() == null);
1115 check(deq.peek() == null);
1116 check(deq.peekFirst() == null);
1117 check(deq.peekLast() == null);
1118 check(!deq.removeFirstOccurrence(e));
1119 check(!deq.removeLastOccurrence(e));
1120
1121 check(deq.addAll(originalContents) == !isEmpty);
1122 equal(new ArrayList<Integer>(deq), originalContents);
1123 check(!deq.addAll(Collections.<Integer>emptyList()));
1124 equal(new ArrayList<Integer>(deq), originalContents);
1125 }
1126 }
1127
1128 private static void testQueueIteratorRemove(Queue<Integer> q) {
1129 System.err.printf("testQueueIteratorRemove %s%n",
1130 q.getClass().getSimpleName());
1131 q.clear();
1132 for (int i = 0; i < 5; i++)
1133 q.add(i);
1134 Iterator<Integer> it = q.iterator();
1135 check(it.hasNext());
1136 for (int i = 3; i >= 0; i--)
1137 q.remove(i);
1138 equal(it.next(), 0);
1139 equal(it.next(), 4);
1140
1141 q.clear();
1142 for (int i = 0; i < 5; i++)
1143 q.add(i);
1144 it = q.iterator();
1145 equal(it.next(), 0);
1146 check(it.hasNext());
1147 for (int i = 1; i < 4; i++)
1148 q.remove(i);
1149 equal(it.next(), 1);
1150 equal(it.next(), 4);
1151 }
1152
1153 // for any array of integer values, check that the result of lastIndexOf(1)
1154 // and indexOf(1) match assumptions for all types of List<Integer> we can
1155 // construct
1156 private static void testListIndexOf(final int index,
1157 final int lastIndex,
1158 final Integer ... values) {
1159 if (values.length == 0) {
1160 checkListIndexOf(emptyList(), index, lastIndex);
1161 } else if (values.length == 1) {
1162 checkListIndexOf(singletonList(values[0]), index, lastIndex);
1163 checkListIndexOf(nCopies(25, values[0]), index, lastIndex == 0 ? 24 : -1);
1164 }
1165 List<Integer> l = List.of(values);
1166 checkListIndexOf(l, index, lastIndex);
1167 checkListIndexOf(Arrays.asList(values), index, lastIndex);
1168 checkListIndexOf(new ArrayList(l), index, lastIndex);
1169 checkListIndexOf(new LinkedList(l), index, lastIndex);
1170 checkListIndexOf(new Vector(l), index, lastIndex);
1171 checkListIndexOf(new CopyOnWriteArrayList(l), index, lastIndex);
1172 }
1173
1174 private static void checkListIndexOf(final List<Integer> list,
1175 final int index,
1176 final int lastIndex) {
1177 String msg = list.getClass().toString();
1178 equal(list.indexOf(1), index, msg);
1179 equal(list.lastIndexOf(1), lastIndex, msg);
1180 equal(list.subList(0, list.size()).indexOf(1), index, msg);
1181 equal(list.subList(0, list.size()).lastIndexOf(1), lastIndex, msg);
1182 }
1183
1184 private static void testList(final List<Integer> l) {
1185 //----------------------------------------------------------------
1186 // 4802633: (coll) AbstractList.addAll(-1,emptyCollection)
1187 // doesn't throw IndexOutOfBoundsException
1188 //----------------------------------------------------------------
1189 try {
1190 l.addAll(-1, Collections.<Integer>emptyList());
1191 fail("Expected IndexOutOfBoundsException not thrown");
1192 }
1193 catch (UnsupportedOperationException ignored) {/* OK */}
1194 catch (IndexOutOfBoundsException ignored) {/* OK */}
1195 catch (Throwable t) { unexpected(t); }
1196
1197 // equal(l instanceof Serializable,
1198 // l.subList(0,0) instanceof Serializable);
1199 if (l.subList(0,0) instanceof Serializable)
1200 check(l instanceof Serializable);
1201
1202 equal(l instanceof RandomAccess,
1203 l.subList(0,0) instanceof RandomAccess);
1204
1205 l.iterator();
1206 l.listIterator();
1207 l.listIterator(0);
1208 l.listIterator(l.size());
1209 THROWS(IndexOutOfBoundsException.class,
1210 () -> l.listIterator(-1),
1211 () -> l.listIterator(l.size() + 1));
1212
1213 if (l instanceof AbstractList) {
1214 try {
1215 int size = l.size();
1216 AbstractList<Integer> abList = (AbstractList<Integer>) l;
1217 Method m = AbstractList.class.getDeclaredMethod("removeRange", new Class[] { int.class, int.class });
1218 m.setAccessible(true);
1219 m.invoke(abList, new Object[] { 0, 0 });
1220 m.invoke(abList, new Object[] { size, size });
1221 equal(size, l.size());
1222 }
1223 catch (UnsupportedOperationException ignored) {/* OK */}
1224 catch (Throwable t) { unexpected(t); }
1225 }
1226
1227 int hashCode = 1;
1228 for (Integer i : l)
1229 hashCode = 31 * hashCode + (i == null ? 0 : i.hashCode());
1230 check(l.hashCode() == hashCode);
1231
1232 var t = new ArrayList<>(l);
1233 check(t.equals(l));
1234 check(l.equals(t));
1235 }
1236
1237 private static void testCollection(Collection<Integer> c) {
1238 try { testCollection1(c); }
1239 catch (Throwable t) { unexpected(t); }
1240 }
1241
1242 private static void testCollection1(Collection<Integer> c) {
1243
1244 System.out.println("\n==> " + c.getClass().getName());
1245
1246 checkFunctionalInvariants(c);
1247
1248 if (! supportsAdd(c)) return;
1249 //System.out.println("add() supported");
1250
1251 if (c instanceof NavigableSet) {
1252 System.out.println("NavigableSet tests...");
1253
1254 NavigableSet<Integer> ns = (NavigableSet<Integer>)c;
1255 testNavigableSet(ns);
1256 testNavigableSet(ns.headSet(6, false));
1257 testNavigableSet(ns.headSet(5, true));
1258 testNavigableSet(ns.tailSet(0, false));
1259 testNavigableSet(ns.tailSet(1, true));
1260 testNavigableSet(ns.subSet(0, false, 5, true));
1261 testNavigableSet(ns.subSet(1, true, 6, false));
1262 }
1263
1264 if (c instanceof Queue)
1265 testQueue((Queue<Integer>)c);
1266
1267 if (c instanceof List)
1268 testList((List<Integer>)c);
1269
1270 if (c instanceof Set) {
1271 int hashCode = 0;
1272 for (Integer i : c)
1273 hashCode = hashCode + (i == null ? 0 : i.hashCode());
1274 check(c.hashCode() == hashCode);
1275 }
1276
1277 check(supportsRemove(c));
1278
1279 try {
1280 oneElement(c);
1281 checkFunctionalInvariants(c);
1282 }
1283 catch (Throwable t) { unexpected(t); }
1284
1285 clear(c); testNullElement(c);
1286 oneElement(c); testNullElement(c);
1287
1288 clear(c); testStringElement(c);
1289 oneElement(c); testStringElement(c);
1290
1291 if (c.getClass().getName().matches(".*concurrent.*"))
1292 testConcurrentCollection(c);
1293
1294 //----------------------------------------------------------------
1295 // The "all" operations should throw NPE when passed null
1296 //----------------------------------------------------------------
1297 {
1298 clear(c);
1299 try {
1300 c.removeAll(null);
1301 fail("Expected NullPointerException");
1302 }
1303 catch (NullPointerException e) { pass(); }
1304 catch (Throwable t) { unexpected(t); }
1305
1306 oneElement(c);
1307 try {
1308 c.removeAll(null);
1309 fail("Expected NullPointerException");
1310 }
1311 catch (NullPointerException e) { pass(); }
1312 catch (Throwable t) { unexpected(t); }
1313
1314 clear(c);
1315 try {
1316 c.retainAll(null);
1317 fail("Expected NullPointerException");
1318 }
1319 catch (NullPointerException e) { pass(); }
1320 catch (Throwable t) { unexpected(t); }
1321
1322 oneElement(c);
1323 try {
1324 c.retainAll(null);
1325 fail("Expected NullPointerException");
1326 }
1327 catch (NullPointerException e) { pass(); }
1328 catch (Throwable t) { unexpected(t); }
1329
1330 oneElement(c);
1331 try {
1332 c.addAll(null);
1333 fail("Expected NullPointerException");
1334 }
1335 catch (NullPointerException e) { pass(); }
1336 catch (Throwable t) { unexpected(t); }
1337
1338 oneElement(c);
1339 try {
1340 c.containsAll(null);
1341 fail("Expected NullPointerException");
1342 }
1343 catch (NullPointerException e) { pass(); }
1344 catch (Throwable t) { unexpected(t); }
1345 }
1346 }
1347
1348 //----------------------------------------------------------------
1349 // Map
1350 //----------------------------------------------------------------
1351 private static void checkFunctionalInvariants(Map<Integer,Integer> m) {
1352 check(m.keySet().size() == m.entrySet().size());
1353 check(m.keySet().size() == m.size());
1354 checkFunctionalInvariants(m.keySet());
1355 checkFunctionalInvariants(m.values());
1356 check(m.size() != 0 ^ m.isEmpty());
1357 check(! m.containsKey(ABSENT_VALUE));
1358
1359 if (m instanceof Serializable) {
1360 //System.out.printf("Serializing %s%n", m.getClass().getName());
1361 try {
1362 Object clone = serialClone(m);
1363 equal(m instanceof Serializable,
1364 clone instanceof Serializable);
1365 equal(m, clone);
1366 } catch (Error xxx) {
1367 if (! (xxx.getCause() instanceof NotSerializableException))
1368 throw xxx;
1369 }
1370 }
1371 }
1372
1373 private static void testMap(Map<Integer,Integer> m) {
1374 System.out.println("\n==> " + m.getClass().getName());
1375
1376 int hashCode = 0;
1377 for (var e : m.entrySet()) {
1378 int entryHash = (e.getKey() == null ? 0 : e.getKey().hashCode()) ^
1379 (e.getValue() == null ? 0 : e.getValue().hashCode());
1380 check(e.hashCode() == entryHash);
1381 hashCode += entryHash;
1382 }
1383 check(m.hashCode() == hashCode);
1384
1385 if (m instanceof ConcurrentMap)
1386 testConcurrentMap((ConcurrentMap<Integer,Integer>) m);
1387
1388 if (m instanceof NavigableMap) {
1389 System.out.println("NavigableMap tests...");
1390
1391 NavigableMap<Integer,Integer> nm =
1392 (NavigableMap<Integer,Integer>) m;
1393 testNavigableMapRemovers(nm);
1394 testNavigableMap(nm);
1395 testNavigableMap(nm.headMap(6, false));
1396 testNavigableMap(nm.headMap(5, true));
1397 testNavigableMap(nm.tailMap(0, false));
1398 testNavigableMap(nm.tailMap(1, true));
1399 testNavigableMap(nm.subMap(1, true, 6, false));
1400 testNavigableMap(nm.subMap(0, false, 5, true));
1401 }
1402
1403 checkFunctionalInvariants(m);
1404
1405 if (supportsClear(m)) {
1406 try { clear(m); }
1407 catch (Throwable t) { unexpected(t); }
1408 }
1409
1410 if (supportsPut(m)) {
1411 try {
1412 check(m.put(3333, 77777) == null);
1413 check(m.put(9134, 74982) == null);
1414 check(m.get(9134) == 74982);
1415 check(m.put(9134, 1382) == 74982);
1416 check(m.get(9134) == 1382);
1417 check(m.size() == 2);
1418 checkFunctionalInvariants(m);
1419 checkNPEConsistency(m);
1420 }
1421 catch (Throwable t) { unexpected(t); }
1422 }
1423 }
1424
1425 private static boolean supportsPut(Map<Integer,Integer> m) {
1426 // We're asking for .equals(...) semantics
1427 if (m instanceof IdentityHashMap) return false;
1428
1429 try { check(m.put(ABSENT_VALUE,12735) == null); }
1430 catch (UnsupportedOperationException t) { return false; }
1431 catch (Throwable t) { unexpected(t); }
1432
1433 try {
1434 check(m.containsKey(ABSENT_VALUE));
1435 check(m.remove(ABSENT_VALUE) != null);
1436 } catch (Throwable t) { unexpected(t); }
1437 return true;
1438 }
1439
1440 private static boolean supportsClear(Map<?,?> m) {
1441 try { m.clear(); }
1442 catch (UnsupportedOperationException t) { return false; }
1443 catch (Throwable t) { unexpected(t); }
1444 return true;
1445 }
1446
1447 //----------------------------------------------------------------
1448 // ConcurrentMap
1449 //----------------------------------------------------------------
1450 private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) {
1451 System.out.println("ConcurrentMap tests...");
1452
1453 try {
1454 clear(m);
1455
1456 check(m.putIfAbsent(18357,7346) == null);
1457 check(m.containsKey(18357));
1458 check(m.putIfAbsent(18357,8263) == 7346);
1459 try { m.putIfAbsent(18357,null); fail("NPE"); }
1460 catch (NullPointerException t) { }
1461 check(m.containsKey(18357));
1462
1463 check(! m.replace(18357,8888,7777));
1464 check(m.containsKey(18357));
1465 try { m.replace(18357,null,7777); fail("NPE"); }
1466 catch (NullPointerException t) { }
1467 check(m.containsKey(18357));
1468 check(m.get(18357) == 7346);
1469 check(m.replace(18357,7346,5555));
1470 check(m.replace(18357,5555,7346));
1471 check(m.get(18357) == 7346);
1472
1473 check(m.replace(92347,7834) == null);
1474 try { m.replace(18357,null); fail("NPE"); }
1475 catch (NullPointerException t) { }
1476 check(m.replace(18357,7346) == 7346);
1477 check(m.replace(18357,5555) == 7346);
1478 check(m.get(18357) == 5555);
1479 check(m.replace(18357,7346) == 5555);
1480 check(m.get(18357) == 7346);
1481
1482 check(! m.remove(18357,9999));
1483 check(m.get(18357) == 7346);
1484 check(m.containsKey(18357));
1485 check(! m.remove(18357,null)); // 6272521
1486 check(m.get(18357) == 7346);
1487 check(m.remove(18357,7346));
1488 check(m.get(18357) == null);
1489 check(! m.containsKey(18357));
1490 check(m.isEmpty());
1491
1492 m.putIfAbsent(1,2);
1493 check(m.size() == 1);
1494 check(! m.remove(1,null));
1495 check(! m.remove(1,null));
1496 check(! m.remove(1,1));
1497 check(m.remove(1,2));
1498 check(m.isEmpty());
1499
1500 testEmptyMap(m);
1501 }
1502 catch (Throwable t) { unexpected(t); }
1503 }
1504
1505 private static void throwsConsistently(Class<? extends Throwable> k,
1506 Iterable<Fun> fs) {
1507 List<Class<? extends Throwable>> threw = new ArrayList<>();
1508 for (Fun f : fs)
1509 try { f.f(); threw.add(null); }
1510 catch (Throwable t) {
1511 check(k.isAssignableFrom(t.getClass()));
1512 threw.add(t.getClass());
1513 }
1514 if (new HashSet<Object>(threw).size() != 1)
1515 fail(threw.toString());
1516 }
1517
1518 private static <T> void checkNPEConsistency(final Map<T,Integer> m) {
1519 m.clear();
1520 final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap)
1521 ? (ConcurrentMap<T,Integer>) m
1522 : null;
1523 List<Fun> fs = new ArrayList<>();
1524 fs.add(() -> check(! m.containsKey(null)));
1525 fs.add(() -> equal(m.remove(null), null));
1526 fs.add(() -> equal(m.get(null), null));
1527 if (cm != null)
1528 fs.add(() -> check(! cm.remove(null,null)));
1529 throwsConsistently(NullPointerException.class, fs);
1530
1531 fs.clear();
1532 final Map<T,Integer> sm = singletonMap(null,1);
1533 fs.add(() -> { equal(m.put(null,1), null); m.clear();});
1534 fs.add(() -> { m.putAll(sm); m.clear();});
1535 if (cm != null) {
1536 fs.add(() -> check(! cm.remove(null,null)));
1537 fs.add(() -> equal(cm.putIfAbsent(null,1), 1));
1538 fs.add(() -> equal(cm.replace(null,1), null));
1539 fs.add(() -> equal(cm.replace(null,1, 1), 1));
1540 }
1541 throwsConsistently(NullPointerException.class, fs);
1542 }
1543
1544 //----------------------------------------------------------------
1545 // NavigableMap
1546 //----------------------------------------------------------------
1547 private static void
1548 checkNavigableMapKeys(NavigableMap<Integer,Integer> m,
1549 Integer i,
1550 Integer lower,
1551 Integer floor,
1552 Integer ceiling,
1553 Integer higher) {
1554 equal(m.lowerKey(i), lower);
1555 equal(m.floorKey(i), floor);
1556 equal(m.ceilingKey(i), ceiling);
1557 equal(m.higherKey(i), higher);
1558 }
1559
1560 private static void
1561 checkNavigableSetKeys(NavigableSet<Integer> m,
1562 Integer i,
1563 Integer lower,
1564 Integer floor,
1565 Integer ceiling,
1566 Integer higher) {
1567 equal(m.lower(i), lower);
1568 equal(m.floor(i), floor);
1569 equal(m.ceiling(i), ceiling);
1570 equal(m.higher(i), higher);
1571 }
1572
1573 static final Random rnd = new Random();
1574 static void equalNext(final Iterator<?> it, Object expected) {
1575 if (rnd.nextBoolean())
1576 check(it.hasNext());
1577 equal(it.next(), expected);
1578 }
1579
1580 static void equalMaps(Map m1, Map m2) {
1581 equal(m1, m2);
1582 equal(m2, m1);
1583 equal(m1.size(), m2.size());
1584 equal(m1.isEmpty(), m2.isEmpty());
1585 equal(m1.toString(), m2.toString());
1586 check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray()));
1587 }
1588
1589 @SuppressWarnings({"unchecked", "rawtypes"})
1590 static void testNavigableMapRemovers(NavigableMap m)
1591 {
1592 final Map emptyMap = new HashMap();
1593
1594 final Map singletonMap = new HashMap();
1595 singletonMap.put(1, 2);
1596
1597 abstract class NavigableMapView {
1598 abstract NavigableMap view(NavigableMap m);
1599 }
1600
1601 NavigableMapView[] views = {
1602 new NavigableMapView() { NavigableMap view(NavigableMap m) {
1603 return m; }},
1604 new NavigableMapView() { NavigableMap view(NavigableMap m) {
1605 return m.headMap(99, true); }},
1606 new NavigableMapView() { NavigableMap view(NavigableMap m) {
1607 return m.tailMap(-99, false); }},
1608 new NavigableMapView() { NavigableMap view(NavigableMap m) {
1609 return m.subMap(-99, true, 99, false); }},
1610 };
1611
1612 abstract class Remover {
1613 abstract void remove(NavigableMap m, Object k, Object v);
1614 }
1615
1616 Remover[] removers = {
1617 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1618 equal(m.remove(k), v); }},
1619
1620 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1621 equal(m.descendingMap().remove(k), v); }},
1622 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1623 equal(m.descendingMap().headMap(-86, false).remove(k), v); }},
1624 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1625 equal(m.descendingMap().tailMap(86, true).remove(k), v); }},
1626
1627 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1628 equal(m.headMap(86, true).remove(k), v); }},
1629 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1630 equal(m.tailMap(-86, true).remove(k), v); }},
1631 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1632 equal(m.subMap(-86, false, 86, true).remove(k), v); }},
1633
1634 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1635 check(m.keySet().remove(k)); }},
1636 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1637 check(m.navigableKeySet().remove(k)); }},
1638
1639 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1640 check(m.navigableKeySet().headSet(86, true).remove(k)); }},
1641 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1642 check(m.navigableKeySet().tailSet(-86, false).remove(k)); }},
1643 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1644 check(m.navigableKeySet().subSet(-86, true, 86, false)
1645 .remove(k)); }},
1646
1647 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1648 check(m.descendingKeySet().headSet(-86, false).remove(k)); }},
1649 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1650 check(m.descendingKeySet().tailSet(86, true).remove(k)); }},
1651 new Remover() { void remove(NavigableMap m, Object k, Object v) {
1652 check(m.descendingKeySet().subSet(86, true, -86, false)
1653 .remove(k)); }},
1654 };
1655
1656 for (NavigableMapView view : views) {
1657 for (Remover remover : removers) {
1658 try {
1659 m.clear();
1660 equalMaps(m, emptyMap);
1661 equal(m.put(1, 2), null);
1662 equalMaps(m, singletonMap);
1663 NavigableMap v = view.view(m);
1664 remover.remove(v, 1, 2);
1665 equalMaps(m, emptyMap);
1666 } catch (Throwable t) { unexpected(t); }
1667 }
1668 }
1669 }
1670
1671 private static void testNavigableMap(NavigableMap<Integer,Integer> m)
1672 {
1673 clear(m);
1674 checkNavigableMapKeys(m, 1, null, null, null, null);
1675
1676 equal(m.put(1, 2), null);
1677 equal(m.put(3, 4), null);
1678 equal(m.put(5, 9), null);
1679
1680 equal(m.put(1, 2), 2);
1681 equal(m.put(3, 4), 4);
1682 equal(m.put(5, 6), 9);
1683
1684 checkNavigableMapKeys(m, 0, null, null, 1, 1);
1685 checkNavigableMapKeys(m, 1, null, 1, 1, 3);
1686 checkNavigableMapKeys(m, 2, 1, 1, 3, 3);
1687 checkNavigableMapKeys(m, 3, 1, 3, 3, 5);
1688 checkNavigableMapKeys(m, 5, 3, 5, 5, null);
1689 checkNavigableMapKeys(m, 6, 5, 5, null, null);
1690
1691 for (final Iterator<Integer> it :
1692 (Iterator<Integer>[])
1693 new Iterator<?>[] {
1694 m.descendingKeySet().iterator(),
1695 m.navigableKeySet().descendingIterator()}) {
1696 equalNext(it, 5);
1697 equalNext(it, 3);
1698 equalNext(it, 1);
1699 check(! it.hasNext());
1700 THROWS(NoSuchElementException.class, () -> it.next());
1701 }
1702
1703 {
1704 final Iterator<Map.Entry<Integer,Integer>> it
1705 = m.descendingMap().entrySet().iterator();
1706 check(it.hasNext()); equal(it.next().getKey(), 5);
1707 check(it.hasNext()); equal(it.next().getKey(), 3);
1708 check(it.hasNext()); equal(it.next().getKey(), 1);
1709 check(! it.hasNext());
1710 THROWS(NoSuchElementException.class, () -> it.next());
1711 }
1712
1713 prepMapForDescItrTests(m);
1714 checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator());
1715 prepMapForDescItrTests(m);
1716 checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator());
1717 prepMapForDescItrTests(m);
1718 checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator());
1719
1720 prepMapForDescItrTests(m);
1721 checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator());
1722 prepMapForDescItrTests(m);
1723 checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator());
1724 prepMapForDescItrTests(m);
1725 checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator());
1726
1727 prepMapForDescItrTests(m);
1728 checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator());
1729 prepMapForDescItrTests(m);
1730 checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator());
1731 prepMapForDescItrTests(m);
1732 checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator());
1733
1734 prepMapForDescItrTests(m);
1735 checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator());
1736 prepMapForDescItrTests(m);
1737 checkDescItrRmMid(m.values(), m.descendingMap().values().iterator());
1738 prepMapForDescItrTests(m);
1739 checkDescItrRmLast(m.values(), m.descendingMap().values().iterator());
1740
1741 prepMapForDescItrTests(m);
1742 checkDescItrRmFirst((Collection)m.entrySet(),
1743 m.descendingMap().entrySet().iterator());
1744 prepMapForDescItrTests(m);
1745 checkDescItrRmMid((Collection)m.entrySet(),
1746 m.descendingMap().entrySet().iterator());
1747 prepMapForDescItrTests(m);
1748 checkDescItrRmLast((Collection)m.entrySet(),
1749 m.descendingMap().entrySet().iterator());
1750 }
1751
1752 private static void testNavigableSet(NavigableSet<Integer> s) {
1753 clear(s);
1754 checkNavigableSetKeys(s, 1, null, null, null, null);
1755
1756 check(s.add(1));
1757 check(s.add(3));
1758 check(s.add(5));
1759
1760 check(! s.add(1));
1761 check(! s.add(3));
1762 check(! s.add(5));
1763
1764 checkNavigableSetKeys(s, 0, null, null, 1, 1);
1765 checkNavigableSetKeys(s, 1, null, 1, 1, 3);
1766 checkNavigableSetKeys(s, 2, 1, 1, 3, 3);
1767 checkNavigableSetKeys(s, 3, 1, 3, 3, 5);
1768 checkNavigableSetKeys(s, 5, 3, 5, 5, null);
1769 checkNavigableSetKeys(s, 6, 5, 5, null, null);
1770
1771 for (final Iterator<Integer> it :
1772 (Iterator<Integer>[])
1773 new Iterator<?>[] {
1774 s.descendingIterator(),
1775 s.descendingSet().iterator()}) {
1776 equalNext(it, 5);
1777 equalNext(it, 3);
1778 equalNext(it, 1);
1779 check(! it.hasNext());
1780 THROWS(NoSuchElementException.class, () -> it.next());
1781 }
1782
1783 prepSetForDescItrTests(s);
1784 checkDescItrRmFirst(s, s.descendingIterator());
1785 prepSetForDescItrTests(s);
1786 checkDescItrRmMid(s, s.descendingIterator());
1787 prepSetForDescItrTests(s);
1788 checkDescItrRmLast(s, s.descendingIterator());
1789
1790 prepSetForDescItrTests(s);
1791 checkDescItrRmFirst(s, s.descendingSet().iterator());
1792 prepSetForDescItrTests(s);
1793 checkDescItrRmMid(s, s.descendingSet().iterator());
1794 prepSetForDescItrTests(s);
1795 checkDescItrRmLast(s, s.descendingSet().iterator());
1796 }
1797
1798 private static void prepSetForDescItrTests(Set s) {
1799 clear(s);
1800 check(s.add(1));
1801 check(s.add(3));
1802 check(s.add(5));
1803 }
1804
1805 private static void prepMapForDescItrTests(Map m) {
1806 clear(m);
1807 equal(m.put(1, 2), null);
1808 equal(m.put(3, 4), null);
1809 equal(m.put(5, 9), null);
1810 }
1811
1812 //--------------------------------------------------------------------
1813 // Check behavior of descending iterator when first element is removed
1814 //--------------------------------------------------------------------
1815 private static <T> void checkDescItrRmFirst(Collection<T> ascColl,
1816 Iterator<T> descItr) {
1817 T[] expected = (T[]) ascColl.toArray();
1818 int idx = expected.length -1;
1819
1820 equalNext(descItr, expected[idx--]);
1821 descItr.remove();
1822 while (idx >= 0 && descItr.hasNext()) {
1823 equalNext(descItr, expected[idx--]);
1824 }
1825 equal(descItr.hasNext(), false);
1826 equal(idx, -1);
1827 }
1828
1829 //-----------------------------------------------------------------------
1830 // Check behavior of descending iterator when a middle element is removed
1831 //-----------------------------------------------------------------------
1832 private static <T> void checkDescItrRmMid(Collection<T> ascColl,
1833 Iterator<T> descItr) {
1834 T[] expected = (T[]) ascColl.toArray();
1835 int idx = expected.length -1;
1836
1837 while (idx >= expected.length / 2) {
1838 equalNext(descItr, expected[idx--]);
1839 }
1840 descItr.remove();
1841 while (idx >= 0 && descItr.hasNext()) {
1842 equalNext(descItr, expected[idx--]);
1843 }
1844 equal(descItr.hasNext(), false);
1845 equal(idx, -1);
1846 }
1847
1848 //-----------------------------------------------------------------------
1849 // Check behavior of descending iterator when the last element is removed
1850 //-----------------------------------------------------------------------
1851 private static <T> void checkDescItrRmLast(Collection<T> ascColl,
1852 Iterator<T> descItr) {
1853 T[] expected = (T[]) ascColl.toArray();
1854 int idx = expected.length -1;
1855
1856 while (idx >= 0 && descItr.hasNext()) {
1857 equalNext(descItr, expected[idx--]);
1858 }
1859 equal(idx, -1);
1860 equal(descItr.hasNext(), false);
1861 descItr.remove();
1862 equal(ascColl.contains(expected[0]), false);
1863 }
1864
1865 //--------------------- Infrastructure ---------------------------
1866 static volatile int passed = 0, failed = 0;
1867 static void pass() { passed++; }
1868 static void fail() { failed++; Thread.dumpStack(); }
1869 static void fail(String msg) { System.out.println(msg); fail(); }
1870 static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
1871 static void check(boolean cond) { if (cond) pass(); else fail(); }
1872 static void equal(Object x, Object y) {
1873 if (x == null ? y == null : x.equals(y)) pass();
1874 else {System.out.println(x + " not equal to " + y); fail();}}
1875 static void equal(Object x, Object y, String msg) {
1876 if (x == null ? y == null : x.equals(y)) pass();
1877 else {System.out.println(x + " not equal to " + y + " : " + msg); fail();}}
1878 static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}
1879 public static void main(String[] args) throws Throwable {
1880 try { realMain(args); } catch (Throwable t) { unexpected(t); }
1881
1882 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
1883 if (failed > 0) throw new Exception("Some tests failed");
1884 }
1885 interface Fun {void f() throws Throwable;}
1886 private static void THROWS(Class<? extends Throwable> k, Fun... fs) {
1887 for (Fun f : fs)
1888 try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
1889 catch (Throwable t) {
1890 if (k.isAssignableFrom(t.getClass())) pass();
1891 else unexpected(t);}}
1892 static byte[] serializedForm(Object obj) {
1893 try {
1894 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1895 new ObjectOutputStream(baos).writeObject(obj);
1896 return baos.toByteArray();
1897 } catch (IOException e) { throw new Error(e); }}
1898 static Object readObject(byte[] bytes)
1899 throws IOException, ClassNotFoundException {
1900 InputStream is = new ByteArrayInputStream(bytes);
1901 return new ObjectInputStream(is).readObject();}
1902 @SuppressWarnings("unchecked")
1903 static <T> T serialClone(T obj) {
1904 try { return (T) readObject(serializedForm(obj)); }
1905 catch (Exception e) { throw new Error(e); }}
1906 private static class NewAbstractCollection<E> extends AbstractCollection<E> {
1907 ArrayList<E> list = new ArrayList<>();
1908 public boolean remove(Object obj) {
1909 return list.remove(obj);
1910 }
1911 public boolean add(E e) {
1912 return list.add(e);
1913 }
1914 public Iterator<E> iterator() {
1915 return list.iterator();
1916 }
1917 public int size() {
1918 return list.size();
1919 }
1920 }
1921 private static class NewAbstractSet<E> extends AbstractSet<E> {
1922 HashSet<E> set = new HashSet<>();
1923 public boolean remove(Object obj) {
1924 return set.remove(obj);
1925 }
1926 public boolean add(E e) {
1927 return set.add(e);
1928 }
1929 public Iterator<E> iterator() {
1930 return set.iterator();
1931 }
1932 public int size() {
1933 return set.size();
1934 }
1935 }
1936
1937 }
--- EOF ---