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
261
test/jdk/java/util/Collection/BiggernYours.java
Normal file
261
test/jdk/java/util/Collection/BiggernYours.java
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2014, 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 6415641 6377302
|
||||
* @summary Concurrent collections are permitted to lie about their size
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BiggernYours {
|
||||
static final Random rnd = new Random(18675309);
|
||||
|
||||
static void compareCollections(Collection c1, Collection c2) {
|
||||
Object[] c1Array = c1.toArray();
|
||||
Object[] c2Array = c2.toArray();
|
||||
|
||||
check(c1Array.length == c2Array.length);
|
||||
for (Object aC1 : c1Array) {
|
||||
boolean found = false;
|
||||
for (Object aC2 : c2Array) {
|
||||
if (Objects.equals(aC1, aC2)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fail(aC1 + " not found in " + Arrays.toString(c2Array));
|
||||
}
|
||||
}
|
||||
|
||||
static void compareMaps(Map m1, Map m2) {
|
||||
compareCollections(m1.keySet(),
|
||||
m2.keySet());
|
||||
compareCollections(m1.values(),
|
||||
m2.values());
|
||||
compareCollections(m1.entrySet(),
|
||||
m2.entrySet());
|
||||
}
|
||||
|
||||
static void compareNavigableMaps(NavigableMap m1, NavigableMap m2) {
|
||||
compareMaps(m1, m2);
|
||||
compareMaps(m1.descendingMap(),
|
||||
m2.descendingMap());
|
||||
compareMaps(m1.tailMap(Integer.MIN_VALUE),
|
||||
m2.tailMap(Integer.MIN_VALUE));
|
||||
compareMaps(m1.headMap(Integer.MAX_VALUE),
|
||||
m2.headMap(Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
static void compareNavigableSets(NavigableSet s1, NavigableSet s2) {
|
||||
compareCollections(s1, s2);
|
||||
compareCollections(s1.descendingSet(),
|
||||
s2.descendingSet());
|
||||
compareCollections(s1.tailSet(Integer.MIN_VALUE),
|
||||
s2.tailSet(Integer.MIN_VALUE));
|
||||
}
|
||||
|
||||
abstract static class MapFrobber { abstract void frob(Map m); }
|
||||
abstract static class SetFrobber { abstract void frob(Set s); }
|
||||
abstract static class ColFrobber { abstract void frob(Collection c); }
|
||||
|
||||
static ColFrobber adder(final int i) {
|
||||
return new ColFrobber() {void frob(Collection c) { c.add(i); }};
|
||||
}
|
||||
|
||||
static final ColFrobber[] adders =
|
||||
{ adder(1), adder(3), adder(2) };
|
||||
|
||||
static MapFrobber putter(final int k, final int v) {
|
||||
return new MapFrobber() {void frob(Map m) { m.put(k,v); }};
|
||||
}
|
||||
|
||||
static final MapFrobber[] putters =
|
||||
{ putter(1, -2), putter(3, -6), putter(2, -4) };
|
||||
|
||||
static void unexpected(Throwable t, Object suspect) {
|
||||
System.out.println(suspect.getClass());
|
||||
unexpected(t);
|
||||
}
|
||||
|
||||
static void testCollections(Collection c1, Collection c2) {
|
||||
try {
|
||||
compareCollections(c1, c2);
|
||||
for (ColFrobber adder : adders) {
|
||||
for (Collection c : new Collection[]{c1, c2})
|
||||
adder.frob(c);
|
||||
compareCollections(c1, c2);
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t, c1); }
|
||||
}
|
||||
|
||||
static void testNavigableSets(NavigableSet s1, NavigableSet s2) {
|
||||
try {
|
||||
compareNavigableSets(s1, s2);
|
||||
for (ColFrobber adder : adders) {
|
||||
for (Set s : new Set[]{s1, s2})
|
||||
adder.frob(s);
|
||||
compareNavigableSets(s1, s2);
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t, s1); }
|
||||
}
|
||||
|
||||
static void testMaps(Map m1, Map m2) {
|
||||
try {
|
||||
compareMaps(m1, m2);
|
||||
for (MapFrobber putter : putters) {
|
||||
for (Map m : new Map[]{m1, m2})
|
||||
putter.frob(m);
|
||||
compareMaps(m1, m2);
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t, m1); }
|
||||
}
|
||||
|
||||
static void testNavigableMaps(NavigableMap m1, NavigableMap m2) {
|
||||
try {
|
||||
compareNavigableMaps(m1, m2);
|
||||
for (MapFrobber putter : putters) {
|
||||
for (Map m : new Map[]{m1, m2})
|
||||
putter.frob(m);
|
||||
compareNavigableMaps(m1, m2);
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t, m1); }
|
||||
}
|
||||
|
||||
static int randomize(int size) { return rnd.nextInt(size + 2); }
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static void realMain(String[] args) {
|
||||
testNavigableMaps(
|
||||
new ConcurrentSkipListMap(),
|
||||
new ConcurrentSkipListMap() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testNavigableSets(
|
||||
new ConcurrentSkipListSet(),
|
||||
new ConcurrentSkipListSet() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new CopyOnWriteArraySet(),
|
||||
new CopyOnWriteArraySet() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new CopyOnWriteArrayList(),
|
||||
new CopyOnWriteArrayList() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new TreeSet(),
|
||||
new TreeSet() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testMaps(
|
||||
new ConcurrentHashMap(),
|
||||
new ConcurrentHashMap() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new ConcurrentLinkedDeque(),
|
||||
new ConcurrentLinkedDeque() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new ConcurrentLinkedQueue(),
|
||||
new ConcurrentLinkedQueue() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new LinkedTransferQueue(),
|
||||
new LinkedTransferQueue() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new LinkedBlockingQueue(),
|
||||
new LinkedBlockingQueue() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new LinkedBlockingDeque(),
|
||||
new LinkedBlockingDeque() {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new ArrayBlockingQueue(5),
|
||||
new ArrayBlockingQueue(5) {
|
||||
public int size() {return randomize(super.size());}});
|
||||
|
||||
testCollections(
|
||||
new PriorityBlockingQueue(5),
|
||||
new PriorityBlockingQueue(5) {
|
||||
public int size() {return randomize(super.size());}});
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
static void arrayEqual(Object[] x, Object[] y) {
|
||||
if (x == null ? y == null : Arrays.equals(x, y)) pass();
|
||||
else fail(Arrays.toString(x) + " not equal to " + Arrays.toString(y));}
|
||||
public static void main(String[] args) {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
private abstract static class CheckedThread extends Thread {
|
||||
abstract void realRun() throws Throwable;
|
||||
public void run() {
|
||||
try {realRun();} catch (Throwable t) {unexpected(t);}}}
|
||||
}
|
||||
195
test/jdk/java/util/Collection/CollectionDefaults.java
Normal file
195
test/jdk/java/util/Collection/CollectionDefaults.java
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 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.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Unit tests for extension methods on Collection
|
||||
* @library testlibrary
|
||||
* @build CollectionAsserts CollectionSupplier ExtendsAbstractSet ExtendsAbstractCollection
|
||||
* @run testng CollectionDefaults
|
||||
*/
|
||||
public class CollectionDefaults {
|
||||
|
||||
public static final Predicate<Integer> pEven = x -> 0 == x % 2;
|
||||
public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
|
||||
|
||||
private static final int SIZE = 100;
|
||||
|
||||
private static final List<Function<Collection<Integer>, Collection<Integer>>> TEST_SUPPLIERS = Arrays.asList(
|
||||
// Collection
|
||||
ExtendsAbstractCollection<Integer>::new,
|
||||
java.util.ArrayDeque<Integer>::new,
|
||||
java.util.concurrent.ConcurrentLinkedDeque<Integer>::new,
|
||||
java.util.concurrent.ConcurrentLinkedQueue<Integer>::new,
|
||||
java.util.concurrent.LinkedBlockingDeque<Integer>::new,
|
||||
java.util.concurrent.LinkedBlockingQueue<Integer>::new,
|
||||
java.util.concurrent.LinkedTransferQueue<Integer>::new,
|
||||
(coll) -> new java.util.concurrent.ArrayBlockingQueue<Integer>(
|
||||
3 * SIZE, false, coll),
|
||||
|
||||
// Lists
|
||||
java.util.ArrayList<Integer>::new,
|
||||
java.util.LinkedList<Integer>::new,
|
||||
java.util.Vector<Integer>::new,
|
||||
java.util.concurrent.CopyOnWriteArrayList<Integer>::new,
|
||||
ExtendsAbstractList<Integer>::new,
|
||||
|
||||
// Sets
|
||||
java.util.HashSet<Integer>::new,
|
||||
java.util.LinkedHashSet<Integer>::new,
|
||||
java.util.TreeSet<Integer>::new,
|
||||
java.util.concurrent.ConcurrentSkipListSet<Integer>::new,
|
||||
java.util.concurrent.CopyOnWriteArraySet<Integer>::new,
|
||||
ExtendsAbstractSet<Integer>::new
|
||||
);
|
||||
|
||||
@DataProvider(name="setProvider", parallel=true)
|
||||
public static Iterator<Object[]> setCases() {
|
||||
final List<Object[]> cases = new LinkedList<>();
|
||||
cases.add(new Object[] { new HashSet<>() });
|
||||
cases.add(new Object[] { new LinkedHashSet<>() });
|
||||
cases.add(new Object[] { new TreeSet<>() });
|
||||
cases.add(new Object[] { new java.util.concurrent.ConcurrentSkipListSet<>() });
|
||||
cases.add(new Object[] { new java.util.concurrent.CopyOnWriteArraySet<>() });
|
||||
|
||||
cases.add(new Object[] { new ExtendsAbstractSet<>() });
|
||||
|
||||
cases.add(new Object[] { Collections.newSetFromMap(new HashMap<>()) });
|
||||
cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap<>()) });
|
||||
cases.add(new Object[] { Collections.newSetFromMap(new TreeMap<>()) });
|
||||
cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentHashMap<>()) });
|
||||
cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentSkipListMap<>()) });
|
||||
|
||||
cases.add(new Object[] { new HashSet<Integer>(){{add(42);}} });
|
||||
cases.add(new Object[] { new ExtendsAbstractSet<Integer>(){{add(42);}} });
|
||||
cases.add(new Object[] { new LinkedHashSet<Integer>(){{add(42);}} });
|
||||
cases.add(new Object[] { new TreeSet<Integer>(){{add(42);}} });
|
||||
return cases.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "setProvider")
|
||||
public void testProvidedWithNull(final Set<Integer> set) {
|
||||
try {
|
||||
set.forEach(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException expected) { // expected
|
||||
}
|
||||
try {
|
||||
set.removeIf(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException expected) { // expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForEach() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE);
|
||||
|
||||
for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
|
||||
final Collection<Integer> original = test.expected;
|
||||
final Collection<Integer> set = test.collection;
|
||||
|
||||
try {
|
||||
set.forEach(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException expected) { // expected
|
||||
}
|
||||
if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
|
||||
CollectionAsserts.assertContentsUnordered(set, original, test.toString());
|
||||
} else {
|
||||
CollectionAsserts.assertContents(set, original, test.toString());
|
||||
}
|
||||
|
||||
final List<Integer> actual = new LinkedList<>();
|
||||
set.forEach(actual::add);
|
||||
if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
|
||||
CollectionAsserts.assertContentsUnordered(actual, set, test.toString());
|
||||
CollectionAsserts.assertContentsUnordered(actual, original, test.toString());
|
||||
} else {
|
||||
CollectionAsserts.assertContents(actual, set, test.toString());
|
||||
CollectionAsserts.assertContents(actual, original, test.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveIf() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
|
||||
final Collection<Integer> original = test.expected;
|
||||
final Collection<Integer> set = test.collection;
|
||||
|
||||
try {
|
||||
set.removeIf(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException expected) { // expected
|
||||
}
|
||||
if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
|
||||
CollectionAsserts.assertContentsUnordered(set, original, test.toString());
|
||||
} else {
|
||||
CollectionAsserts.assertContents(set, original, test.toString());
|
||||
}
|
||||
|
||||
set.removeIf(pEven);
|
||||
for (int i : set) {
|
||||
assertTrue((i % 2) == 1);
|
||||
}
|
||||
for (int i : original) {
|
||||
if (i % 2 == 1) {
|
||||
assertTrue(set.contains(i));
|
||||
}
|
||||
}
|
||||
set.removeIf(pOdd);
|
||||
assertTrue(set.isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
114
test/jdk/java/util/Collection/HotPotatoes.java
Normal file
114
test/jdk/java/util/Collection/HotPotatoes.java
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2006, 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 6355660 6347106 6394004
|
||||
* @summary methods taking concurrently mutating collection should work
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class HotPotatoes {
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
testImplementation(Vector.class);
|
||||
testImplementation(ArrayList.class);
|
||||
testImplementation(PriorityQueue.class);
|
||||
testImplementation(PriorityBlockingQueue.class);
|
||||
}
|
||||
|
||||
private static void testImplementation(Class<? extends Collection> implClazz)
|
||||
throws Throwable
|
||||
{
|
||||
testPotato(implClazz, Vector.class);
|
||||
testPotato(implClazz, CopyOnWriteArrayList.class);
|
||||
|
||||
final Constructor<? extends Collection> constr
|
||||
= implClazz.getConstructor(Collection.class);
|
||||
final Collection<Object> coll
|
||||
= constr.newInstance(Arrays.asList(new String[] {}));
|
||||
coll.add(1);
|
||||
equal(coll.toString(), "[1]");
|
||||
}
|
||||
|
||||
private static void testPotato(Class<? extends Collection> implClazz,
|
||||
Class<? extends List> argClazz)
|
||||
throws Throwable
|
||||
{
|
||||
try {
|
||||
System.out.printf("implClazz=%s, argClazz=%s\n",
|
||||
implClazz.getName(), argClazz.getName());
|
||||
final int iterations = 100000;
|
||||
final List<Integer> list = (List<Integer>)
|
||||
argClazz.getDeclaredConstructor().newInstance();
|
||||
final Integer one = Integer.valueOf(1);
|
||||
final List<Integer> oneElementList = Collections.singletonList(one);
|
||||
final Constructor<? extends Collection> constr
|
||||
= implClazz.getConstructor(Collection.class);
|
||||
final Thread t = new CheckedThread() { public void realRun() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
list.add(one);
|
||||
list.remove(one);
|
||||
}}};
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Collection<?> coll = constr.newInstance(list);
|
||||
Object[] elts = coll.toArray();
|
||||
check(elts.length == 0 ||
|
||||
(elts.length == 1 && elts[0] == one));
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
private abstract static class CheckedThread extends Thread {
|
||||
public abstract void realRun() throws Throwable;
|
||||
public void run() {
|
||||
try { realRun(); } catch (Throwable t) { unexpected(t); }}}
|
||||
}
|
||||
166
test/jdk/java/util/Collection/IteratorAtEnd.java
Normal file
166
test/jdk/java/util/Collection/IteratorAtEnd.java
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2014, 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 6529795
|
||||
* @summary next() does not change iterator state if throws NoSuchElementException
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class IteratorAtEnd {
|
||||
private static final int SIZE = 6;
|
||||
|
||||
static void realMain(String[] args) throws Throwable {
|
||||
testCollection(new ArrayList());
|
||||
testCollection(new Vector());
|
||||
testCollection(new LinkedList());
|
||||
testCollection(new ArrayDeque());
|
||||
testCollection(new TreeSet());
|
||||
testCollection(new CopyOnWriteArrayList());
|
||||
testCollection(new CopyOnWriteArraySet());
|
||||
testCollection(new ConcurrentSkipListSet());
|
||||
|
||||
testCollection(new PriorityQueue());
|
||||
testCollection(new LinkedBlockingQueue());
|
||||
testCollection(new ArrayBlockingQueue(100));
|
||||
testCollection(new ConcurrentLinkedDeque());
|
||||
testCollection(new ConcurrentLinkedQueue());
|
||||
testCollection(new LinkedTransferQueue());
|
||||
|
||||
testMap(new HashMap());
|
||||
testMap(new Hashtable());
|
||||
testMap(new LinkedHashMap());
|
||||
testMap(new WeakHashMap());
|
||||
testMap(new IdentityHashMap());
|
||||
testMap(new ConcurrentHashMap());
|
||||
testMap(new ConcurrentSkipListMap());
|
||||
testMap(new TreeMap());
|
||||
}
|
||||
|
||||
static void testCollection(Collection c) {
|
||||
try {
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
c.add(i);
|
||||
test(c);
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
static void testMap(Map m) {
|
||||
try {
|
||||
for (int i = 0; i < 3*SIZE; i++)
|
||||
m.put(i, i);
|
||||
test(m.values());
|
||||
test(m.keySet());
|
||||
test(m.entrySet());
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
static void test(Collection c) {
|
||||
try {
|
||||
final Iterator it = c.iterator();
|
||||
THROWS(NoSuchElementException.class,
|
||||
() -> { while (true) it.next(); });
|
||||
try { it.remove(); }
|
||||
catch (UnsupportedOperationException exc) { return; }
|
||||
pass();
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
|
||||
if (c instanceof List) {
|
||||
final List list = (List) c;
|
||||
try {
|
||||
final ListIterator it = list.listIterator(0);
|
||||
it.next();
|
||||
final Object x = it.previous();
|
||||
THROWS(NoSuchElementException.class, () -> it.previous());
|
||||
try { it.remove(); }
|
||||
catch (UnsupportedOperationException exc) { return; }
|
||||
pass();
|
||||
check(! list.get(0).equals(x));
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
|
||||
try {
|
||||
final ListIterator it = list.listIterator(list.size());
|
||||
it.previous();
|
||||
final Object x = it.next();
|
||||
THROWS(NoSuchElementException.class, () -> it.next());
|
||||
try { it.remove(); }
|
||||
catch (UnsupportedOperationException exc) { return; }
|
||||
pass();
|
||||
check(! list.get(list.size()-1).equals(x));
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
interface Fun {void f() throws Throwable;}
|
||||
static void THROWS(Class<? extends Throwable> k, Fun... fs) {
|
||||
for (Fun f : fs)
|
||||
try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
}
|
||||
628
test/jdk/java/util/Collection/IteratorMicroBenchmark.java
Normal file
628
test/jdk/java/util/Collection/IteratorMicroBenchmark.java
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* @summary micro-benchmark correctness mode
|
||||
* @run main IteratorMicroBenchmark iterations=1 size=8 warmup=0
|
||||
*/
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.stream.Collectors.summingInt;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
|
||||
*
|
||||
* To run this in micro-benchmark mode, simply run as a normal java program.
|
||||
* Be patient; this program runs for a very long time.
|
||||
* For faster runs, restrict execution using command line args.
|
||||
*
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
public class IteratorMicroBenchmark {
|
||||
abstract static class Job {
|
||||
private final String name;
|
||||
public Job(String name) { this.name = name; }
|
||||
public String name() { return name; }
|
||||
public abstract void work() throws Throwable;
|
||||
public void run() {
|
||||
try { work(); }
|
||||
catch (Throwable ex) {
|
||||
// current job cannot always be deduced from stacktrace.
|
||||
throw new RuntimeException("Job failed: " + name(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int iterations;
|
||||
final int size; // number of elements in collections
|
||||
final double warmupSeconds;
|
||||
final long warmupNanos;
|
||||
final Pattern nameFilter; // select subset of Jobs to run
|
||||
final boolean reverse; // reverse order of Jobs
|
||||
final boolean shuffle; // randomize order of Jobs
|
||||
|
||||
IteratorMicroBenchmark(String[] args) {
|
||||
iterations = intArg(args, "iterations", 10_000);
|
||||
size = intArg(args, "size", 1000);
|
||||
warmupSeconds = doubleArg(args, "warmup", 7.0);
|
||||
nameFilter = patternArg(args, "filter");
|
||||
reverse = booleanArg(args, "reverse");
|
||||
shuffle = booleanArg(args, "shuffle");
|
||||
|
||||
warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
|
||||
}
|
||||
|
||||
// --------------- GC finalization infrastructure ---------------
|
||||
|
||||
/** No guarantees, but effective in practice. */
|
||||
static void forceFullGc() {
|
||||
long timeoutMillis = 1000L;
|
||||
CountDownLatch finalized = new CountDownLatch(1);
|
||||
ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
WeakReference<Object> ref = new WeakReference<>(
|
||||
new Object() {
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void finalize() { finalized.countDown(); }},
|
||||
queue);
|
||||
try {
|
||||
for (int tries = 3; tries--> 0; ) {
|
||||
System.gc();
|
||||
if (finalized.await(timeoutMillis, MILLISECONDS)
|
||||
&& queue.remove(timeoutMillis) != null
|
||||
&& ref.get() == null) {
|
||||
System.runFinalization(); // try to pick up stragglers
|
||||
return;
|
||||
}
|
||||
timeoutMillis *= 4;
|
||||
}
|
||||
} catch (InterruptedException unexpected) {
|
||||
throw new AssertionError("unexpected InterruptedException");
|
||||
}
|
||||
throw new AssertionError("failed to do a \"full\" gc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs each job for long enough that all the runtime compilers
|
||||
* have had plenty of time to warm up, i.e. get around to
|
||||
* compiling everything worth compiling.
|
||||
* Returns array of average times per job per run.
|
||||
*/
|
||||
long[] time0(List<Job> jobs) {
|
||||
final int size = jobs.size();
|
||||
long[] nanoss = new long[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (warmupNanos > 0) forceFullGc();
|
||||
Job job = jobs.get(i);
|
||||
long totalTime;
|
||||
int runs = 0;
|
||||
long startTime = System.nanoTime();
|
||||
do { job.run(); runs++; }
|
||||
while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
|
||||
nanoss[i] = totalTime/runs;
|
||||
}
|
||||
return nanoss;
|
||||
}
|
||||
|
||||
void time(List<Job> jobs) throws Throwable {
|
||||
if (warmupNanos > 0) time0(jobs); // Warm up run
|
||||
final int size = jobs.size();
|
||||
final long[] nanoss = time0(jobs); // Real timing run
|
||||
final long[] milliss = new long[size];
|
||||
final double[] ratios = new double[size];
|
||||
|
||||
final String nameHeader = "Method";
|
||||
final String millisHeader = "Millis";
|
||||
final String ratioHeader = "Ratio";
|
||||
|
||||
int nameWidth = nameHeader.length();
|
||||
int millisWidth = millisHeader.length();
|
||||
int ratioWidth = ratioHeader.length();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
nameWidth = Math.max(nameWidth, jobs.get(i).name().length());
|
||||
|
||||
milliss[i] = nanoss[i]/(1000L * 1000L);
|
||||
millisWidth = Math.max(millisWidth,
|
||||
String.format("%d", milliss[i]).length());
|
||||
|
||||
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
|
||||
ratioWidth = Math.max(ratioWidth,
|
||||
String.format("%.3f", ratios[i]).length());
|
||||
}
|
||||
|
||||
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
|
||||
|
||||
// Print out absolute and relative times, calibrated against first job
|
||||
for (int i = 0; i < size; i++)
|
||||
System.out.printf(format, jobs.get(i).name(), milliss[i], ratios[i]);
|
||||
}
|
||||
|
||||
private static String keywordValue(String[] args, String keyword) {
|
||||
for (String arg : args)
|
||||
if (arg.startsWith(keyword))
|
||||
return arg.substring(keyword.length() + 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int intArg(String[] args, String keyword, int defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Integer.parseInt(val);
|
||||
}
|
||||
|
||||
private static double doubleArg(String[] args, String keyword, double defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Double.parseDouble(val);
|
||||
}
|
||||
|
||||
private static Pattern patternArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? null : Pattern.compile(val);
|
||||
}
|
||||
|
||||
private static boolean booleanArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
if (val == null || val.equals("false")) return false;
|
||||
if (val.equals("true")) return true;
|
||||
throw new IllegalArgumentException(val);
|
||||
}
|
||||
|
||||
private static void deoptimize(int sum) {
|
||||
if (sum == 42)
|
||||
System.out.println("the answer");
|
||||
}
|
||||
|
||||
private static <T> Iterable<T> backwards(final List<T> list) {
|
||||
return new Iterable<T>() {
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
final ListIterator<T> it = list.listIterator(list.size());
|
||||
public boolean hasNext() { return it.hasPrevious(); }
|
||||
public T next() { return it.previous(); }
|
||||
public void remove() { it.remove(); }};}};
|
||||
}
|
||||
|
||||
// Checks for correctness *and* prevents loop optimizations
|
||||
static class Check {
|
||||
private int sum;
|
||||
public void sum(int sum) {
|
||||
if (this.sum == 0)
|
||||
this.sum = sum;
|
||||
if (this.sum != sum)
|
||||
throw new AssertionError("Sum mismatch");
|
||||
}
|
||||
}
|
||||
volatile Check check = new Check();
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new IteratorMicroBenchmark(args).run();
|
||||
}
|
||||
|
||||
HashMap<Class<?>, String> goodClassName = new HashMap<>();
|
||||
|
||||
String goodClassName(Class<?> klazz) {
|
||||
return goodClassName.computeIfAbsent(
|
||||
klazz,
|
||||
k -> {
|
||||
String simple = k.getSimpleName();
|
||||
return (simple.equals("SubList")) // too simple!
|
||||
? k.getName().replaceFirst(".*\\.", "")
|
||||
: simple;
|
||||
});
|
||||
}
|
||||
|
||||
String goodClassName(Object x) {
|
||||
return goodClassName(x.getClass());
|
||||
}
|
||||
|
||||
static List<Integer> makeSubList(
|
||||
List<Integer> elements,
|
||||
UnaryOperator<List<Integer>> copyConstructor) {
|
||||
final ArrayList<Integer> padded = new ArrayList<>();
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
final int frontPorch = rnd.nextInt(3);
|
||||
final int backPorch = rnd.nextInt(3);
|
||||
for (int n = frontPorch; n--> 0; ) padded.add(rnd.nextInt());
|
||||
padded.addAll(elements);
|
||||
for (int n = backPorch; n--> 0; ) padded.add(rnd.nextInt());
|
||||
return copyConstructor.apply(padded)
|
||||
.subList(frontPorch, frontPorch + elements.size());
|
||||
}
|
||||
|
||||
void run() throws Throwable {
|
||||
final ArrayList<Integer> al = new ArrayList<>(size);
|
||||
|
||||
// Populate collections with random data
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
for (int i = 0; i < size; i++)
|
||||
al.add(rnd.nextInt(size));
|
||||
|
||||
final ArrayDeque<Integer> ad = new ArrayDeque<>(al);
|
||||
final ArrayBlockingQueue<Integer> abq = new ArrayBlockingQueue<>(al.size());
|
||||
abq.addAll(al);
|
||||
|
||||
// shuffle circular array elements so they wrap
|
||||
for (int i = 0, n = rnd.nextInt(size); i < n; i++) {
|
||||
ad.addLast(ad.removeFirst());
|
||||
abq.add(abq.remove());
|
||||
}
|
||||
|
||||
final Integer[] array = al.toArray(new Integer[0]);
|
||||
final List<Integer> immutableSubList
|
||||
= makeSubList(al, x -> List.of(x.toArray(new Integer[0])));
|
||||
|
||||
Stream<Collection<Integer>> collections = concatStreams(
|
||||
Stream.of(
|
||||
// Lists and their subLists
|
||||
al,
|
||||
makeSubList(al, ArrayList::new),
|
||||
new Vector<>(al),
|
||||
makeSubList(al, Vector::new),
|
||||
new LinkedList<>(al),
|
||||
makeSubList(al, LinkedList::new),
|
||||
new CopyOnWriteArrayList<>(al),
|
||||
makeSubList(al, CopyOnWriteArrayList::new),
|
||||
|
||||
ad,
|
||||
new PriorityQueue<>(al),
|
||||
new ConcurrentLinkedQueue<>(al),
|
||||
new ConcurrentLinkedDeque<>(al),
|
||||
|
||||
// Blocking Queues
|
||||
abq,
|
||||
new LinkedBlockingQueue<>(al),
|
||||
new LinkedBlockingDeque<>(al),
|
||||
new LinkedTransferQueue<>(al),
|
||||
new PriorityBlockingQueue<>(al),
|
||||
|
||||
List.of(al.toArray(new Integer[0]))),
|
||||
|
||||
// avoid UnsupportedOperationException in jdk9 and jdk10
|
||||
(goodClassName(immutableSubList).equals("RandomAccessSubList"))
|
||||
? Stream.empty()
|
||||
: Stream.of(immutableSubList));
|
||||
|
||||
ArrayList<Job> jobs = collections
|
||||
.flatMap(x -> jobs(x))
|
||||
.filter(job ->
|
||||
nameFilter == null || nameFilter.matcher(job.name()).find())
|
||||
.collect(toCollection(ArrayList::new));
|
||||
|
||||
if (reverse) Collections.reverse(jobs);
|
||||
if (shuffle) Collections.shuffle(jobs);
|
||||
|
||||
time(jobs);
|
||||
}
|
||||
|
||||
@SafeVarargs @SuppressWarnings("varargs")
|
||||
private static <T> Stream<T> concatStreams(Stream<T> ... streams) {
|
||||
return Stream.of(streams).flatMap(s -> s);
|
||||
}
|
||||
|
||||
boolean isMutable(Collection<Integer> x) {
|
||||
return !(x.getClass().getName().contains("ImmutableCollections$"));
|
||||
}
|
||||
|
||||
Stream<Job> jobs(Collection<Integer> x) {
|
||||
return concatStreams(
|
||||
collectionJobs(x),
|
||||
|
||||
(isMutable(x))
|
||||
? mutableCollectionJobs(x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof Deque)
|
||||
? dequeJobs((Deque<Integer>)x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof List)
|
||||
? listJobs((List<Integer>)x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof List && isMutable(x))
|
||||
? mutableListJobs((List<Integer>)x)
|
||||
: Stream.empty());
|
||||
}
|
||||
|
||||
Object sneakyAdder(int[] sneakySum) {
|
||||
return new Object() {
|
||||
public int hashCode() { throw new AssertionError(); }
|
||||
public boolean equals(Object z) {
|
||||
sneakySum[0] += (int) z; return false; }};
|
||||
}
|
||||
|
||||
Stream<Job> collectionJobs(Collection<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : x)
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job(klazz + " iterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.iterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " spliterator().tryAdvance()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
Spliterator<Integer> spliterator = x.spliterator();
|
||||
do {} while (spliterator.tryAdvance(n -> sum[0] += n));
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " spliterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.spliterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " contains") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Object sneakyAdder = sneakyAdder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.contains(sneakyAdder)) throw new AssertionError();
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " containsAll") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Collection<Object> sneakyAdderCollection =
|
||||
Collections.singleton(sneakyAdder(sum));
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.containsAll(sneakyAdderCollection))
|
||||
throw new AssertionError();
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " forEach") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.forEach(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " toArray()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Object o : x.toArray())
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " toArray(a)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = new Integer[x.size()];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.toArray(a);
|
||||
for (Object o : a)
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " toArray(empty)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] empty = new Integer[0];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Integer o : x.toArray(empty))
|
||||
sum[0] += o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " stream().forEach") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.stream().forEach(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " stream().mapToInt") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
check.sum(x.stream().mapToInt(e -> e).sum());}}},
|
||||
new Job(klazz + " stream().collect") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
check.sum(x.stream()
|
||||
.collect(summingInt(e -> e)));}}},
|
||||
new Job(klazz + " stream()::iterator") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Integer o : (Iterable<Integer>) x.stream()::iterator)
|
||||
sum[0] += o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " parallelStream().forEach") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
LongAdder sum = new LongAdder();
|
||||
x.parallelStream().forEach(n -> sum.add(n));
|
||||
check.sum((int) sum.sum());}}},
|
||||
new Job(klazz + " parallelStream().mapToInt") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
check.sum(x.parallelStream().mapToInt(e -> e).sum());}}},
|
||||
new Job(klazz + " parallelStream().collect") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
check.sum(x.parallelStream()
|
||||
.collect(summingInt(e -> e)));}}},
|
||||
new Job(klazz + " parallelStream()::iterator") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Integer o : (Iterable<Integer>) x.parallelStream()::iterator)
|
||||
sum[0] += o;
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> mutableCollectionJobs(Collection<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.removeIf(n -> { sum[0] += n; return false; }))
|
||||
throw new AssertionError();
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " remove(Object)") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Object sneakyAdder = sneakyAdder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.remove(sneakyAdder)) throw new AssertionError();
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> dequeJobs(Deque<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " descendingIterator() loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
Iterator<Integer> it = x.descendingIterator();
|
||||
while (it.hasNext())
|
||||
sum += it.next();
|
||||
check.sum(sum);}}},
|
||||
new Job(klazz + " descendingIterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.descendingIterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> listJobs(List<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " listIterator forward loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
ListIterator<Integer> it = x.listIterator();
|
||||
while (it.hasNext())
|
||||
sum += it.next();
|
||||
check.sum(sum);}}},
|
||||
new Job(klazz + " listIterator backward loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
ListIterator<Integer> it = x.listIterator(x.size());
|
||||
while (it.hasPrevious())
|
||||
sum += it.previous();
|
||||
check.sum(sum);}}},
|
||||
new Job(klazz + " indexOf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Object sneakyAdder = sneakyAdder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.indexOf(sneakyAdder) != -1)
|
||||
throw new AssertionError();
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " lastIndexOf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Object sneakyAdder = sneakyAdder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
if (x.lastIndexOf(sneakyAdder) != -1)
|
||||
throw new AssertionError();
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " equals") {
|
||||
public void work() throws Throwable {
|
||||
ArrayList<Integer> copy = new ArrayList<>(x);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if (!x.equals(copy))
|
||||
throw new AssertionError();}}},
|
||||
new Job(klazz + " hashCode") {
|
||||
public void work() throws Throwable {
|
||||
int hashCode = Arrays.hashCode(x.toArray());
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if (x.hashCode() != hashCode)
|
||||
throw new AssertionError();}}});
|
||||
}
|
||||
|
||||
Stream<Job> mutableListJobs(List<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " replaceAll") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
UnaryOperator<Integer> sneakyAdder =
|
||||
x -> { sum[0] += x; return x; };
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.replaceAll(sneakyAdder);
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
}
|
||||
1967
test/jdk/java/util/Collection/MOAT.java
Normal file
1967
test/jdk/java/util/Collection/MOAT.java
Normal file
File diff suppressed because it is too large
Load diff
206
test/jdk/java/util/Collection/RandomizedIteration.java
Normal file
206
test/jdk/java/util/Collection/RandomizedIteration.java
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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 8201518
|
||||
* @key randomness
|
||||
* @summary Ensure that randomized iteration order of unmodifiable sets
|
||||
* and maps is actually randomized. Must be run othervm so that
|
||||
* the per-VM-instance salt value differs.
|
||||
* @run main/othervm RandomizedIteration 0
|
||||
* @run main/othervm RandomizedIteration 1
|
||||
* @run main/othervm RandomizedIteration 2
|
||||
* @run main/othervm RandomizedIteration 3
|
||||
* @run main/othervm RandomizedIteration 4
|
||||
* @run main/othervm RandomizedIteration verify 5
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.toUnmodifiableMap;
|
||||
|
||||
/**
|
||||
* Test of randomized iteration of unmodifiable sets and maps.
|
||||
*
|
||||
* Usage: RandomizedIteration n
|
||||
* - writes files suffixed with 'n' containing set elements and map keys
|
||||
* in iteration order
|
||||
* RandomizedIteration "verify" count
|
||||
* - reads files 0..count-1 and checks to ensure that their orders differ
|
||||
*
|
||||
* The idea is to generate several test files by invoking this test with an arg
|
||||
* of 0 through count-1. Then invoke the test once more with two args, the first being
|
||||
* the word "verify" and the second arg being the count. This will read all the generated
|
||||
* files and perform verification.
|
||||
*
|
||||
* The test is considered to pass if any of the runs result in different iteration
|
||||
* orders. The randomization is not actually very random, so over many runs there is
|
||||
* the possibility of a couple of the test files having the same order. That's ok, as
|
||||
* long as the iteration order is usually different. The test fails if *all* of the
|
||||
* iteration orders are the same.
|
||||
*/
|
||||
public class RandomizedIteration {
|
||||
/**
|
||||
* Generates a set and a map from the word array, and then writes
|
||||
* text files "set.#" and "map.#" containing the set elements and
|
||||
* map keys in iteration order.
|
||||
*
|
||||
* @param suffix number used for the file suffix
|
||||
*/
|
||||
static void writeFiles(int suffix) throws IOException {
|
||||
try (PrintStream setOut = new PrintStream("set." + suffix)) {
|
||||
Set.of(WORDS)
|
||||
.forEach(setOut::println);
|
||||
}
|
||||
|
||||
try (PrintStream mapOut = new PrintStream("map." + suffix)) {
|
||||
var map = Map.ofEntries(Arrays.stream(WORDS)
|
||||
.map(word -> Map.entry(word, ""))
|
||||
.toArray(Map.Entry<?, ?>[]::new));
|
||||
map.keySet()
|
||||
.forEach(mapOut::println);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads lines from each file derived from the prefix and index from 0..count-1
|
||||
* into a list, computes its hashcode, and returns a set of those hashcodes.
|
||||
* The hashcode of the list is order sensitive, so the same lines in a different
|
||||
* order should have different hashcodes.
|
||||
*
|
||||
* @param prefix the file prefix
|
||||
* @param count the number of files to read
|
||||
* @return a set of hashcodes of each file
|
||||
*/
|
||||
static Set<Integer> readFiles(String prefix, int count) throws IOException {
|
||||
Set<Integer> hashes = new HashSet<>();
|
||||
for (int suffix = 0; suffix < count; suffix++) {
|
||||
String name = prefix + suffix;
|
||||
int hash = Files.readAllLines(Paths.get(name)).hashCode();
|
||||
System.out.println(name + ": " + hash);
|
||||
hashes.add(hash);
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test main routine.
|
||||
*
|
||||
* @param args n | "verify" count
|
||||
* @throws IOException if an error occurred
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
if ("verify".equals(args[0])) {
|
||||
int count = Integer.parseInt(args[1]);
|
||||
System.out.println("Verifying " + count + " files.");
|
||||
Set<Integer> setHashes = readFiles("set.", count);
|
||||
Set<Integer> mapHashes = readFiles("map.", count);
|
||||
if (setHashes.size() > 1 && mapHashes.size() > 1) {
|
||||
System.out.println("Passed: differing iteration orders were detected.");
|
||||
} else {
|
||||
throw new AssertionError("FAILED: iteration order not randomized!");
|
||||
}
|
||||
} else {
|
||||
int suffix = Integer.parseInt(args[0]);
|
||||
System.out.println("Generating files: " + suffix);
|
||||
writeFiles(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of 63 words of 22 or more letters from BSD /usr/share/dict/words.
|
||||
*/
|
||||
static final String[] WORDS = {
|
||||
"anatomicophysiological",
|
||||
"anthropomorphologically",
|
||||
"aquopentamminecobaltic",
|
||||
"blepharoconjunctivitis",
|
||||
"blepharosphincterectomy",
|
||||
"cholecystenterorrhaphy",
|
||||
"cholecystoduodenostomy",
|
||||
"choledochoduodenostomy",
|
||||
"counterexcommunication",
|
||||
"dacryocystoblennorrhea",
|
||||
"dacryocystosyringotomy",
|
||||
"deanthropomorphization",
|
||||
"duodenocholecystostomy",
|
||||
"electroencephalography",
|
||||
"electrotelethermometer",
|
||||
"epididymodeferentectomy",
|
||||
"formaldehydesulphoxylate",
|
||||
"formaldehydesulphoxylic",
|
||||
"gastroenteroanastomosis",
|
||||
"hematospectrophotometer",
|
||||
"hexamethylenetetramine",
|
||||
"hexanitrodiphenylamine",
|
||||
"historicocabbalistical",
|
||||
"hydropneumopericardium",
|
||||
"hyperconscientiousness",
|
||||
"laparocolpohysterotomy",
|
||||
"lymphangioendothelioma",
|
||||
"macracanthrorhynchiasis",
|
||||
"microcryptocrystalline",
|
||||
"naphthylaminesulphonic",
|
||||
"nonrepresentationalism",
|
||||
"omnirepresentativeness",
|
||||
"pancreaticoduodenostomy",
|
||||
"pancreaticogastrostomy",
|
||||
"pathologicohistological",
|
||||
"pathologicopsychological",
|
||||
"pericardiomediastinitis",
|
||||
"phenolsulphonephthalein",
|
||||
"philosophicohistorical",
|
||||
"philosophicotheological",
|
||||
"photochronographically",
|
||||
"photospectroheliograph",
|
||||
"pneumohydropericardium",
|
||||
"pneumoventriculography",
|
||||
"polioencephalomyelitis",
|
||||
"Prorhipidoglossomorpha",
|
||||
"Pseudolamellibranchiata",
|
||||
"pseudolamellibranchiate",
|
||||
"pseudomonocotyledonous",
|
||||
"pyopneumocholecystitis",
|
||||
"scientificogeographical",
|
||||
"scientificophilosophical",
|
||||
"scleroticochorioiditis",
|
||||
"stereophotomicrography",
|
||||
"tetraiodophenolphthalein",
|
||||
"theologicoastronomical",
|
||||
"theologicometaphysical",
|
||||
"thymolsulphonephthalein",
|
||||
"thyroparathyroidectomize",
|
||||
"thyroparathyroidectomy",
|
||||
"transubstantiationalist",
|
||||
"ureterocystanastomosis",
|
||||
"zoologicoarchaeologist"
|
||||
};
|
||||
}
|
||||
573
test/jdk/java/util/Collection/RemoveMicroBenchmark.java
Normal file
573
test/jdk/java/util/Collection/RemoveMicroBenchmark.java
Normal file
|
|
@ -0,0 +1,573 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* @summary micro-benchmark correctness mode
|
||||
* @run main RemoveMicroBenchmark iterations=1 size=8 warmup=0
|
||||
*/
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Queue;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
|
||||
*
|
||||
* To run this in micro-benchmark mode, simply run as a normal java program.
|
||||
* Be patient; this program runs for a very long time.
|
||||
* For faster runs, restrict execution using command line args.
|
||||
*
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
public class RemoveMicroBenchmark {
|
||||
abstract static class Job {
|
||||
private final String name;
|
||||
public Job(String name) { this.name = name; }
|
||||
public String name() { return name; }
|
||||
public abstract void work() throws Throwable;
|
||||
public void run() {
|
||||
try { work(); }
|
||||
catch (Throwable ex) {
|
||||
// current job cannot always be deduced from stacktrace.
|
||||
throw new RuntimeException("Job failed: " + name(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int iterations;
|
||||
final int size; // number of elements in collections
|
||||
final double warmupSeconds;
|
||||
final long warmupNanos;
|
||||
final Pattern nameFilter; // select subset of Jobs to run
|
||||
final boolean reverse; // reverse order of Jobs
|
||||
final boolean shuffle; // randomize order of Jobs
|
||||
|
||||
final ArrayList<Integer> elements; // contains size random Integers
|
||||
|
||||
RemoveMicroBenchmark(String[] args) {
|
||||
iterations = intArg(args, "iterations", 10_000);
|
||||
size = intArg(args, "size", 1000);
|
||||
warmupSeconds = doubleArg(args, "warmup", 7.0);
|
||||
nameFilter = patternArg(args, "filter");
|
||||
reverse = booleanArg(args, "reverse");
|
||||
shuffle = booleanArg(args, "shuffle");
|
||||
|
||||
warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
|
||||
|
||||
elements = ThreadLocalRandom.current().ints(size)
|
||||
.mapToObj(x -> x)
|
||||
.collect(toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
// --------------- GC finalization infrastructure ---------------
|
||||
|
||||
/** No guarantees, but effective in practice. */
|
||||
static void forceFullGc() {
|
||||
long timeoutMillis = 1000L;
|
||||
CountDownLatch finalized = new CountDownLatch(1);
|
||||
ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
WeakReference<Object> ref = new WeakReference<>(
|
||||
new Object() { protected void finalize() { finalized.countDown(); }},
|
||||
queue);
|
||||
try {
|
||||
for (int tries = 3; tries--> 0; ) {
|
||||
System.gc();
|
||||
if (finalized.await(timeoutMillis, MILLISECONDS)
|
||||
&& queue.remove(timeoutMillis) != null
|
||||
&& ref.get() == null) {
|
||||
System.runFinalization(); // try to pick up stragglers
|
||||
return;
|
||||
}
|
||||
timeoutMillis *= 4;
|
||||
}
|
||||
} catch (InterruptedException unexpected) {
|
||||
throw new AssertionError("unexpected InterruptedException");
|
||||
}
|
||||
throw new AssertionError("failed to do a \"full\" gc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs each job for long enough that all the runtime compilers
|
||||
* have had plenty of time to warm up, i.e. get around to
|
||||
* compiling everything worth compiling.
|
||||
* Returns array of average times per job per run.
|
||||
*/
|
||||
long[] time0(List<Job> jobs) {
|
||||
final int size = jobs.size();
|
||||
long[] nanoss = new long[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (warmupNanos > 0) forceFullGc();
|
||||
Job job = jobs.get(i);
|
||||
long totalTime;
|
||||
int runs = 0;
|
||||
long startTime = System.nanoTime();
|
||||
do { job.run(); runs++; }
|
||||
while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
|
||||
nanoss[i] = totalTime/runs;
|
||||
}
|
||||
return nanoss;
|
||||
}
|
||||
|
||||
void time(List<Job> jobs) throws Throwable {
|
||||
if (warmupNanos > 0) time0(jobs); // Warm up run
|
||||
final int size = jobs.size();
|
||||
final long[] nanoss = time0(jobs); // Real timing run
|
||||
final long[] milliss = new long[size];
|
||||
final double[] ratios = new double[size];
|
||||
|
||||
final String nameHeader = "Method";
|
||||
final String millisHeader = "Millis";
|
||||
final String ratioHeader = "Ratio";
|
||||
|
||||
int nameWidth = nameHeader.length();
|
||||
int millisWidth = millisHeader.length();
|
||||
int ratioWidth = ratioHeader.length();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
nameWidth = Math.max(nameWidth, jobs.get(i).name().length());
|
||||
|
||||
milliss[i] = nanoss[i]/(1000L * 1000L);
|
||||
millisWidth = Math.max(millisWidth,
|
||||
String.format("%d", milliss[i]).length());
|
||||
|
||||
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
|
||||
ratioWidth = Math.max(ratioWidth,
|
||||
String.format("%.3f", ratios[i]).length());
|
||||
}
|
||||
|
||||
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
|
||||
|
||||
// Print out absolute and relative times, calibrated against first job
|
||||
for (int i = 0; i < size; i++)
|
||||
System.out.printf(format, jobs.get(i).name(), milliss[i], ratios[i]);
|
||||
}
|
||||
|
||||
private static String keywordValue(String[] args, String keyword) {
|
||||
for (String arg : args)
|
||||
if (arg.startsWith(keyword))
|
||||
return arg.substring(keyword.length() + 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int intArg(String[] args, String keyword, int defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Integer.parseInt(val);
|
||||
}
|
||||
|
||||
private static double doubleArg(String[] args, String keyword, double defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Double.parseDouble(val);
|
||||
}
|
||||
|
||||
private static Pattern patternArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? null : Pattern.compile(val);
|
||||
}
|
||||
|
||||
private static boolean booleanArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
if (val == null || val.equals("false")) return false;
|
||||
if (val.equals("true")) return true;
|
||||
throw new IllegalArgumentException(val);
|
||||
}
|
||||
|
||||
private static void deoptimize(int sum) {
|
||||
if (sum == 42)
|
||||
System.out.println("the answer");
|
||||
}
|
||||
|
||||
private static <T> Iterable<T> backwards(final List<T> list) {
|
||||
return new Iterable<T>() {
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
final ListIterator<T> it = list.listIterator(list.size());
|
||||
public boolean hasNext() { return it.hasPrevious(); }
|
||||
public T next() { return it.previous(); }
|
||||
public void remove() { it.remove(); }};}};
|
||||
}
|
||||
|
||||
// Checks for correctness *and* prevents loop optimizations
|
||||
static class Check {
|
||||
private int sum;
|
||||
public void sum(int sum) {
|
||||
if (this.sum == 0)
|
||||
this.sum = sum;
|
||||
if (this.sum != sum)
|
||||
throw new AssertionError("Sum mismatch");
|
||||
}
|
||||
}
|
||||
volatile Check check = new Check();
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new RemoveMicroBenchmark(args).run();
|
||||
}
|
||||
|
||||
HashMap<Class<?>, String> goodClassName = new HashMap<>();
|
||||
|
||||
String goodClassName(Class<?> klazz) {
|
||||
return goodClassName.computeIfAbsent(
|
||||
klazz,
|
||||
k -> {
|
||||
String simple = k.getSimpleName();
|
||||
return (simple.equals("SubList")) // too simple!
|
||||
? k.getName().replaceFirst(".*\\.", "")
|
||||
: simple;
|
||||
});
|
||||
}
|
||||
|
||||
String goodClassName(Object x) {
|
||||
return goodClassName(x.getClass());
|
||||
}
|
||||
|
||||
static List<Integer> makeSubList(List<Integer> list) {
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
int size = rnd.nextInt(4);
|
||||
for (int i = size; i--> 0; )
|
||||
list.add(rnd.nextInt());
|
||||
int index = rnd.nextInt(size + 1);
|
||||
return list.subList(index, index);
|
||||
}
|
||||
|
||||
private static <T> List<T> asSubList(List<T> list) {
|
||||
return list.subList(0, list.size());
|
||||
}
|
||||
|
||||
@SafeVarargs @SuppressWarnings("varargs")
|
||||
private static <T> Stream<T> concatStreams(Stream<T> ... streams) {
|
||||
return Stream.of(streams).flatMap(s -> s);
|
||||
}
|
||||
|
||||
Class<?> topLevelClass(Object x) {
|
||||
for (Class<?> k = x.getClass();; ) {
|
||||
Class<?> enclosing = k.getEnclosingClass();
|
||||
if (enclosing == null)
|
||||
return k;
|
||||
k = enclosing;
|
||||
}
|
||||
}
|
||||
|
||||
void run() throws Throwable {
|
||||
ArrayList<Job> jobs = Stream.<Collection<Integer>>of(
|
||||
new ArrayList<>(),
|
||||
makeSubList(new ArrayList<>()),
|
||||
new LinkedList<>(),
|
||||
makeSubList(new LinkedList<>()),
|
||||
new Vector<>(),
|
||||
makeSubList(new Vector<>()),
|
||||
new CopyOnWriteArrayList<>(),
|
||||
makeSubList(new CopyOnWriteArrayList<>()),
|
||||
new ArrayDeque<>(),
|
||||
new PriorityQueue<>(),
|
||||
new ArrayBlockingQueue<>(elements.size()),
|
||||
new ConcurrentLinkedQueue<>(),
|
||||
new ConcurrentLinkedDeque<>(),
|
||||
new LinkedBlockingQueue<>(),
|
||||
new LinkedBlockingDeque<>(),
|
||||
new LinkedTransferQueue<>(),
|
||||
new PriorityBlockingQueue<>())
|
||||
.flatMap(x -> jobs(x))
|
||||
.filter(job ->
|
||||
nameFilter == null || nameFilter.matcher(job.name()).find())
|
||||
.collect(toCollection(ArrayList::new));
|
||||
|
||||
if (reverse) Collections.reverse(jobs);
|
||||
if (shuffle) Collections.shuffle(jobs);
|
||||
|
||||
time(jobs);
|
||||
}
|
||||
|
||||
Stream<Job> jobs(Collection<Integer> x) {
|
||||
return concatStreams(
|
||||
collectionJobs(x),
|
||||
|
||||
(CopyOnWriteArrayList.class.isAssignableFrom(topLevelClass(x)))
|
||||
? Stream.empty()
|
||||
: iteratorRemoveJobs(x),
|
||||
|
||||
(x instanceof Queue)
|
||||
? queueJobs((Queue<Integer>)x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof Deque)
|
||||
? dequeJobs((Deque<Integer>)x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof BlockingQueue)
|
||||
? blockingQueueJobs((BlockingQueue<Integer>)x)
|
||||
: Stream.empty(),
|
||||
|
||||
(x instanceof BlockingDeque)
|
||||
? blockingDequeJobs((BlockingDeque<Integer>)x)
|
||||
: Stream.empty());
|
||||
}
|
||||
|
||||
Collection<Integer> universeRecorder(int[] sum) {
|
||||
return new ArrayList<>() {
|
||||
public boolean contains(Object x) {
|
||||
sum[0] += (Integer) x;
|
||||
return true;
|
||||
}};
|
||||
}
|
||||
|
||||
Collection<Integer> emptyRecorder(int[] sum) {
|
||||
return new ArrayList<>() {
|
||||
public boolean contains(Object x) {
|
||||
sum[0] += (Integer) x;
|
||||
return false;
|
||||
}};
|
||||
}
|
||||
|
||||
Stream<Job> collectionJobs(Collection<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
x.removeIf(n -> { sum[0] += n; return true; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " removeIf rnd-two-pass") {
|
||||
public void work() throws Throwable {
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
x.removeIf(n -> {
|
||||
boolean b = rnd.nextBoolean();
|
||||
if (b) sum[0] += n;
|
||||
return b; });
|
||||
x.removeIf(n -> { sum[0] += n; return true; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " removeAll") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Collection<Integer> universe = universeRecorder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
x.removeAll(universe);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " retainAll") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
Collection<Integer> empty = emptyRecorder(sum);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
x.retainAll(empty);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " clear") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
x.forEach(e -> sum[0] += e);
|
||||
x.clear();
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> iteratorRemoveJobs(Collection<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " Iterator.remove") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
Iterator<Integer> it = x.iterator();
|
||||
while (it.hasNext()) {
|
||||
sum[0] += it.next();
|
||||
it.remove();
|
||||
}
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " Iterator.remove-rnd-two-pass") {
|
||||
public void work() throws Throwable {
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Iterator<Integer> it = x.iterator();
|
||||
it.hasNext(); ) {
|
||||
Integer e = it.next();
|
||||
if (rnd.nextBoolean()) {
|
||||
sum[0] += e;
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<Integer> it = x.iterator();
|
||||
it.hasNext(); ) {
|
||||
sum[0] += it.next();
|
||||
it.remove();
|
||||
}
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> queueJobs(Queue<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " poll()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.poll()) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> dequeJobs(Deque<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " descendingIterator().remove") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
Iterator<Integer> it = x.descendingIterator();
|
||||
while (it.hasNext()) {
|
||||
sum[0] += it.next();
|
||||
it.remove();
|
||||
}
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " pollFirst()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.pollFirst()) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " pollLast()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.pollLast()) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> blockingQueueJobs(BlockingQueue<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " timed poll()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.poll(0L, TimeUnit.DAYS)) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " drainTo(sink)") {
|
||||
public void work() throws Throwable {
|
||||
ArrayList<Integer> sink = new ArrayList<>();
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
sink.clear();
|
||||
x.addAll(elements);
|
||||
x.drainTo(sink);
|
||||
sink.forEach(e -> sum[0] += e);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " drainTo(sink, n)") {
|
||||
public void work() throws Throwable {
|
||||
ArrayList<Integer> sink = new ArrayList<>();
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
sink.clear();
|
||||
x.addAll(elements);
|
||||
x.drainTo(sink, elements.size());
|
||||
sink.forEach(e -> sum[0] += e);
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
|
||||
Stream<Job> blockingDequeJobs(BlockingDeque<Integer> x) {
|
||||
final String klazz = goodClassName(x);
|
||||
return Stream.of(
|
||||
new Job(klazz + " timed pollFirst()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.pollFirst(0L, TimeUnit.DAYS)) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job(klazz + " timed pollLast()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
x.addAll(elements);
|
||||
for (Integer e; (e = x.pollLast(0L, TimeUnit.DAYS)) != null; )
|
||||
sum[0] += e;
|
||||
check.sum(sum[0]);}}});
|
||||
}
|
||||
}
|
||||
345
test/jdk/java/util/Collection/SetFactories.java
Normal file
345
test/jdk/java/util/Collection/SetFactories.java
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotEquals;
|
||||
import static org.testng.Assert.assertNotSame;
|
||||
import static org.testng.Assert.assertSame;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048330
|
||||
* @summary Test convenience static factory methods on Set.
|
||||
* @run testng SetFactories
|
||||
*/
|
||||
|
||||
|
||||
public class SetFactories {
|
||||
|
||||
static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
|
||||
static final String[] stringArray;
|
||||
static {
|
||||
String[] sa = new String[NUM_STRINGS];
|
||||
for (int i = 0; i < NUM_STRINGS; i++) {
|
||||
sa[i] = String.valueOf((char)('a' + i));
|
||||
}
|
||||
stringArray = sa;
|
||||
}
|
||||
|
||||
static Object[] a(Set<String> act, Set<String> exp) {
|
||||
return new Object[] { act, exp };
|
||||
}
|
||||
|
||||
static Set<String> hashSetOf(String... args) {
|
||||
return new HashSet<>(Arrays.asList(args));
|
||||
}
|
||||
|
||||
@DataProvider(name="empty")
|
||||
public Iterator<Object[]> empty() {
|
||||
return Collections.singletonList(
|
||||
// actual, expected
|
||||
a(Set.of(), Collections.emptySet())
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonempty")
|
||||
public Iterator<Object[]> nonempty() {
|
||||
return Arrays.asList(
|
||||
// actual, expected
|
||||
a( Set.of("a"),
|
||||
hashSetOf("a")),
|
||||
a( Set.of("a", "b"),
|
||||
hashSetOf("a", "b")),
|
||||
a( Set.of("a", "b", "c"),
|
||||
hashSetOf("a", "b", "c")),
|
||||
a( Set.of("a", "b", "c", "d"),
|
||||
hashSetOf("a", "b", "c", "d")),
|
||||
a( Set.of("a", "b", "c", "d", "e"),
|
||||
hashSetOf("a", "b", "c", "d", "e")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
|
||||
Set.of("j", "i", "h", "g", "f", "e", "d", "c", "b", "a")),
|
||||
a( Set.of(stringArray),
|
||||
hashSetOf(stringArray))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="all")
|
||||
public Iterator<Object[]> all() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAdd(Set<String> act, Set<String> exp) {
|
||||
act.add("x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotRemove(Set<String> act, Set<String> exp) {
|
||||
act.remove(act.iterator().next());
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void contentsMatch(Set<String> act, Set<String> exp) {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed2() {
|
||||
Set<String> set = Set.of("a", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed3() {
|
||||
Set<String> set = Set.of("a", "b", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed4() {
|
||||
Set<String> set = Set.of("a", "b", "c", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed5() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed6() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed7() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed8() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed9() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed10() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowedN() {
|
||||
String[] array = stringArray.clone();
|
||||
array[0] = array[1];
|
||||
Set<String> set = Set.of(array);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void hashCodeEqual(Set<String> act, Set<String> exp) {
|
||||
assertEquals(act.hashCode(), exp.hashCode());
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void containsAll(Set<String> act, Set<String> exp) {
|
||||
assertTrue(act.containsAll(exp));
|
||||
assertTrue(exp.containsAll(act));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed1() {
|
||||
Set.of((String)null); // force one-arg overload
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2a() {
|
||||
Set.of("a", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2b() {
|
||||
Set.of(null, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed3() {
|
||||
Set.of("a", "b", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed4() {
|
||||
Set.of("a", "b", "c", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed5() {
|
||||
Set.of("a", "b", "c", "d", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed6() {
|
||||
Set.of("a", "b", "c", "d", "e", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed7() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed8() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed9() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", "h", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed10() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowedN() {
|
||||
String[] array = stringArray.clone();
|
||||
array[0] = null;
|
||||
Set.of(array);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullArrayDisallowed() {
|
||||
Set.of((Object[])null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=NullPointerException.class)
|
||||
public void containsNullShouldThrowNPE(Set<String> act, Set<String> exp) {
|
||||
act.contains(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void serialEquality(Set<String> act, Set<String> exp) {
|
||||
// assume that act.equals(exp) tested elsewhere
|
||||
Set<String> copy = serialClone(act);
|
||||
assertEquals(act, copy);
|
||||
assertEquals(copy, exp);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
|
||||
oos.writeObject(obj);
|
||||
}
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
return (T) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Set<Integer> genSet() {
|
||||
return new HashSet<>(Arrays.asList(1, 2, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfResultsEqual() {
|
||||
Set<Integer> orig = genSet();
|
||||
Set<Integer> copy = Set.copyOf(orig);
|
||||
|
||||
assertEquals(orig, copy);
|
||||
assertEquals(copy, orig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfModifiedUnequal() {
|
||||
Set<Integer> orig = genSet();
|
||||
Set<Integer> copy = Set.copyOf(orig);
|
||||
orig.add(4);
|
||||
|
||||
assertNotEquals(orig, copy);
|
||||
assertNotEquals(copy, orig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfIdentity() {
|
||||
Set<Integer> orig = genSet();
|
||||
Set<Integer> copy1 = Set.copyOf(orig);
|
||||
Set<Integer> copy2 = Set.copyOf(copy1);
|
||||
|
||||
assertNotSame(orig, copy1);
|
||||
assertSame(copy1, copy2);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void copyOfRejectsNullCollection() {
|
||||
Set<Integer> set = Set.copyOf(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void copyOfRejectsNullElements() {
|
||||
Set<Integer> set = Set.copyOf(Arrays.asList(1, null, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfAcceptsDuplicates() {
|
||||
Set<Integer> set = Set.copyOf(Arrays.asList(1, 1, 2, 3, 3, 3));
|
||||
assertEquals(set, Set.of(1, 2, 3));
|
||||
}
|
||||
}
|
||||
216
test/jdk/java/util/Collection/testlibrary/CollectionAsserts.java
Normal file
216
test/jdk/java/util/Collection/testlibrary/CollectionAsserts.java
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 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.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
* @library
|
||||
* CollectionAssert -- assertion methods for lambda test cases
|
||||
*/
|
||||
public class CollectionAsserts {
|
||||
|
||||
private CollectionAsserts() {
|
||||
// no instances
|
||||
}
|
||||
|
||||
public static void assertCountSum(Iterable<? super Integer> it, int count, int sum) {
|
||||
assertCountSum(it.iterator(), count, sum);
|
||||
}
|
||||
|
||||
public static void assertCountSum(Iterator<? super Integer> it, int count, int sum) {
|
||||
int c = 0;
|
||||
int s = 0;
|
||||
while (it.hasNext()) {
|
||||
int i = (Integer) it.next();
|
||||
c++;
|
||||
s += i;
|
||||
}
|
||||
|
||||
assertEquals(c, count);
|
||||
assertEquals(s, sum);
|
||||
}
|
||||
|
||||
public static void assertConcat(Iterator<Character> it, String result) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (it.hasNext()) {
|
||||
sb.append(it.next());
|
||||
}
|
||||
|
||||
assertEquals(result, sb.toString());
|
||||
}
|
||||
|
||||
public static<T extends Comparable<? super T>> void assertSorted(Iterator<T> i) {
|
||||
if (!i.hasNext())
|
||||
return;
|
||||
T last = i.next();
|
||||
while (i.hasNext()) {
|
||||
T t = i.next();
|
||||
assertTrue(last.compareTo(t) <= 0);
|
||||
assertTrue(t.compareTo(last) >= 0);
|
||||
last = t;
|
||||
}
|
||||
}
|
||||
|
||||
public static<T> void assertSorted(Iterator<T> i, Comparator<? super T> comp) {
|
||||
if (!i.hasNext())
|
||||
return;
|
||||
T last = i.next();
|
||||
while (i.hasNext()) {
|
||||
T t = i.next();
|
||||
assertTrue(comp.compare(last, t) <= 0);
|
||||
assertTrue(comp.compare(t, last) >= 0);
|
||||
last = t;
|
||||
}
|
||||
}
|
||||
|
||||
public static<T extends Comparable<? super T>> void assertSorted(Iterable<T> iter) {
|
||||
assertSorted(iter.iterator());
|
||||
}
|
||||
|
||||
public static<T> void assertSorted(Iterable<T> iter, Comparator<? super T> comp) {
|
||||
assertSorted(iter.iterator(), comp);
|
||||
}
|
||||
|
||||
public static <T> void assertUnique(Iterable<T> iter) {
|
||||
assertUnique(iter.iterator());
|
||||
}
|
||||
|
||||
public static<T> void assertUnique(Iterator<T> iter) {
|
||||
if (!iter.hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<T> uniq = new HashSet<>();
|
||||
while (iter.hasNext()) {
|
||||
T each = iter.next();
|
||||
assertTrue(!uniq.contains(each));
|
||||
uniq.add(each);
|
||||
}
|
||||
}
|
||||
|
||||
public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
|
||||
assertContents(actual, expected, null);
|
||||
}
|
||||
|
||||
public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected, String msg) {
|
||||
assertContents(actual.iterator(), expected.iterator(), msg);
|
||||
}
|
||||
|
||||
public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
|
||||
assertContents(actual, expected, null);
|
||||
}
|
||||
|
||||
public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected, String msg) {
|
||||
List<T> history = new ArrayList<>();
|
||||
|
||||
while (expected.hasNext()) {
|
||||
if (!actual.hasNext()) {
|
||||
List<T> expectedData = new ArrayList<>(history);
|
||||
while (expected.hasNext())
|
||||
expectedData.add(expected.next());
|
||||
fail(String.format("%s Premature end of data; expected=%s, found=%s",
|
||||
(msg == null ? "" : msg), expectedData, history));
|
||||
}
|
||||
T a = actual.next();
|
||||
T e = expected.next();
|
||||
history.add(a);
|
||||
|
||||
if (!Objects.equals(a, e))
|
||||
fail(String.format("%s Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s",
|
||||
(msg == null ? "" : msg), history, e, a));
|
||||
}
|
||||
if (actual.hasNext()) {
|
||||
List<T> rest = new ArrayList<>();
|
||||
while (actual.hasNext())
|
||||
rest.add(actual.next());
|
||||
fail(String.format("%s Unexpected data %s after %s",
|
||||
(msg == null ? "" : msg), rest, history));
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("varargs")
|
||||
public static<T> void assertContents(Iterator<T> actual, T... expected) {
|
||||
assertContents(actual, Arrays.asList(expected).iterator());
|
||||
}
|
||||
|
||||
public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
|
||||
assertContentsUnordered(actual, expected, null);
|
||||
}
|
||||
|
||||
public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected, String msg) {
|
||||
List<T> allExpected = new ArrayList<>();
|
||||
for (T t : expected) {
|
||||
allExpected.add(t);
|
||||
}
|
||||
|
||||
for (T t : actual) {
|
||||
assertTrue(allExpected.remove(t), msg + " element '" + String.valueOf(t) + "' not found");
|
||||
}
|
||||
|
||||
assertTrue(allExpected.isEmpty(), msg + "expected contained additional elements");
|
||||
}
|
||||
|
||||
static <T> void assertSplitContents(Iterable<Iterable<T>> splits, Iterable<T> list) {
|
||||
Iterator<Iterable<T>> mI = splits.iterator();
|
||||
Iterator<T> pI = null;
|
||||
Iterator<T> lI = list.iterator();
|
||||
|
||||
while (lI.hasNext()) {
|
||||
if (pI == null)
|
||||
pI = mI.next().iterator();
|
||||
while (!pI.hasNext()) {
|
||||
if (!mI.hasNext()) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
pI = mI.next().iterator();
|
||||
}
|
||||
}
|
||||
assertTrue(pI.hasNext());
|
||||
T pT = pI.next();
|
||||
T lT = lI.next();
|
||||
assertEquals(pT, lT);
|
||||
}
|
||||
|
||||
if (pI != null) {
|
||||
assertTrue(!pI.hasNext());
|
||||
}
|
||||
|
||||
while (mI.hasNext()) {
|
||||
pI = mI.next().iterator();
|
||||
assertTrue(!pI.hasNext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 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.lang.Exception;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Iterable;
|
||||
import java.lang.Override;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.testng.TestException;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @library
|
||||
* @summary A Supplier of test cases for Collection tests
|
||||
*/
|
||||
public final class CollectionSupplier<C extends Collection<Integer>> implements Supplier<Iterable<CollectionSupplier.TestCase<C>>> {
|
||||
|
||||
private final List<Function<Collection<Integer>, C>> suppliers;
|
||||
private final int size;
|
||||
|
||||
/**
|
||||
* A Collection test case.
|
||||
*/
|
||||
public static final class TestCase<C extends Collection<Integer>> {
|
||||
/**
|
||||
* The name of the test case.
|
||||
*/
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* The supplier of a collection
|
||||
*/
|
||||
public Function<Collection<Integer>, C> supplier;
|
||||
|
||||
/**
|
||||
* Unmodifiable reference collection, useful for comparisons.
|
||||
*/
|
||||
public final List<Integer> expected;
|
||||
|
||||
/**
|
||||
* A modifiable test collection.
|
||||
*/
|
||||
public final C collection;
|
||||
|
||||
/**
|
||||
* Create a Collection test case.
|
||||
*
|
||||
* @param name name of the test case
|
||||
* @param collection the modifiable test collection
|
||||
*/
|
||||
public TestCase(String name, Function<Collection<Integer>, C> supplier, C collection) {
|
||||
this.name = name;
|
||||
this.supplier = supplier;
|
||||
this.expected = Collections.unmodifiableList(
|
||||
Arrays.asList(collection.toArray(new Integer[0])));
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + " " + collection.getClass().toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle a list using a PRNG with known seed for repeatability
|
||||
*
|
||||
* @param list the list to be shuffled
|
||||
*/
|
||||
public static <E> void shuffle(final List<E> list) {
|
||||
// PRNG with known seed for repeatable tests
|
||||
final Random prng = new Random(13);
|
||||
final int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
// random index in interval [i, size)
|
||||
final int j = i + prng.nextInt(size - i);
|
||||
// swap elements at indices i & j
|
||||
final E e = list.get(i);
|
||||
list.set(i, list.get(j));
|
||||
list.set(j, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code CollectionSupplier} that creates instances of specified
|
||||
* collection suppliers of the specified size.
|
||||
*
|
||||
* @param suppliers the suppliers names that supply {@code Collection}
|
||||
* instances
|
||||
* @param size the desired size of each collection
|
||||
*/
|
||||
public CollectionSupplier(List<Function<Collection<Integer>, C>> suppliers, int size) {
|
||||
this.suppliers = suppliers;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<TestCase<C>> get() {
|
||||
final Collection<TestCase<C>> cases = new LinkedList<>();
|
||||
for (final Function<Collection<Integer>, C> supplier : suppliers)
|
||||
try {
|
||||
cases.add(new TestCase<>("empty", supplier, supplier.apply(Collections.emptyList())));
|
||||
|
||||
cases.add(new TestCase<>("single", supplier, supplier.apply(Arrays.asList(42))));
|
||||
|
||||
final Collection<Integer> regular = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
regular.add(i);
|
||||
}
|
||||
cases.add(new TestCase<>("regular", supplier, supplier.apply(regular)));
|
||||
|
||||
final Collection<Integer> reverse = new ArrayList<>();
|
||||
for (int i = size; i >= 0; i--) {
|
||||
reverse.add(i);
|
||||
}
|
||||
cases.add(new TestCase<>("reverse", supplier, supplier.apply(reverse)));
|
||||
|
||||
final Collection<Integer> odds = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
odds.add((i * 2) + 1);
|
||||
}
|
||||
cases.add(new TestCase<>("odds", supplier, supplier.apply(odds)));
|
||||
|
||||
final Collection<Integer> evens = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
evens.add(i * 2);
|
||||
}
|
||||
cases.add(new TestCase<>("evens", supplier, supplier.apply(evens)));
|
||||
|
||||
final Collection<Integer> fibonacci = new ArrayList<>();
|
||||
int prev2 = 0;
|
||||
int prev1 = 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int n = prev1 + prev2;
|
||||
if (n < 0) { // stop on overflow
|
||||
break;
|
||||
}
|
||||
fibonacci.add(n);
|
||||
prev2 = prev1;
|
||||
prev1 = n;
|
||||
}
|
||||
cases.add(new TestCase<>("fibonacci", supplier, supplier.apply(fibonacci)));
|
||||
|
||||
|
||||
boolean isStructurallyModifiable = false;
|
||||
try {
|
||||
C t = supplier.apply(Collections.emptyList());
|
||||
t.add(1);
|
||||
isStructurallyModifiable = true;
|
||||
} catch (UnsupportedOperationException e) { }
|
||||
|
||||
if (!isStructurallyModifiable)
|
||||
continue;
|
||||
|
||||
|
||||
// variants where the size of the backing storage != reported size
|
||||
// created by removing half of the elements
|
||||
final C emptyWithSlack = supplier.apply(Collections.emptyList());
|
||||
emptyWithSlack.add(42);
|
||||
assertTrue(emptyWithSlack.remove(42));
|
||||
cases.add(new TestCase<>("emptyWithSlack", supplier, emptyWithSlack));
|
||||
|
||||
final C singleWithSlack = supplier.apply(Collections.emptyList());
|
||||
singleWithSlack.add(42);
|
||||
singleWithSlack.add(43);
|
||||
assertTrue(singleWithSlack.remove(43));
|
||||
cases.add(new TestCase<>("singleWithSlack", supplier, singleWithSlack));
|
||||
|
||||
final C regularWithSlack = supplier.apply(Collections.emptyList());
|
||||
for (int i = 0; i < (2 * size); i++) {
|
||||
regularWithSlack.add(i);
|
||||
}
|
||||
assertTrue(regularWithSlack.removeIf(x -> x < size));
|
||||
cases.add(new TestCase<>("regularWithSlack", supplier, regularWithSlack));
|
||||
|
||||
final C reverseWithSlack = supplier.apply(Collections.emptyList());
|
||||
for (int i = 2 * size; i >= 0; i--) {
|
||||
reverseWithSlack.add(i);
|
||||
}
|
||||
assertTrue(reverseWithSlack.removeIf(x -> x < size));
|
||||
cases.add(new TestCase<>("reverseWithSlack", supplier, reverseWithSlack));
|
||||
|
||||
final C oddsWithSlack = supplier.apply(Collections.emptyList());
|
||||
for (int i = 0; i < 2 * size; i++) {
|
||||
oddsWithSlack.add((i * 2) + 1);
|
||||
}
|
||||
assertTrue(oddsWithSlack.removeIf(x -> x >= size));
|
||||
cases.add(new TestCase<>("oddsWithSlack", supplier, oddsWithSlack));
|
||||
|
||||
final C evensWithSlack = supplier.apply(Collections.emptyList());
|
||||
for (int i = 0; i < 2 * size; i++) {
|
||||
evensWithSlack.add(i * 2);
|
||||
}
|
||||
assertTrue(evensWithSlack.removeIf(x -> x >= size));
|
||||
cases.add(new TestCase<>("evensWithSlack", supplier, evensWithSlack));
|
||||
|
||||
final C fibonacciWithSlack = supplier.apply(Collections.emptyList());
|
||||
prev2 = 0;
|
||||
prev1 = 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int n = prev1 + prev2;
|
||||
if (n < 0) { // stop on overflow
|
||||
break;
|
||||
}
|
||||
fibonacciWithSlack.add(n);
|
||||
prev2 = prev1;
|
||||
prev1 = n;
|
||||
}
|
||||
assertTrue(fibonacciWithSlack.removeIf(x -> x < 20));
|
||||
cases.add(new TestCase<>("fibonacciWithSlack", supplier, fibonacciWithSlack));
|
||||
}
|
||||
catch (Exception failed) {
|
||||
throw new TestException(failed);
|
||||
}
|
||||
|
||||
return cases;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 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.AbstractCollection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @library
|
||||
*
|
||||
* A simple mutable collection implementation that provides only default
|
||||
* implementations of all methods. ie. none of the Collection interface default
|
||||
* methods have overridden implementations.
|
||||
*
|
||||
* @param <E> type of collection elements
|
||||
*/
|
||||
public class ExtendsAbstractCollection<E> extends AbstractCollection<E> {
|
||||
|
||||
protected final Collection<E> coll;
|
||||
|
||||
public ExtendsAbstractCollection() {
|
||||
this(ArrayList<E>::new);
|
||||
}
|
||||
|
||||
public ExtendsAbstractCollection(Collection<E> source) {
|
||||
this();
|
||||
coll.addAll(source);
|
||||
}
|
||||
|
||||
protected ExtendsAbstractCollection(Supplier<Collection<E>> backer) {
|
||||
this.coll = backer.get();
|
||||
}
|
||||
|
||||
public boolean add(E element) {
|
||||
return coll.add(element);
|
||||
}
|
||||
|
||||
public boolean remove(Object element) {
|
||||
return coll.remove(element);
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
Iterator<E> source = coll.iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return source.hasNext();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return source.next();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
source.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return coll.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 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.AbstractList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @library
|
||||
*
|
||||
* A simple mutable list implementation that provides only default
|
||||
* implementations of all methods. ie. none of the List interface default
|
||||
* methods have overridden implementations.
|
||||
*
|
||||
* @param <E> type of list elements
|
||||
*/
|
||||
public class ExtendsAbstractList<E> extends AbstractList<E> {
|
||||
|
||||
protected final List<E> list;
|
||||
|
||||
public ExtendsAbstractList() {
|
||||
this(ArrayList<E>::new);
|
||||
}
|
||||
|
||||
protected ExtendsAbstractList(Supplier<List<E>> supplier) {
|
||||
this.list = supplier.get();
|
||||
}
|
||||
|
||||
public ExtendsAbstractList(Collection<E> source) {
|
||||
this();
|
||||
addAll(source);
|
||||
}
|
||||
|
||||
public boolean add(E element) {
|
||||
return list.add(element);
|
||||
}
|
||||
|
||||
public E get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
public boolean remove(Object element) {
|
||||
return list.remove(element);
|
||||
}
|
||||
|
||||
public E set(int index, E element) {
|
||||
return list.set(index, element);
|
||||
}
|
||||
|
||||
public void add(int index, E element) {
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
public E remove(int index) {
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
Iterator<E> source = list.iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return source.hasNext();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return source.next();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
source.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 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.HashSet;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @library
|
||||
*
|
||||
* A simple mutable set implementation that provides only default
|
||||
* implementations of all methods. ie. none of the Set interface default methods
|
||||
* have overridden implementations.
|
||||
*
|
||||
* @param <E> type of set members
|
||||
*/
|
||||
public class ExtendsAbstractSet<E> extends AbstractSet<E> {
|
||||
|
||||
protected final Set<E> set;
|
||||
|
||||
public ExtendsAbstractSet() {
|
||||
this(HashSet<E>::new);
|
||||
}
|
||||
|
||||
public ExtendsAbstractSet(Collection<E> source) {
|
||||
this();
|
||||
addAll(source);
|
||||
}
|
||||
|
||||
protected ExtendsAbstractSet(Supplier<Set<E>> backer) {
|
||||
this.set = backer.get();
|
||||
}
|
||||
|
||||
public boolean add(E element) {
|
||||
return set.add(element);
|
||||
}
|
||||
|
||||
public boolean remove(Object element) {
|
||||
return set.remove(element);
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
Iterator<E> source = set.iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return source.hasNext();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return source.next();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
source.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue