342 |
|
} |
343 |
|
|
344 |
|
/** |
345 |
+ |
* All elements removed in the middle of CONCURRENT traversal. |
346 |
+ |
*/ |
347 |
+ |
public void testElementRemovalDuringTraversal() { |
348 |
+ |
Collection c = impl.emptyCollection(); |
349 |
+ |
ThreadLocalRandom rnd = ThreadLocalRandom.current(); |
350 |
+ |
int n = rnd.nextInt(6); |
351 |
+ |
ArrayList copy = new ArrayList(); |
352 |
+ |
for (int i = 0; i < n; i++) { |
353 |
+ |
Object x = impl.makeElement(i); |
354 |
+ |
copy.add(x); |
355 |
+ |
c.add(x); |
356 |
+ |
} |
357 |
+ |
ArrayList iterated = new ArrayList(); |
358 |
+ |
ArrayList spliterated = new ArrayList(); |
359 |
+ |
Spliterator s = c.spliterator(); |
360 |
+ |
Iterator it = c.iterator(); |
361 |
+ |
for (int i = rnd.nextInt(n + 1); --i >= 0; ) { |
362 |
+ |
assertTrue(s.tryAdvance(spliterated::add)); |
363 |
+ |
if (rnd.nextBoolean()) assertTrue(it.hasNext()); |
364 |
+ |
iterated.add(it.next()); |
365 |
+ |
} |
366 |
+ |
Consumer alwaysThrows = e -> { throw new AssertionError(); }; |
367 |
+ |
if (s.hasCharacteristics(Spliterator.CONCURRENT)) { |
368 |
+ |
c.clear(); // TODO: many more removal methods |
369 |
+ |
if (testImplementationDetails |
370 |
+ |
&& !(c instanceof java.util.concurrent.ArrayBlockingQueue)) { |
371 |
+ |
if (rnd.nextBoolean()) |
372 |
+ |
assertFalse(s.tryAdvance(alwaysThrows)); |
373 |
+ |
else |
374 |
+ |
s.forEachRemaining(alwaysThrows); |
375 |
+ |
} |
376 |
+ |
if (it.hasNext()) iterated.add(it.next()); |
377 |
+ |
if (rnd.nextBoolean()) assertIteratorExhausted(it); |
378 |
+ |
} |
379 |
+ |
assertTrue(copy.containsAll(iterated)); |
380 |
+ |
assertTrue(copy.containsAll(spliterated)); |
381 |
+ |
} |
382 |
+ |
|
383 |
+ |
/** |
384 |
+ |
* Some elements randomly disappear in the middle of traversal. |
385 |
+ |
*/ |
386 |
+ |
public void testRandomElementRemovalDuringTraversal() { |
387 |
+ |
Collection c = impl.emptyCollection(); |
388 |
+ |
ThreadLocalRandom rnd = ThreadLocalRandom.current(); |
389 |
+ |
int n = rnd.nextInt(6); |
390 |
+ |
ArrayList copy = new ArrayList(); |
391 |
+ |
for (int i = 0; i < n; i++) { |
392 |
+ |
Object x = impl.makeElement(i); |
393 |
+ |
copy.add(x); |
394 |
+ |
c.add(x); |
395 |
+ |
} |
396 |
+ |
ArrayList iterated = new ArrayList(); |
397 |
+ |
ArrayList spliterated = new ArrayList(); |
398 |
+ |
ArrayList removed = new ArrayList(); |
399 |
+ |
Spliterator s = c.spliterator(); |
400 |
+ |
Iterator it = c.iterator(); |
401 |
+ |
if (! (s.hasCharacteristics(Spliterator.CONCURRENT) || |
402 |
+ |
s.hasCharacteristics(Spliterator.IMMUTABLE))) |
403 |
+ |
return; |
404 |
+ |
for (int i = rnd.nextInt(n + 1); --i >= 0; ) { |
405 |
+ |
assertTrue(s.tryAdvance(e -> {})); |
406 |
+ |
if (rnd.nextBoolean()) assertTrue(it.hasNext()); |
407 |
+ |
it.next(); |
408 |
+ |
} |
409 |
+ |
Consumer alwaysThrows = e -> { throw new AssertionError(); }; |
410 |
+ |
// TODO: many more removal methods |
411 |
+ |
if (rnd.nextBoolean()) { |
412 |
+ |
for (Iterator z = c.iterator(); z.hasNext(); ) { |
413 |
+ |
Object e = z.next(); |
414 |
+ |
if (rnd.nextBoolean()) { |
415 |
+ |
try { |
416 |
+ |
z.remove(); |
417 |
+ |
} catch (UnsupportedOperationException ok) { return; } |
418 |
+ |
removed.add(e); |
419 |
+ |
} |
420 |
+ |
} |
421 |
+ |
} else { |
422 |
+ |
Predicate randomlyRemove = e -> { |
423 |
+ |
if (rnd.nextBoolean()) { removed.add(e); return true; } |
424 |
+ |
else return false; |
425 |
+ |
}; |
426 |
+ |
c.removeIf(randomlyRemove); |
427 |
+ |
} |
428 |
+ |
s.forEachRemaining(spliterated::add); |
429 |
+ |
while (it.hasNext()) |
430 |
+ |
iterated.add(it.next()); |
431 |
+ |
assertTrue(copy.containsAll(iterated)); |
432 |
+ |
assertTrue(copy.containsAll(spliterated)); |
433 |
+ |
assertTrue(copy.containsAll(removed)); |
434 |
+ |
if (s.hasCharacteristics(Spliterator.CONCURRENT)) { |
435 |
+ |
ArrayList iteratedAndRemoved = new ArrayList(iterated); |
436 |
+ |
ArrayList spliteratedAndRemoved = new ArrayList(spliterated); |
437 |
+ |
iteratedAndRemoved.retainAll(removed); |
438 |
+ |
spliteratedAndRemoved.retainAll(removed); |
439 |
+ |
assertTrue(iteratedAndRemoved.size() <= 1); |
440 |
+ |
assertTrue(spliteratedAndRemoved.size() <= 1); |
441 |
+ |
if (testImplementationDetails |
442 |
+ |
&& !(c instanceof java.util.concurrent.ArrayBlockingQueue)) |
443 |
+ |
assertTrue(spliteratedAndRemoved.isEmpty()); |
444 |
+ |
} |
445 |
+ |
} |
446 |
+ |
|
447 |
+ |
/** |
448 |
|
* Various ways of traversing a collection yield same elements |
449 |
|
*/ |
450 |
|
public void testIteratorEquivalence() { |