--- jsr166/src/test/tck/Collection8Test.java 2016/11/28 03:30:28 1.32 +++ jsr166/src/test/tck/Collection8Test.java 2016/12/07 22:03:41 1.38 @@ -353,6 +353,7 @@ public class Collection8Test extends JSR ArrayList iteratedForEachRemaining = new ArrayList(); ArrayList tryAdvanced = new ArrayList(); ArrayList spliterated = new ArrayList(); + ArrayList splitonced = new ArrayList(); ArrayList forEached = new ArrayList(); ArrayList streamForEached = new ArrayList(); ConcurrentLinkedQueue parallelStreamForEached = new ConcurrentLinkedQueue(); @@ -362,6 +363,11 @@ public class Collection8Test extends JSR for (Spliterator s = c.spliterator(); s.tryAdvance(tryAdvanced::add); ) {} c.spliterator().forEachRemaining(spliterated::add); + { // trySplit returns "strict prefix" + Spliterator s1 = c.spliterator(), s2 = s1.trySplit(); + if (s2 != null) s2.forEachRemaining(splitonced::add); + s1.forEachRemaining(splitonced::add); + } c.forEach(forEached::add); c.stream().forEach(streamForEached::add); c.parallelStream().forEach(parallelStreamForEached::add); @@ -376,6 +382,7 @@ public class Collection8Test extends JSR assertEquals(iterated, iteratedForEachRemaining); assertEquals(iterated, tryAdvanced); assertEquals(iterated, spliterated); + assertEquals(iterated, splitonced); assertEquals(iterated, forEached); assertEquals(iterated, streamForEached); assertEquals(iterated, removeIfed); @@ -384,6 +391,7 @@ public class Collection8Test extends JSR assertEquals(cset, new HashSet(iteratedForEachRemaining)); assertEquals(cset, new HashSet(tryAdvanced)); assertEquals(cset, new HashSet(spliterated)); + assertEquals(cset, new HashSet(splitonced)); assertEquals(cset, new HashSet(forEached)); assertEquals(cset, new HashSet(streamForEached)); assertEquals(cset, new HashSet(removeIfed)); @@ -542,6 +550,41 @@ public class Collection8Test extends JSR assertTrue(found.isEmpty()); } + /** TODO: promote to a common utility */ + static T chooseOne(T ... ts) { + return ts[ThreadLocalRandom.current().nextInt(ts.length)]; + } + + /** TODO: more random adders and removers */ + static Runnable adderRemover(Collection c, E e) { + return chooseOne( + () -> { + assertTrue(c.add(e)); + assertTrue(c.contains(e)); + assertTrue(c.remove(e)); + assertFalse(c.contains(e)); + }, + () -> { + assertTrue(c.add(e)); + assertTrue(c.contains(e)); + assertTrue(c.removeIf(x -> x == e)); + assertFalse(c.contains(e)); + }, + () -> { + assertTrue(c.add(e)); + assertTrue(c.contains(e)); + for (Iterator it = c.iterator();; ) + if (it.next() == e) { + try { it.remove(); } + catch (UnsupportedOperationException ok) { + c.remove(e); + } + break; + } + assertFalse(c.contains(e)); + }); + } + /** * Motley crew of threads concurrently randomly hammer the collection. */ @@ -549,15 +592,20 @@ public class Collection8Test extends JSR if (!impl.isConcurrent()) return; final ThreadLocalRandom rnd = ThreadLocalRandom.current(); final Collection c = impl.emptyCollection(); - final long testDurationMillis = timeoutMillis(); + 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 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> futures; final Phaser threadsStarted = new Phaser(1); // register this thread - final Consumer checkSanity = x -> assertTrue(x == one || x == two); final Runnable[] frobbers = { () -> c.forEach(checkSanity), () -> c.stream().forEach(checkSanity), @@ -573,20 +621,23 @@ public class Collection8Test extends JSR do {} while (s.tryAdvance(checkSanity)); }, () -> { for (Object x : c) checkSanity.accept(x); }, - () -> { for (Object x : c.toArray()) checkSanity.accept(x); }, - () -> { for (Object x : c.toArray(emptyArray)) checkSanity.accept(x); }, - () -> { - assertTrue(c.add(one)); - assertTrue(c.contains(one)); - assertTrue(c.remove(one)); - assertFalse(c.contains(one)); - }, + () -> checkArraySanity.accept(c.toArray()), + () -> checkArraySanity.accept(c.toArray(emptyArray)), () -> { - assertTrue(c.add(two)); - assertTrue(c.contains(two)); - assertTrue(c.remove(two)); - assertFalse(c.contains(two)); - }, + 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]); + // A careful reading of the spec does not support: + // for (i++; i < a.length; i++) assertSame(three, a[i]); + else + checkArraySanity.accept(x); + }, + adderRemover(c, one), + adderRemover(c, two), }; final List tasks = Arrays.stream(frobbers)