use of java8.util.concurrent.ThreadLocalRandom in project streamsupport by stefan-zobel.
the class Collection8Test method testForEachRemainingConsistentWithDefaultImplementation.
/**
* Iterator.forEachRemaining has same behavior as Iterator's
* default implementation.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testForEachRemainingConsistentWithDefaultImplementation(String description, Supplier<CollectionImplementation> sci) {
CollectionImplementation impl = sci.get();
Collection c = impl.emptyCollection();
if (!testImplementationDetails || c.getClass() == java.util.LinkedList.class)
return;
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = 1 + rnd.nextInt(3);
for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
ArrayList iterated = new ArrayList();
ArrayList iteratedForEachRemaining = new ArrayList();
Iterator<?> it1 = c.iterator();
Iterator<?> it2 = c.iterator();
assertTrue(it1.hasNext());
assertTrue(it2.hasNext());
c.clear();
Object r1, r2;
try {
while (it1.hasNext()) iterated.add(it1.next());
r1 = iterated;
} catch (ConcurrentModificationException ex) {
r1 = ConcurrentModificationException.class;
assertFalse(impl.isConcurrent());
}
try {
Iterators.forEachRemaining(it2, iteratedForEachRemaining::add);
r2 = iteratedForEachRemaining;
} catch (ConcurrentModificationException ex) {
r2 = ConcurrentModificationException.class;
assertFalse(impl.isConcurrent());
}
assertEquals(r1, r2);
}
use of java8.util.concurrent.ThreadLocalRandom in project streamsupport by stefan-zobel.
the class Collection8Test method testRemoveIf.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testRemoveIf(String description, Supplier<CollectionImplementation> sci) {
CollectionImplementation impl = sci.get();
if (CopyOnWriteArrayList.class.equals(impl.klazz()) || CopyOnWriteArraySet.class.equals(impl.klazz())) {
return;
}
Collection c = impl.emptyCollection();
boolean ordered = Spliterators.spliterator(c).hasCharacteristics(Spliterator.ORDERED);
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = rnd.nextInt(6);
for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
AtomicReference threwAt = new AtomicReference<>(null);
List<?> orig = rnd.nextBoolean() ? new ArrayList<>(c) : Arrays.asList(c.toArray());
// Merely creating an iterator can change ArrayBlockingQueue behavior
Iterator<?> it = rnd.nextBoolean() ? c.iterator() : null;
ArrayList survivors = new ArrayList<>();
ArrayList accepts = new ArrayList<>();
ArrayList rejects = new ArrayList<>();
Predicate randomPredicate = e -> {
assertNull(threwAt.get());
switch(rnd.nextInt(3)) {
case 0:
accepts.add(e);
return true;
case 1:
rejects.add(e);
return false;
case 2:
threwAt.set(e);
throw new ArithmeticException();
default:
throw new AssertionError();
}
};
try {
try {
boolean modified = Iterables.removeIf(c, randomPredicate);
assertNull(threwAt.get());
assertEquals(modified, accepts.size() > 0);
assertEquals(modified, rejects.size() != n);
assertEquals(accepts.size() + rejects.size(), n);
if (ordered) {
assertEquals(rejects, Arrays.asList(c.toArray()));
} else {
assertEquals(new HashSet<>(rejects), new HashSet<>(Arrays.asList(c.toArray())));
}
} catch (ArithmeticException ok) {
assertNotNull(threwAt.get());
assertTrue(c.contains(threwAt.get()));
}
if (it != null && impl.isConcurrent())
// check for weakly consistent iterator
while (it.hasNext()) assertTrue(orig.contains(it.next()));
switch(rnd.nextInt(4)) {
case 0:
survivors.addAll(c);
break;
case 1:
survivors.addAll(Arrays.asList(c.toArray()));
break;
case 2:
Iterables.forEach(c, survivors::add);
break;
case 3:
for (Object e : c) survivors.add(e);
break;
}
assertTrue(orig.containsAll(accepts));
assertTrue(orig.containsAll(rejects));
assertTrue(orig.containsAll(survivors));
assertTrue(orig.containsAll(c));
assertTrue(c.containsAll(rejects));
assertTrue(c.containsAll(survivors));
assertTrue(survivors.containsAll(rejects));
if (threwAt.get() == null) {
assertEquals(n - accepts.size(), c.size());
for (Object x : accepts) assertFalse(c.contains(x));
} else {
// Two acceptable behaviors: entire removeIf call is one
// transaction, or each element processed is one transaction.
assertTrue(n == c.size() || n == c.size() + accepts.size());
int k = 0;
for (Object x : accepts) if (c.contains(x))
k++;
assertTrue(k == accepts.size() || k == 0);
}
} catch (Throwable ex) {
System.err.println(impl.klazz());
// c is at risk of corruption if we got here, so be lenient
try {
System.err.printf("c=%s%n", c);
} catch (Throwable t) {
t.printStackTrace();
}
System.err.printf("n=%d%n", n);
System.err.printf("orig=%s%n", orig);
System.err.printf("accepts=%s%n", accepts);
System.err.printf("rejects=%s%n", rejects);
System.err.printf("survivors=%s%n", survivors);
System.err.printf("threwAt=%s%n", threwAt.get());
throw ex;
}
}
use of java8.util.concurrent.ThreadLocalRandom in project streamsupport by stefan-zobel.
the class Collection8Test method testDetectRaces.
/**
* Motley crew of threads concurrently randomly hammer the collection.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testDetectRaces(String description, Supplier<CollectionImplementation> sci) throws Throwable {
CollectionImplementation impl = sci.get();
if (!impl.isConcurrent())
return;
if (HAS_JAVA8_SPLITERATOR_BUG && LinkedBlockingDeque.class.equals(impl.klazz())) {
// https://bugs.openjdk.java.net/browse/JDK-8169739
return;
}
if (CopyOnWriteArraySet.class.equals(impl.klazz())) {
return;
}
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final Collection c = impl.emptyCollection();
final long testDurationMillis = expensiveTests ? LONG_DELAY_MS : timeoutMillis();
final AtomicBoolean done = new AtomicBoolean(false);
final Object one = impl.makeElement(1);
final Object two = impl.makeElement(2);
final Consumer checkSanity = x -> assertTrue(x == one || x == two);
final Consumer<Object[]> checkArraySanity = array -> {
// assertTrue(array.length <= 2); // duplicates are permitted
for (Object x : array) assertTrue(x == one || x == two);
};
final Object[] emptyArray = (Object[]) java.lang.reflect.Array.newInstance(one.getClass(), 0);
final List<Future<?>> futures;
// register this thread
final Phaser threadsStarted = new Phaser(1);
final Runnable[] frobbers = { () -> Iterables.forEach(c, checkSanity), () -> StreamSupport.stream(c).forEach(checkSanity), () -> StreamSupport.parallelStream(c).forEach(checkSanity), () -> Spliterators.spliterator(c).trySplit(), () -> {
Spliterator<?> s = Spliterators.spliterator(c);
s.tryAdvance(checkSanity);
s.trySplit();
}, () -> {
Spliterator<?> s = Spliterators.spliterator(c);
do {
} while (s.tryAdvance(checkSanity));
}, () -> {
for (Object x : c) checkSanity.accept(x);
}, () -> checkArraySanity.accept(c.toArray()), () -> checkArraySanity.accept(c.toArray(emptyArray)), () -> {
Object[] a = new Object[5];
Object three = impl.makeElement(3);
Arrays.fill(a, 0, a.length, three);
Object[] x = c.toArray(a);
if (x == a)
for (int i = 0; i < a.length && a[i] != null; i++) checkSanity.accept(a[i]);
else
// A careful reading of the spec does not support:
// for (i++; i < a.length; i++) assertSame(three, a[i]);
checkArraySanity.accept(x);
}, adderRemover(c, one), adderRemover(c, two) };
final List<Runnable> tasks = J8Arrays.stream(frobbers).filter(// random subset
task -> rnd.nextBoolean()).map(task -> (Runnable) () -> {
threadsStarted.arriveAndAwaitAdvance();
while (!done.get()) task.run();
}).collect(Collectors.<Runnable>toList());
final ExecutorService pool = Executors.newCachedThreadPool();
PoolCleaner cleaner = null;
try {
cleaner = cleaner(pool, done);
threadsStarted.bulkRegister(tasks.size());
futures = StreamSupport.stream(tasks).map(pool::submit).collect(Collectors.toList());
threadsStarted.arriveAndDeregister();
Thread.sleep(testDurationMillis);
} finally {
if (cleaner != null) {
cleaner.close();
}
}
for (Future<?> future : futures) assertNull(future.get(0L, MILLISECONDS));
}
use of java8.util.concurrent.ThreadLocalRandom in project streamsupport by stefan-zobel.
the class Collection8Test method testRandomElementRemovalDuringTraversal.
/**
* Some elements randomly disappear in the middle of traversal.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testRandomElementRemovalDuringTraversal(String description, Supplier<CollectionImplementation> sci) {
CollectionImplementation impl = sci.get();
if (CopyOnWriteArrayList.class.equals(impl.klazz()) || CopyOnWriteArraySet.class.equals(impl.klazz())) {
return;
}
if (HAS_JAVA8_SPLITERATOR_BUG && (LinkedBlockingDeque.class.equals(impl.klazz())) || LinkedBlockingQueue.class.equals(impl.klazz())) {
// https://bugs.openjdk.java.net/browse/JDK-8171051
return;
}
Collection c = impl.emptyCollection();
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = rnd.nextInt(6);
ArrayList copy = new ArrayList();
for (int i = 0; i < n; i++) {
Object x = impl.makeElement(i);
copy.add(x);
c.add(x);
}
ArrayList iterated = new ArrayList();
ArrayList spliterated = new ArrayList();
ArrayList removed = new ArrayList();
Spliterator<?> s = Spliterators.spliterator(c);
Iterator<?> it = c.iterator();
if (!(s.hasCharacteristics(Spliterator.CONCURRENT) || s.hasCharacteristics(Spliterator.IMMUTABLE)))
return;
for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
assertTrue(s.tryAdvance(e -> {
}));
if (rnd.nextBoolean())
assertTrue(it.hasNext());
it.next();
}
// TODO: many more removal methods
if (rnd.nextBoolean()) {
for (Iterator<?> z = c.iterator(); z.hasNext(); ) {
Object e = z.next();
if (rnd.nextBoolean()) {
try {
z.remove();
} catch (UnsupportedOperationException ok) {
return;
}
removed.add(e);
}
}
} else {
Predicate randomlyRemove = e -> {
if (rnd.nextBoolean()) {
removed.add(e);
return true;
} else
return false;
};
Iterables.removeIf(c, randomlyRemove);
}
s.forEachRemaining(spliterated::add);
while (it.hasNext()) iterated.add(it.next());
assertTrue(copy.containsAll(iterated));
assertTrue(copy.containsAll(spliterated));
assertTrue(copy.containsAll(removed));
if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
ArrayList<?> iteratedAndRemoved = new ArrayList<>(iterated);
ArrayList<?> spliteratedAndRemoved = new ArrayList<>(spliterated);
iteratedAndRemoved.retainAll(removed);
spliteratedAndRemoved.retainAll(removed);
assertTrue(iteratedAndRemoved.size() <= 1);
assertTrue(spliteratedAndRemoved.size() <= 1);
if (testImplementationDetails && !(c instanceof java.util.concurrent.ArrayBlockingQueue))
assertTrue(spliteratedAndRemoved.isEmpty());
}
}
use of java8.util.concurrent.ThreadLocalRandom in project streamsupport by stefan-zobel.
the class Collection8Test method populatedDeque.
/**
* Returns a new deque of given size containing consecutive
* Integers 0 ... n - 1.
*/
private static ArrayDeque<Integer> populatedDeque(int n) {
// Randomize various aspects of memory layout, including
// capacity slop and wraparound.
final ArrayDeque<Integer> q;
ThreadLocalRandom rnd = ThreadLocalRandom.current();
switch(rnd.nextInt(6)) {
case 0:
q = new ArrayDeque<Integer>();
break;
case 1:
q = new ArrayDeque<Integer>(0);
break;
case 2:
q = new ArrayDeque<Integer>(1);
break;
case 3:
q = new ArrayDeque<Integer>(Math.max(0, n - 1));
break;
case 4:
q = new ArrayDeque<Integer>(n);
break;
case 5:
q = new ArrayDeque<Integer>(n + 1);
break;
default:
throw new AssertionError();
}
switch(rnd.nextInt(3)) {
case 0:
q.addFirst(42);
assertEquals((Integer) 42, q.removeLast());
break;
case 1:
q.addLast(42);
assertEquals((Integer) 42, q.removeFirst());
break;
case 2:
/* do nothing */
break;
default:
throw new AssertionError();
}
assertTrue(q.isEmpty());
if (rnd.nextBoolean())
for (int i = 0; i < n; i++) assertTrue(q.offerLast((Integer) i));
else
for (int i = n; --i >= 0; ) q.addFirst((Integer) i);
assertEquals(n, q.size());
if (n > 0) {
assertFalse(q.isEmpty());
assertEquals((Integer) 0, q.peekFirst());
assertEquals((Integer) (n - 1), q.peekLast());
}
return q;
}
Aggregations