undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
149
test/jdk/java/util/Spliterator/IteratorFromSpliteratorTest.java
Normal file
149
test/jdk/java/util/Spliterator/IteratorFromSpliteratorTest.java
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Spliterator.iterator traversing tests
|
||||
* @library /lib/testlibrary/bootlib
|
||||
* @run testng IteratorFromSpliteratorTest
|
||||
* @bug 8267452
|
||||
*/
|
||||
public class IteratorFromSpliteratorTest {
|
||||
@Test
|
||||
public void testIteratorFromSpliterator() {
|
||||
List<Integer> input = List.of(1, 2, 3, 4, 5);
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
Iterator<Integer> iterator = Spliterators.iterator(input.spliterator());
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int j = i;
|
||||
while (j++ < input.size() && iterator.hasNext()) {
|
||||
result.add(iterator.next());
|
||||
}
|
||||
// While SpliteratorTraversingAndSplittingTest tests some scenarios with Spliterators.iterator
|
||||
// it always wraps the resulting iterator into spliterator again, and this limits the use patterns.
|
||||
// In particular, calling hasNext() right before forEachRemaining() is not tested.
|
||||
// Here we cover such a scenario.
|
||||
assertEquals(iterator.hasNext(), result.size() < input.size());
|
||||
iterator.forEachRemaining(result::add);
|
||||
iterator.forEachRemaining(x -> fail("Should not be called"));
|
||||
assertFalse(iterator.hasNext());
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
iterator.forEachRemaining(x -> fail("Should not be called"));
|
||||
assertEquals(result, input);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratorFromSpliteratorInt() {
|
||||
int[] input = {1, 2, 3, 4, 5};
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
PrimitiveIterator.OfInt iterator = Spliterators.iterator(Arrays.spliterator(input));
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int j = i;
|
||||
while (j++ < input.length && iterator.hasNext()) {
|
||||
result.add(iterator.nextInt());
|
||||
}
|
||||
assertEquals(iterator.hasNext(), result.size() < input.length);
|
||||
iterator.forEachRemaining((IntConsumer) result::add);
|
||||
iterator.forEachRemaining((IntConsumer) (x -> fail("Should not be called")));
|
||||
assertFalse(iterator.hasNext());
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
iterator.forEachRemaining((IntConsumer) (x -> fail("Should not be called")));
|
||||
assertEquals(result.stream().mapToInt(x -> x).toArray(), input);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratorFromSpliteratorLong() {
|
||||
long[] input = {1, 2, 3, 4, 5};
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
PrimitiveIterator.OfLong iterator = Spliterators.iterator(Arrays.spliterator(input));
|
||||
List<Long> result = new ArrayList<>();
|
||||
int j = i;
|
||||
while (j++ < input.length && iterator.hasNext()) {
|
||||
result.add(iterator.nextLong());
|
||||
}
|
||||
assertEquals(iterator.hasNext(), result.size() < input.length);
|
||||
iterator.forEachRemaining((LongConsumer) result::add);
|
||||
iterator.forEachRemaining((LongConsumer) (x -> fail("Should not be called")));
|
||||
assertFalse(iterator.hasNext());
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
iterator.forEachRemaining((LongConsumer) (x -> fail("Should not be called")));
|
||||
assertEquals(result.stream().mapToLong(x -> x).toArray(), input);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratorFromSpliteratorDouble() {
|
||||
double[] input = {1, 2, 3, 4, 5};
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
PrimitiveIterator.OfDouble iterator = Spliterators.iterator(Arrays.spliterator(input));
|
||||
List<Double> result = new ArrayList<>();
|
||||
int j = i;
|
||||
while (j++ < input.length && iterator.hasNext()) {
|
||||
result.add(iterator.nextDouble());
|
||||
}
|
||||
assertEquals(iterator.hasNext(), result.size() < input.length);
|
||||
iterator.forEachRemaining((DoubleConsumer) result::add);
|
||||
iterator.forEachRemaining((DoubleConsumer) (x -> fail("Should not be called")));
|
||||
assertFalse(iterator.hasNext());
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
iterator.forEachRemaining((DoubleConsumer) (x -> fail("Should not be called")));
|
||||
assertEquals(result.stream().mapToDouble(x -> x).toArray(), input);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratorFromSpliteratorEmpty() {
|
||||
Iterator<?>[] iterators = {
|
||||
Spliterators.iterator(Spliterators.emptySpliterator()),
|
||||
Spliterators.iterator(Spliterators.emptyIntSpliterator()),
|
||||
Spliterators.iterator(Spliterators.emptyLongSpliterator()),
|
||||
Spliterators.iterator(Spliterators.emptyDoubleSpliterator())
|
||||
};
|
||||
for (Iterator<?> iterator : iterators) {
|
||||
iterator.forEachRemaining(x -> fail("Should not be called"));
|
||||
assertFalse(iterator.hasNext());
|
||||
iterator.forEachRemaining(x -> fail("Should not be called"));
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
}
|
||||
}
|
||||
}
|
||||
425
test/jdk/java/util/Spliterator/SpliteratorCharacteristics.java
Normal file
425
test/jdk/java/util/Spliterator/SpliteratorCharacteristics.java
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8020156 8020009 8022326 8012913 8024405 8024408 8071477
|
||||
* @run testng SpliteratorCharacteristics
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class SpliteratorCharacteristics {
|
||||
|
||||
public void testSpliteratorFromCharSequence() {
|
||||
class CharSequenceImpl implements CharSequence {
|
||||
final String s;
|
||||
|
||||
public CharSequenceImpl(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return s.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return s.charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return s.subSequence(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
CharSequence cs = "A";
|
||||
Spliterator.OfInt s = cs.chars().spliterator();
|
||||
assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED |
|
||||
Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
s = cs.codePoints().spliterator();
|
||||
assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
|
||||
for (CharSequence c : Arrays.asList(new CharSequenceImpl("A"),
|
||||
new StringBuilder("A"),
|
||||
new StringBuffer("A"))) {
|
||||
s = cs.chars().spliterator();
|
||||
assertCharacteristics(s, Spliterator.ORDERED |
|
||||
Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
s = cs.codePoints().spliterator();
|
||||
assertCharacteristics(s, Spliterator.ORDERED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorFromCollection() {
|
||||
List<Integer> l = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
l.iterator(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfIntFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfInt> si = () -> IntStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfLongFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfLong> si = () -> LongStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfDoubleFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfDouble> si = () -> DoubleStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public void testHashMap() {
|
||||
assertMapCharacteristics(new HashMap<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT);
|
||||
}
|
||||
|
||||
public void testWeakHashMap() {
|
||||
assertMapCharacteristics(new WeakHashMap<>(),
|
||||
Spliterator.DISTINCT);
|
||||
}
|
||||
|
||||
public void testHashSet() {
|
||||
assertSetCharacteristics(new HashSet<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT);
|
||||
}
|
||||
|
||||
public void testLinkedHashMap() {
|
||||
assertMapCharacteristics(new LinkedHashMap<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testLinkedHashSet() {
|
||||
assertSetCharacteristics(new LinkedHashSet<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testTreeMap() {
|
||||
assertSortedMapCharacteristics(new TreeMap<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.SORTED | Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testTreeMapWithComparator() {
|
||||
assertSortedMapCharacteristics(new TreeMap<>(Comparator.reverseOrder()),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.SORTED | Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testTreeSet() {
|
||||
assertSortedSetCharacteristics(new TreeSet<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.SORTED | Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testTreeSetWithComparator() {
|
||||
assertSortedSetCharacteristics(new TreeSet<>(Comparator.reverseOrder()),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT |
|
||||
Spliterator.SORTED | Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testConcurrentSkipListMap() {
|
||||
assertSortedMapCharacteristics(new ConcurrentSkipListMap<>(),
|
||||
Spliterator.CONCURRENT | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testConcurrentSkipListMapWithComparator() {
|
||||
assertSortedMapCharacteristics(new ConcurrentSkipListMap<>(Comparator.<Integer>reverseOrder()),
|
||||
Spliterator.CONCURRENT | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testConcurrentSkipListSet() {
|
||||
assertSortedSetCharacteristics(new ConcurrentSkipListSet<>(),
|
||||
Spliterator.CONCURRENT | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
public void testConcurrentSkipListSetWithComparator() {
|
||||
assertSortedSetCharacteristics(new ConcurrentSkipListSet<>(Comparator.reverseOrder()),
|
||||
Spliterator.CONCURRENT | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED |
|
||||
Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
void assertMapCharacteristics(Map<Integer, String> m, int keyCharacteristics) {
|
||||
assertMapCharacteristics(m, keyCharacteristics, 0);
|
||||
}
|
||||
|
||||
void assertMapCharacteristics(Map<Integer, String> m, int keyCharacteristics, int notValueCharacteristics) {
|
||||
initMap(m);
|
||||
|
||||
assertCharacteristics(m.keySet(), keyCharacteristics);
|
||||
|
||||
assertCharacteristics(m.values(),
|
||||
keyCharacteristics & ~(Spliterator.DISTINCT | notValueCharacteristics));
|
||||
|
||||
assertCharacteristics(m.entrySet(), keyCharacteristics);
|
||||
|
||||
if ((keyCharacteristics & Spliterator.SORTED) == 0) {
|
||||
assertISEComparator(m.keySet());
|
||||
assertISEComparator(m.values());
|
||||
assertISEComparator(m.entrySet());
|
||||
}
|
||||
}
|
||||
|
||||
void assertSetCharacteristics(Set<Integer> s, int keyCharacteristics) {
|
||||
initSet(s);
|
||||
|
||||
assertCharacteristics(s, keyCharacteristics);
|
||||
|
||||
if ((keyCharacteristics & Spliterator.SORTED) == 0) {
|
||||
assertISEComparator(s);
|
||||
}
|
||||
}
|
||||
|
||||
void assertSortedMapCharacteristics(SortedMap<Integer, String> m, int keyCharacteristics) {
|
||||
assertMapCharacteristics(m, keyCharacteristics, Spliterator.SORTED);
|
||||
|
||||
Set<Integer> keys = m.keySet();
|
||||
if (m.comparator() != null) {
|
||||
assertNotNullComparator(keys);
|
||||
}
|
||||
else {
|
||||
assertNullComparator(keys);
|
||||
}
|
||||
|
||||
assertISEComparator(m.values());
|
||||
|
||||
assertNotNullComparator(m.entrySet());
|
||||
}
|
||||
|
||||
void assertSortedSetCharacteristics(SortedSet<Integer> s, int keyCharacteristics) {
|
||||
assertSetCharacteristics(s, keyCharacteristics);
|
||||
|
||||
if (s.comparator() != null) {
|
||||
assertNotNullComparator(s);
|
||||
}
|
||||
else {
|
||||
assertNullComparator(s);
|
||||
}
|
||||
}
|
||||
|
||||
void initMap(Map<Integer, String> m) {
|
||||
m.put(1, "4");
|
||||
m.put(2, "3");
|
||||
m.put(3, "2");
|
||||
m.put(4, "1");
|
||||
}
|
||||
|
||||
void initSet(Set<Integer> s) {
|
||||
s.addAll(Arrays.asList(1, 2, 3, 4));
|
||||
}
|
||||
|
||||
void assertCharacteristics(Collection<?> c, int expectedCharacteristics) {
|
||||
assertCharacteristics(c.spliterator(), expectedCharacteristics);
|
||||
}
|
||||
|
||||
void assertCharacteristics(Spliterator<?> s, int expectedCharacteristics) {
|
||||
assertTrue(s.hasCharacteristics(expectedCharacteristics),
|
||||
"Spliterator characteristics");
|
||||
}
|
||||
|
||||
void assertHasNotCharacteristics(Spliterator<?> s, int expectedCharacteristics) {
|
||||
assertFalse(s.hasCharacteristics(expectedCharacteristics),
|
||||
"Spliterator characteristics");
|
||||
}
|
||||
|
||||
void assertNullComparator(Collection<?> c) {
|
||||
assertNull(c.spliterator().getComparator(),
|
||||
"Comparator of Spliterator of Collection");
|
||||
}
|
||||
|
||||
void assertNotNullComparator(Collection<?> c) {
|
||||
assertNotNull(c.spliterator().getComparator(),
|
||||
"Comparator of Spliterator of Collection");
|
||||
}
|
||||
|
||||
void assertISEComparator(Collection<?> c) {
|
||||
assertISEComparator(c.spliterator());
|
||||
}
|
||||
|
||||
void assertISEComparator(Spliterator<?> s) {
|
||||
boolean caught = false;
|
||||
try {
|
||||
s.getComparator();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
caught = true;
|
||||
}
|
||||
assertTrue(caught, "Throwing IllegalStateException");
|
||||
}
|
||||
}
|
||||
342
test/jdk/java/util/Spliterator/SpliteratorCollisions.java
Normal file
342
test/jdk/java/util/Spliterator/SpliteratorCollisions.java
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8005698
|
||||
* @library /lib/testlibrary/bootlib
|
||||
* @build java.base/java.util.SpliteratorTestHelper
|
||||
* @run testng SpliteratorCollisions
|
||||
* @summary Spliterator traversing and splitting hash maps containing colliding hashes
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Spliterator;
|
||||
import java.util.SpliteratorTestHelper;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class SpliteratorCollisions extends SpliteratorTestHelper {
|
||||
|
||||
private static final List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
|
||||
|
||||
private static class SpliteratorDataBuilder<T> {
|
||||
List<Object[]> data;
|
||||
List<T> exp;
|
||||
Map<T, T> mExp;
|
||||
|
||||
SpliteratorDataBuilder(List<Object[]> data, List<T> exp) {
|
||||
this.data = data;
|
||||
this.exp = exp;
|
||||
this.mExp = createMap(exp);
|
||||
}
|
||||
|
||||
Map<T, T> createMap(List<T> l) {
|
||||
Map<T, T> m = new LinkedHashMap<>();
|
||||
for (T t : l) {
|
||||
m.put(t, t);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
void add(String description, Collection<?> expected, Supplier<Spliterator<?>> s) {
|
||||
description = joiner(description).toString();
|
||||
data.add(new Object[]{description, expected, s});
|
||||
}
|
||||
|
||||
void add(String description, Supplier<Spliterator<?>> s) {
|
||||
add(description, exp, s);
|
||||
}
|
||||
|
||||
void addCollection(Function<Collection<T>, ? extends Collection<T>> c) {
|
||||
add("new " + c.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator()",
|
||||
() -> c.apply(exp).spliterator());
|
||||
}
|
||||
|
||||
void addList(Function<Collection<T>, ? extends List<T>> l) {
|
||||
// @@@ If collection is instance of List then add sub-list tests
|
||||
addCollection(l);
|
||||
}
|
||||
|
||||
void addMap(Function<Map<T, T>, ? extends Map<T, T>> m) {
|
||||
String description = "new " + m.apply(Collections.<T, T>emptyMap()).getClass().getName();
|
||||
add(description + ".keySet().spliterator()", () -> m.apply(mExp).keySet().spliterator());
|
||||
add(description + ".values().spliterator()", () -> m.apply(mExp).values().spliterator());
|
||||
add(description + ".entrySet().spliterator()", mExp.entrySet(), () -> m.apply(mExp).entrySet().spliterator());
|
||||
}
|
||||
|
||||
StringBuilder joiner(String description) {
|
||||
return new StringBuilder(description).
|
||||
append(" {").
|
||||
append("size=").append(exp.size()).
|
||||
append("}");
|
||||
}
|
||||
}
|
||||
|
||||
static Object[][] spliteratorDataProvider;
|
||||
|
||||
@DataProvider(name = "HashableIntSpliterator")
|
||||
public static Object[][] spliteratorDataProvider() {
|
||||
if (spliteratorDataProvider != null) {
|
||||
return spliteratorDataProvider;
|
||||
}
|
||||
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
for (int size : SIZES) {
|
||||
List<HashableInteger> exp = listIntRange(size, false);
|
||||
SpliteratorDataBuilder<HashableInteger> db = new SpliteratorDataBuilder<>(data, exp);
|
||||
|
||||
// Maps
|
||||
db.addMap(HashMap::new);
|
||||
db.addMap(LinkedHashMap::new);
|
||||
|
||||
// Collections that use HashMap
|
||||
db.addCollection(HashSet::new);
|
||||
db.addCollection(LinkedHashSet::new);
|
||||
db.addCollection(TreeSet::new);
|
||||
}
|
||||
return spliteratorDataProvider = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
static Object[][] spliteratorDataProviderWithNull;
|
||||
|
||||
@DataProvider(name = "HashableIntSpliteratorWithNull")
|
||||
public static Object[][] spliteratorNullDataProvider() {
|
||||
if (spliteratorDataProviderWithNull != null) {
|
||||
return spliteratorDataProviderWithNull;
|
||||
}
|
||||
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
for (int size : SIZES) {
|
||||
List<HashableInteger> exp = listIntRange(size, true);
|
||||
SpliteratorDataBuilder<HashableInteger> db = new SpliteratorDataBuilder<>(data, exp);
|
||||
|
||||
// Maps
|
||||
db.addMap(HashMap::new);
|
||||
db.addMap(LinkedHashMap::new);
|
||||
// TODO: add this back in if we decide to keep TreeBin in WeakHashMap
|
||||
//db.addMap(WeakHashMap::new);
|
||||
|
||||
// Collections that use HashMap
|
||||
db.addCollection(HashSet::new);
|
||||
db.addCollection(LinkedHashSet::new);
|
||||
// db.addCollection(TreeSet::new);
|
||||
|
||||
}
|
||||
return spliteratorDataProviderWithNull = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
static final class HashableInteger implements Comparable<HashableInteger> {
|
||||
|
||||
final int value;
|
||||
final int hashmask; //yes duplication
|
||||
|
||||
HashableInteger(int value, int hashmask) {
|
||||
this.value = value;
|
||||
this.hashmask = hashmask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof HashableInteger) {
|
||||
HashableInteger other = (HashableInteger) obj;
|
||||
|
||||
return other.value == value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value % hashmask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(HashableInteger o) {
|
||||
return value - o.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toString(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<HashableInteger> listIntRange(int upTo, boolean withNull) {
|
||||
List<HashableInteger> exp = new ArrayList<>();
|
||||
if (withNull) {
|
||||
exp.add(null);
|
||||
}
|
||||
for (int i = 0; i < upTo; i++) {
|
||||
exp.add(new HashableInteger(i, 10));
|
||||
}
|
||||
return Collections.unmodifiableList(exp);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testNullPointerException(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
assertThrowsNPE(() -> s.get().forEachRemaining(null));
|
||||
assertThrowsNPE(() -> s.get().tryAdvance(null));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testNullPointerExceptionWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
assertThrowsNPE(() -> s.get().forEachRemaining(null));
|
||||
assertThrowsNPE(() -> s.get().tryAdvance(null));
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testForEach(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testForEach(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testForEachWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testForEach(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testTryAdvance(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testTryAdvance(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testTryAdvanceWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testTryAdvance(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testMixedTryAdvanceForEach(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testMixedTryAdvanceForEach(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testMixedTryAdvanceForEachWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testMixedTryAdvanceForEach(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testMixedTraverseAndSplit(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testMixedTraverseAndSplit(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testMixedTraverseAndSplitWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testMixedTraverseAndSplit(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testSplitAfterFullTraversal(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitAfterFullTraversal(s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testSplitAfterFullTraversalWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitAfterFullTraversal(s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testSplitOnce(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitOnce(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testSplitOnceWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitOnce(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testSplitSixDeep(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitSixDeep(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testSplitSixDeepWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitSixDeep(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliterator")
|
||||
void testSplitUntilNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitUntilNull(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "HashableIntSpliteratorWithNull")
|
||||
void testSplitUntilNullWithNull(String description,
|
||||
Collection<HashableInteger> exp,
|
||||
Supplier<Spliterator<HashableInteger>> s) {
|
||||
testSplitUntilNull(exp, s, UnaryOperator.identity());
|
||||
}
|
||||
|
||||
}
|
||||
184
test/jdk/java/util/Spliterator/SpliteratorFailFastTest.java
Normal file
184
test/jdk/java/util/Spliterator/SpliteratorFailFastTest.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.testng.Assert.ThrowingRunnable;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8148748
|
||||
* @summary Spliterator fail-fast tests
|
||||
* @run testng SpliteratorFailFastTest
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class SpliteratorFailFastTest extends SpliteratorLateBindingFailFastHelper {
|
||||
|
||||
static Object[][] spliteratorDataProvider;
|
||||
|
||||
@DataProvider(name = "Source")
|
||||
public static Object[][] spliteratorDataProvider() {
|
||||
if (spliteratorDataProvider != null) {
|
||||
return spliteratorDataProvider;
|
||||
}
|
||||
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
SpliteratorDataBuilder<Integer> db =
|
||||
new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
|
||||
|
||||
// Collections
|
||||
|
||||
db.addList(ArrayList::new);
|
||||
|
||||
db.addList(LinkedList::new);
|
||||
|
||||
db.addList(Vector::new);
|
||||
|
||||
db.addList(AbstractRandomAccessListImpl::new);
|
||||
|
||||
db.addCollection(HashSet::new);
|
||||
|
||||
db.addCollection(LinkedHashSet::new);
|
||||
|
||||
db.addCollection(TreeSet::new);
|
||||
|
||||
db.addCollection(c -> {
|
||||
Stack<Integer> s = new Stack<>();
|
||||
s.addAll(c);
|
||||
return s;
|
||||
});
|
||||
|
||||
db.addCollection(PriorityQueue::new);
|
||||
|
||||
// ArrayDeque fails some tests since its fail-fast support is weaker
|
||||
// than other collections and limited to detecting most, but not all,
|
||||
// removals. It probably requires its own test since it is difficult
|
||||
// to abstract out the conditions under which it fails-fast.
|
||||
// db.addCollection(ArrayDeque::new);
|
||||
|
||||
// Maps
|
||||
|
||||
db.addMap(HashMap::new);
|
||||
|
||||
db.addMap(LinkedHashMap::new);
|
||||
|
||||
// This fails when run through jtreg but passes when run through
|
||||
// ant
|
||||
// db.addMap(IdentityHashMap::new);
|
||||
|
||||
db.addMap(WeakHashMap::new);
|
||||
|
||||
// @@@ Descending maps etc
|
||||
db.addMap(TreeMap::new);
|
||||
|
||||
return spliteratorDataProvider = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "Source")
|
||||
public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
|
||||
{
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
s.tryAdvance(e -> {
|
||||
});
|
||||
source.update();
|
||||
|
||||
assertThrowsCME(() -> s.tryAdvance(e -> {
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
s.tryAdvance(e -> {
|
||||
});
|
||||
source.update();
|
||||
|
||||
assertThrowsCME(() -> s.forEachRemaining(e -> {
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "Source")
|
||||
public <T> void testForEach(String description, Supplier<Source<T>> ss) {
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
assertThrowsCME(() -> s.forEachRemaining(e -> {
|
||||
source.update();
|
||||
}));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "Source")
|
||||
public <T> void testEstimateSize(String description, Supplier<Source<T>> ss) {
|
||||
{
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
s.estimateSize();
|
||||
source.update();
|
||||
|
||||
assertThrowsCME(() -> s.tryAdvance(e -> {
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
s.estimateSize();
|
||||
source.update();
|
||||
|
||||
assertThrowsCME(() -> s.forEachRemaining(e -> {
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertThrowsCME(ThrowingRunnable r) {
|
||||
assertThrows(ConcurrentModificationException.class, r);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.RandomAccess;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class SpliteratorLateBindingFailFastHelper {
|
||||
|
||||
interface Source<T> {
|
||||
Spliterator<T> spliterator();
|
||||
|
||||
void update();
|
||||
|
||||
default boolean bindOnCharacteristics() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class IntSource<T> implements Source<Integer> {
|
||||
final T b;
|
||||
final Function<? super T, Spliterator.OfInt> toSpliterator;
|
||||
final Consumer<T> updater;
|
||||
final boolean bindOnCharacteristics;
|
||||
|
||||
public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
|
||||
Consumer<T> updater) {
|
||||
this(b, toSpliterator, updater, false);
|
||||
}
|
||||
|
||||
public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
|
||||
Consumer<T> updater, boolean bindOnCharacteristics) {
|
||||
this.b = b;
|
||||
this.toSpliterator = toSpliterator;
|
||||
this.updater = updater;
|
||||
this.bindOnCharacteristics = bindOnCharacteristics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator.OfInt spliterator() {
|
||||
return toSpliterator.apply(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updater.accept(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bindOnCharacteristics() {
|
||||
return bindOnCharacteristics;
|
||||
}
|
||||
}
|
||||
|
||||
static class SpliteratorDataBuilder<T> {
|
||||
final List<Object[]> data;
|
||||
|
||||
final T newValue;
|
||||
|
||||
final List<T> exp;
|
||||
|
||||
final Map<T, T> mExp;
|
||||
|
||||
SpliteratorDataBuilder(List<Object[]> data, T newValue, List<T> exp) {
|
||||
this.data = data;
|
||||
this.newValue = newValue;
|
||||
this.exp = exp;
|
||||
this.mExp = createMap(exp);
|
||||
}
|
||||
|
||||
Map<T, T> createMap(List<T> l) {
|
||||
Map<T, T> m = new LinkedHashMap<>();
|
||||
for (T t : l) {
|
||||
m.put(t, t);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
void add(String description, Supplier<Source<?>> s) {
|
||||
data.add(new Object[]{description, s});
|
||||
}
|
||||
|
||||
void addCollection(Function<Collection<T>, ? extends Collection<T>> f) {
|
||||
class CollectionSource implements Source<T> {
|
||||
final Collection<T> c = f.apply(exp);
|
||||
|
||||
final Consumer<Collection<T>> updater;
|
||||
|
||||
CollectionSource(Consumer<Collection<T>> updater) {
|
||||
this.updater = updater;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<T> spliterator() {
|
||||
return c.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updater.accept(c);
|
||||
}
|
||||
}
|
||||
|
||||
String description = "new " + f.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator() ";
|
||||
add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue)));
|
||||
add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next())));
|
||||
}
|
||||
|
||||
void addList(Function<Collection<T>, ? extends List<T>> l) {
|
||||
addCollection(l);
|
||||
addCollection(l.andThen(list -> list.subList(0, list.size())));
|
||||
}
|
||||
|
||||
void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) {
|
||||
class MapSource<U> implements Source<U> {
|
||||
final Map<T, T> m = mapConstructor.apply(mExp);
|
||||
|
||||
final Collection<U> c;
|
||||
|
||||
final Consumer<Map<T, T>> updater;
|
||||
|
||||
MapSource(Function<Map<T, T>, Collection<U>> f, Consumer<Map<T, T>> updater) {
|
||||
this.c = f.apply(m);
|
||||
this.updater = updater;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<U> spliterator() {
|
||||
return c.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updater.accept(m);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Consumer<Map<T, T>>> actions = new HashMap<>();
|
||||
actions.put("ADD", m -> m.put(newValue, newValue));
|
||||
actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next()));
|
||||
|
||||
String description = "new " + mapConstructor.apply(Collections.<T, T>emptyMap()).getClass().getName();
|
||||
for (Map.Entry<String, Consumer<Map<T, T>>> e : actions.entrySet()) {
|
||||
add(description + ".keySet().spliterator() " + e.getKey(),
|
||||
() -> new MapSource<>(m -> m.keySet(), e.getValue()));
|
||||
add(description + ".values().spliterator() " + e.getKey(),
|
||||
() -> new MapSource<>(m -> m.values(), e.getValue()));
|
||||
add(description + ".entrySet().spliterator() " + e.getKey(),
|
||||
() -> new MapSource<>(m -> m.entrySet(), e.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class AbstractRandomAccessListImpl extends AbstractList<Integer> implements RandomAccess {
|
||||
List<Integer> l;
|
||||
|
||||
AbstractRandomAccessListImpl(Collection<Integer> c) {
|
||||
this.l = new ArrayList<>(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Integer integer) {
|
||||
modCount++;
|
||||
return l.add(integer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
return l.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(int index) {
|
||||
return l.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
modCount++;
|
||||
return l.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return l.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> subList(int fromIndex, int toIndex) {
|
||||
return l.subList(fromIndex, toIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
221
test/jdk/java/util/Spliterator/SpliteratorLateBindingTest.java
Normal file
221
test/jdk/java/util/Spliterator/SpliteratorLateBindingTest.java
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8148748 8170155
|
||||
* @summary Spliterator last-binding tests
|
||||
* @run testng SpliteratorLateBindingTest
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class SpliteratorLateBindingTest extends SpliteratorLateBindingFailFastHelper {
|
||||
|
||||
static Object[][] spliteratorDataProvider;
|
||||
|
||||
@DataProvider(name = "Source")
|
||||
public static Object[][] sourceDataProvider() {
|
||||
if (spliteratorDataProvider != null) {
|
||||
return spliteratorDataProvider;
|
||||
}
|
||||
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
SpliteratorDataBuilder<Integer> db =
|
||||
new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
|
||||
|
||||
// Collections
|
||||
|
||||
db.addList(ArrayList::new);
|
||||
|
||||
db.addList(LinkedList::new);
|
||||
|
||||
db.addList(Vector::new);
|
||||
|
||||
db.addList(AbstractRandomAccessListImpl::new);
|
||||
|
||||
db.addCollection(HashSet::new);
|
||||
|
||||
db.addCollection(LinkedHashSet::new);
|
||||
|
||||
db.addCollection(TreeSet::new);
|
||||
|
||||
db.addCollection(c -> {
|
||||
Stack<Integer> s = new Stack<>();
|
||||
s.addAll(c);
|
||||
return s;
|
||||
});
|
||||
|
||||
db.addCollection(PriorityQueue::new);
|
||||
|
||||
db.addCollection(ArrayDeque::new);
|
||||
|
||||
// Maps
|
||||
|
||||
db.addMap(HashMap::new);
|
||||
|
||||
db.addMap(LinkedHashMap::new);
|
||||
|
||||
db.addMap(IdentityHashMap::new);
|
||||
|
||||
db.addMap(WeakHashMap::new);
|
||||
|
||||
// @@@ Descending maps etc
|
||||
db.addMap(TreeMap::new);
|
||||
|
||||
// BitSet
|
||||
|
||||
List<Integer> bits = List.of(0, 1, 2);
|
||||
Function<BitSet, Spliterator.OfInt> bitsSource = bs -> bs.stream().spliterator();
|
||||
db.add("new BitSet.stream().spliterator() ADD",
|
||||
() -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.set(3)));
|
||||
db.add("new BitSet.stream().spliterator() REMOVE",
|
||||
() -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.clear(2)));
|
||||
|
||||
// CharSequence
|
||||
|
||||
Function<CharSequence, Spliterator.OfInt> charsSource = sb -> sb.chars().spliterator();
|
||||
Function<CharSequence, Spliterator.OfInt> pointsSource = sb -> sb.codePoints().spliterator();
|
||||
|
||||
db.add("new StringBuilder.chars().spliterator() ADD",
|
||||
() -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.append("D"), true));
|
||||
db.add("new StringBuilder.chars().spliterator() REMOVE",
|
||||
() -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
|
||||
db.add("new StringBuilder.codePoints().spliterator() ADD",
|
||||
() -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.append("D"), true));
|
||||
db.add("new StringBuilder.codePoints().spliterator() REMOVE",
|
||||
() -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
|
||||
|
||||
db.add("new StringBuffer.chars().spliterator() ADD",
|
||||
() -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.append("D"), true));
|
||||
db.add("new StringBuffer.chars().spliterator() REMOVE",
|
||||
() -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
|
||||
db.add("new StringBuffer.codePoints().spliterator() ADD",
|
||||
() -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.append("D"), true));
|
||||
db.add("new StringBuffer.codePoints().spliterator() REMOVE",
|
||||
() -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
|
||||
|
||||
db.add("CharBuffer.wrap().chars().spliterator() ADD",
|
||||
() -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), charsSource, bs -> bs.limit(4), true));
|
||||
db.add("CharBuffer.wrap().chars().spliterator() REMOVE",
|
||||
() -> new IntSource<>(CharBuffer.wrap("ABCD"), charsSource, bs -> bs.limit(3), true));
|
||||
db.add("CharBuffer.wrap().codePoints().spliterator() ADD",
|
||||
() -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), pointsSource, bs -> bs.limit(4), true));
|
||||
db.add("CharBuffer.wrap().codePoints().spliterator() REMOVE",
|
||||
() -> new IntSource<>(CharBuffer.wrap("ABCD"), pointsSource, bs -> bs.limit(3), true));
|
||||
|
||||
return spliteratorDataProvider = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "Source.Non.Binding.Characteristics")
|
||||
public static Object[][] sourceCharacteristicsDataProvider() {
|
||||
return Stream.of(sourceDataProvider()).filter(tc -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Source<?>> s = (Supplier<Source<?>>) tc[1];
|
||||
return !s.get().bindOnCharacteristics();
|
||||
}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
static BitSet toBitSet(List<Integer> bits) {
|
||||
BitSet bs = new BitSet();
|
||||
bits.forEach(bs::set);
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "Source")
|
||||
public <T> void testForEach(String description, Supplier<Source<T>> ss) {
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
source.update();
|
||||
|
||||
Set<T> a = new HashSet<>();
|
||||
s.forEachRemaining(a::add);
|
||||
|
||||
Set<T> e = new HashSet<>();
|
||||
source.spliterator().forEachRemaining(e::add);
|
||||
assertEquals(a, e);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "Source")
|
||||
public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
source.update();
|
||||
|
||||
Set<T> a = new HashSet<>();
|
||||
while (s.tryAdvance(a::add)) {
|
||||
}
|
||||
|
||||
Set<T> e = new HashSet<>();
|
||||
source.spliterator().forEachRemaining(e::add);
|
||||
assertEquals(a, e);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "Source.Non.Binding.Characteristics")
|
||||
public <T> void testCharacteristics(String description, Supplier<Source<T>> ss) {
|
||||
Source<T> source = ss.get();
|
||||
Spliterator<T> s = source.spliterator();
|
||||
|
||||
s.characteristics();
|
||||
source.update();
|
||||
|
||||
Set<T> a = new HashSet<>();
|
||||
s.forEachRemaining(a::add);
|
||||
|
||||
Set<T> e = new HashSet<>();
|
||||
source.spliterator().forEachRemaining(e::add);
|
||||
assertEquals(a, e);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue