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
545
test/jdk/java/util/List/ListDefaults.java
Normal file
545
test/jdk/java/util/List/ListDefaults.java
Normal file
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2024, 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.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Unit tests for extension methods on List
|
||||
* @bug 8023367 8037106 8325679
|
||||
* @library ../Collection/testlibrary
|
||||
* @build CollectionAsserts CollectionSupplier ExtendsAbstractList
|
||||
* @run testng ListDefaults
|
||||
*/
|
||||
public class ListDefaults {
|
||||
|
||||
// Suppliers of lists that can support structural modifications
|
||||
private static final List<Function<Collection, List>> LIST_STRUCT_MOD_SUPPLIERS = Arrays.asList(
|
||||
java.util.ArrayList::new,
|
||||
java.util.LinkedList::new,
|
||||
java.util.Vector::new,
|
||||
java.util.concurrent.CopyOnWriteArrayList::new,
|
||||
ExtendsAbstractList::new
|
||||
);
|
||||
|
||||
// Suppliers of lists that can support in place modifications
|
||||
private static final List<Function<Collection, List>> LIST_SUPPLIERS = Arrays.asList(
|
||||
java.util.ArrayList::new,
|
||||
java.util.LinkedList::new,
|
||||
java.util.Vector::new,
|
||||
java.util.concurrent.CopyOnWriteArrayList::new,
|
||||
ExtendsAbstractList::new,
|
||||
c -> Arrays.asList(c.toArray())
|
||||
);
|
||||
|
||||
// Suppliers of lists supporting CMEs
|
||||
private static final List<Function<Collection, List>> LIST_CME_SUPPLIERS = Arrays.asList(
|
||||
java.util.ArrayList::new,
|
||||
java.util.Vector::new
|
||||
);
|
||||
|
||||
private static final Predicate<Integer> pEven = x -> 0 == x % 2;
|
||||
private static final Predicate<Integer> pOdd = x -> 1 == x % 2;
|
||||
|
||||
private static final Comparator<Integer> BIT_COUNT_COMPARATOR =
|
||||
(x, y) -> Integer.bitCount(x) - Integer.bitCount(y);
|
||||
|
||||
private static final Comparator<AtomicInteger> ATOMIC_INTEGER_COMPARATOR =
|
||||
(x, y) -> x.intValue() - y.intValue();
|
||||
|
||||
private static final int SIZE = 100;
|
||||
private static final int SUBLIST_FROM = 20;
|
||||
private static final int SUBLIST_TO = SIZE - 5;
|
||||
private static final int SUBLIST_SIZE = SUBLIST_TO - SUBLIST_FROM;
|
||||
|
||||
// call the callback for each recursive subList
|
||||
private void trimmedSubList(final List<Integer> list, final Consumer<List<Integer>> callback) {
|
||||
int size = list.size();
|
||||
if (size > 1) {
|
||||
// trim 1 element from both ends
|
||||
final List<Integer> subList = list.subList(1, size - 1);
|
||||
callback.accept(subList);
|
||||
trimmedSubList(subList, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name="listProvider", parallel=true)
|
||||
public static Object[][] listCases() {
|
||||
final List<Object[]> cases = new LinkedList<>();
|
||||
cases.add(new Object[] { Collections.emptyList() });
|
||||
cases.add(new Object[] { new ArrayList<>() });
|
||||
cases.add(new Object[] { new LinkedList<>() });
|
||||
cases.add(new Object[] { new Vector<>() });
|
||||
cases.add(new Object[] { new Stack<>() });
|
||||
cases.add(new Object[] { new CopyOnWriteArrayList<>() });
|
||||
cases.add(new Object[] { Arrays.asList() });
|
||||
|
||||
List<Integer> l = Arrays.asList(42);
|
||||
cases.add(new Object[] { new ArrayList<>(l) });
|
||||
cases.add(new Object[] { new LinkedList<>(l) });
|
||||
cases.add(new Object[] { new Vector<>(l) });
|
||||
Stack<Integer> s = new Stack<>(); s.addAll(l);
|
||||
cases.add(new Object[]{s});
|
||||
cases.add(new Object[] { new CopyOnWriteArrayList<>(l) });
|
||||
cases.add(new Object[] { l });
|
||||
return cases.toArray(new Object[0][cases.size()]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "listProvider")
|
||||
public void testProvidedWithNull(final List<Integer> list) {
|
||||
try {
|
||||
list.forEach(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
try {
|
||||
list.replaceAll(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
try {
|
||||
list.removeIf(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
try {
|
||||
list.sort(null);
|
||||
} catch (Throwable t) {
|
||||
fail("Exception not expected: " + t);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForEach() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
try {
|
||||
list.forEach(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
final List<Integer> actual = new LinkedList<>();
|
||||
list.forEach(actual::add);
|
||||
CollectionAsserts.assertContents(actual, list);
|
||||
CollectionAsserts.assertContents(actual, original);
|
||||
|
||||
if (original.size() > SUBLIST_SIZE) {
|
||||
final List<Integer> subList = original.subList(SUBLIST_FROM, SUBLIST_TO);
|
||||
final List<Integer> actualSubList = new LinkedList<>();
|
||||
subList.forEach(actualSubList::add);
|
||||
assertEquals(actualSubList.size(), SUBLIST_SIZE);
|
||||
for (int i = 0; i < SUBLIST_SIZE; i++) {
|
||||
assertEquals(actualSubList.get(i), original.get(i + SUBLIST_FROM));
|
||||
}
|
||||
}
|
||||
|
||||
trimmedSubList(list, l -> {
|
||||
final List<Integer> a = new LinkedList<>();
|
||||
l.forEach(a::add);
|
||||
CollectionAsserts.assertContents(a, l);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveIf() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_STRUCT_MOD_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
try {
|
||||
list.removeIf(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
final AtomicInteger offset = new AtomicInteger(1);
|
||||
while (list.size() > 0) {
|
||||
removeFirst(original, list, offset);
|
||||
}
|
||||
}
|
||||
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
list.removeIf(pOdd);
|
||||
for (int i : list) {
|
||||
assertTrue((i % 2) == 0);
|
||||
}
|
||||
for (int i : original) {
|
||||
if (i % 2 == 0) {
|
||||
assertTrue(list.contains(i));
|
||||
}
|
||||
}
|
||||
list.removeIf(pEven);
|
||||
assertTrue(list.isEmpty());
|
||||
}
|
||||
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
final List<Integer> listCopy = new ArrayList<>(list);
|
||||
if (original.size() > SUBLIST_SIZE) {
|
||||
final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
|
||||
final List<Integer> subListCopy = new ArrayList<>(subList);
|
||||
listCopy.removeAll(subList);
|
||||
subList.removeIf(pOdd);
|
||||
for (int i : subList) {
|
||||
assertTrue((i % 2) == 0);
|
||||
}
|
||||
for (int i : subListCopy) {
|
||||
if (i % 2 == 0) {
|
||||
assertTrue(subList.contains(i));
|
||||
} else {
|
||||
assertFalse(subList.contains(i));
|
||||
}
|
||||
}
|
||||
subList.removeIf(pEven);
|
||||
assertTrue(subList.isEmpty());
|
||||
// elements outside the view should remain
|
||||
CollectionAsserts.assertContents(list, listCopy);
|
||||
}
|
||||
}
|
||||
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
trimmedSubList(list, l -> {
|
||||
final List<Integer> copy = new ArrayList<>(l);
|
||||
l.removeIf(pOdd);
|
||||
for (int i : l) {
|
||||
assertTrue((i % 2) == 0);
|
||||
}
|
||||
for (int i : copy) {
|
||||
if (i % 2 == 0) {
|
||||
assertTrue(l.contains(i));
|
||||
} else {
|
||||
assertFalse(l.contains(i));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// remove the first element
|
||||
private void removeFirst(final List<Integer> original, final List<Integer> list, final AtomicInteger offset) {
|
||||
final AtomicBoolean first = new AtomicBoolean(true);
|
||||
list.removeIf(x -> first.getAndSet(false));
|
||||
CollectionAsserts.assertContents(original.subList(offset.getAndIncrement(), original.size()), list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAll() {
|
||||
final int scale = 3;
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
try {
|
||||
list.replaceAll(null);
|
||||
fail("expected NPE not thrown");
|
||||
} catch (NullPointerException npe) {}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
list.replaceAll(x -> scale * x);
|
||||
for (int i = 0; i < original.size(); i++) {
|
||||
assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i);
|
||||
}
|
||||
|
||||
if (original.size() > SUBLIST_SIZE) {
|
||||
final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
|
||||
subList.replaceAll(x -> x + 1);
|
||||
// verify elements in view [from, to) were replaced
|
||||
for (int i = 0; i < SUBLIST_SIZE; i++) {
|
||||
assertTrue(subList.get(i) == ((scale * original.get(i + SUBLIST_FROM)) + 1),
|
||||
"mismatch at sublist index " + i);
|
||||
}
|
||||
// verify that elements [0, from) remain unmodified
|
||||
for (int i = 0; i < SUBLIST_FROM; i++) {
|
||||
assertTrue(list.get(i) == (scale * original.get(i)),
|
||||
"mismatch at original index " + i);
|
||||
}
|
||||
// verify that elements [to, size) remain unmodified
|
||||
for (int i = SUBLIST_TO; i < list.size(); i++) {
|
||||
assertTrue(list.get(i) == (scale * original.get(i)),
|
||||
"mismatch at original index " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
trimmedSubList(list, l -> {
|
||||
final List<Integer> copy = new ArrayList<>(l);
|
||||
final int offset = 5;
|
||||
l.replaceAll(x -> offset + x);
|
||||
for (int i = 0; i < copy.size(); i++) {
|
||||
assertTrue(l.get(i) == (offset + copy.get(i)), "mismatch at index " + i);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSort() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> original = test.expected;
|
||||
final List<Integer> list = test.collection;
|
||||
CollectionSupplier.shuffle(list);
|
||||
list.sort(Integer::compare);
|
||||
CollectionAsserts.assertSorted(list, Integer::compare);
|
||||
if (test.name.startsWith("reverse")) {
|
||||
Collections.reverse(list);
|
||||
}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
CollectionSupplier.shuffle(list);
|
||||
list.sort(null);
|
||||
CollectionAsserts.assertSorted(list, Comparator.naturalOrder());
|
||||
if (test.name.startsWith("reverse")) {
|
||||
Collections.reverse(list);
|
||||
}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
CollectionSupplier.shuffle(list);
|
||||
list.sort(Comparator.naturalOrder());
|
||||
CollectionAsserts.assertSorted(list, Comparator.naturalOrder());
|
||||
if (test.name.startsWith("reverse")) {
|
||||
Collections.reverse(list);
|
||||
}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
CollectionSupplier.shuffle(list);
|
||||
list.sort(Comparator.reverseOrder());
|
||||
CollectionAsserts.assertSorted(list, Comparator.reverseOrder());
|
||||
if (!test.name.startsWith("reverse")) {
|
||||
Collections.reverse(list);
|
||||
}
|
||||
CollectionAsserts.assertContents(list, original);
|
||||
|
||||
CollectionSupplier.shuffle(list);
|
||||
list.sort(BIT_COUNT_COMPARATOR);
|
||||
CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR);
|
||||
// check sort by verifying that bitCount increases and never drops
|
||||
int minBitCount = 0;
|
||||
for (final Integer i : list) {
|
||||
int bitCount = Integer.bitCount(i);
|
||||
assertTrue(bitCount >= minBitCount);
|
||||
minBitCount = bitCount;
|
||||
}
|
||||
|
||||
// Reuse the supplier to store AtomicInteger instead of Integer
|
||||
// Hence the use of raw type and cast
|
||||
List<AtomicInteger> incomparablesData = new ArrayList<>();
|
||||
for (int i = 0; i < test.expected.size(); i++) {
|
||||
incomparablesData.add(new AtomicInteger(i));
|
||||
}
|
||||
Function f = test.supplier;
|
||||
@SuppressWarnings("unchecked")
|
||||
List<AtomicInteger> incomparables = (List<AtomicInteger>) f.apply(incomparablesData);
|
||||
|
||||
CollectionSupplier.shuffle(incomparables);
|
||||
incomparables.sort(ATOMIC_INTEGER_COMPARATOR);
|
||||
for (int i = 0; i < test.expected.size(); i++) {
|
||||
assertEquals(i, incomparables.get(i).intValue());
|
||||
}
|
||||
|
||||
|
||||
if (original.size() > SUBLIST_SIZE) {
|
||||
final List<Integer> copy = new ArrayList<>(list);
|
||||
final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
|
||||
CollectionSupplier.shuffle(subList);
|
||||
subList.sort(Comparator.naturalOrder());
|
||||
CollectionAsserts.assertSorted(subList, Comparator.naturalOrder());
|
||||
// verify that elements [0, from) remain unmodified
|
||||
for (int i = 0; i < SUBLIST_FROM; i++) {
|
||||
assertTrue(list.get(i) == copy.get(i),
|
||||
"mismatch at index " + i);
|
||||
}
|
||||
// verify that elements [to, size) remain unmodified
|
||||
for (int i = SUBLIST_TO; i < list.size(); i++) {
|
||||
assertTrue(list.get(i) == copy.get(i),
|
||||
"mismatch at index " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
trimmedSubList(list, l -> {
|
||||
CollectionSupplier.shuffle(l);
|
||||
l.sort(Comparator.naturalOrder());
|
||||
CollectionAsserts.assertSorted(l, Comparator.naturalOrder());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForEachThrowsCME() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
if (list.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
boolean gotException = false;
|
||||
try {
|
||||
// bad predicate that modifies its list, should throw CME
|
||||
list.forEach(list::add);
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
gotException = true;
|
||||
}
|
||||
if (!gotException) {
|
||||
fail("expected CME was not thrown from " + test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveIfThrowsCME() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
if (list.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
boolean gotException = false;
|
||||
try {
|
||||
// bad predicate that modifies its list, should throw CME
|
||||
list.removeIf(list::add);
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
gotException = true;
|
||||
}
|
||||
if (!gotException) {
|
||||
fail("expected CME was not thrown from " + test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllThrowsCME() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
if (list.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
boolean gotException = false;
|
||||
try {
|
||||
// bad predicate that modifies its list, should throw CME
|
||||
list.replaceAll(x -> {int n = 3 * x; list.add(n); return n;});
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
gotException = true;
|
||||
}
|
||||
if (!gotException) {
|
||||
fail("expected CME was not thrown from " + test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSortThrowsCME() {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
|
||||
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
|
||||
final List<Integer> list = test.collection;
|
||||
|
||||
if (list.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
boolean gotException = false;
|
||||
try {
|
||||
// bad predicate that modifies its list, should throw CME
|
||||
list.sort((x, y) -> {list.add(x); return x - y;});
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
gotException = true;
|
||||
}
|
||||
if (!gotException) {
|
||||
fail("expected CME was not thrown from " + test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final List<Integer> SLICED_EXPECTED = Arrays.asList(0, 1, 2, 3, 5, 6, 7, 8, 9);
|
||||
private static final List<Integer> SLICED_EXPECTED2 = Arrays.asList(0, 1, 2, 5, 6, 7, 8, 9);
|
||||
|
||||
@DataProvider(name="shortIntListProvider", parallel=true)
|
||||
public static Object[][] intListCases() {
|
||||
final Integer[] DATA = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
final List<Object[]> cases = new LinkedList<>();
|
||||
cases.add(new Object[] { new ArrayList<>(Arrays.asList(DATA)) });
|
||||
cases.add(new Object[] { new LinkedList<>(Arrays.asList(DATA)) });
|
||||
cases.add(new Object[] { new Vector<>(Arrays.asList(DATA)) });
|
||||
cases.add(new Object[] { new CopyOnWriteArrayList<>(Arrays.asList(DATA)) });
|
||||
cases.add(new Object[] { new ExtendsAbstractList<>(Arrays.asList(DATA)) });
|
||||
return cases.toArray(new Object[0][cases.size()]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "shortIntListProvider")
|
||||
public void testRemoveIfFromSlice(final List<Integer> list) {
|
||||
final List<Integer> sublist = list.subList(3, 6);
|
||||
assertTrue(sublist.removeIf(x -> x == 4));
|
||||
CollectionAsserts.assertContents(list, SLICED_EXPECTED);
|
||||
|
||||
final List<Integer> sublist2 = list.subList(2, 5);
|
||||
assertTrue(sublist2.removeIf(x -> x == 3));
|
||||
CollectionAsserts.assertContents(list, SLICED_EXPECTED2);
|
||||
}
|
||||
}
|
||||
406
test/jdk/java/util/List/ListFactories.java
Normal file
406
test/jdk/java/util/List/ListFactories.java
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
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.assertThrows;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048330 8203184
|
||||
* @summary Test convenience static factory methods on List.
|
||||
* @run testng ListFactories
|
||||
*/
|
||||
|
||||
public class ListFactories {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// returns array of [actual, expected]
|
||||
static Object[] a(List<String> act, List<String> exp) {
|
||||
return new Object[] { act, exp };
|
||||
}
|
||||
|
||||
@DataProvider(name="empty")
|
||||
public Iterator<Object[]> empty() {
|
||||
return Collections.singletonList(
|
||||
a(List.of(), asList())
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonempty")
|
||||
public Iterator<Object[]> nonempty() {
|
||||
return asList(
|
||||
a(List.of("a"),
|
||||
asList("a")),
|
||||
a(List.of("a", "b"),
|
||||
asList("a", "b")),
|
||||
a(List.of("a", "b", "c"),
|
||||
asList("a", "b", "c")),
|
||||
a(List.of("a", "b", "c", "d"),
|
||||
asList("a", "b", "c", "d")),
|
||||
a(List.of("a", "b", "c", "d", "e"),
|
||||
asList("a", "b", "c", "d", "e")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f"),
|
||||
asList("a", "b", "c", "d", "e", "f")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
|
||||
a(List.of(stringArray),
|
||||
asList(stringArray))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="sublists")
|
||||
public Iterator<Object[]> sublists() {
|
||||
return asList(
|
||||
a(List.<String>of().subList(0,0),
|
||||
asList()),
|
||||
a(List.of("a").subList(0,0),
|
||||
asList("a").subList(0,0)),
|
||||
a(List.of("a", "b").subList(0,1),
|
||||
asList("a", "b").subList(0,1)),
|
||||
a(List.of("a", "b", "c").subList(1,3),
|
||||
asList("a", "b", "c").subList(1,3)),
|
||||
a(List.of("a", "b", "c", "d").subList(0,4),
|
||||
asList("a", "b", "c", "d").subList(0,4)),
|
||||
a(List.of("a", "b", "c", "d", "e").subList(0,3),
|
||||
asList("a", "b", "c", "d", "e").subList(0,3)),
|
||||
a(List.of("a", "b", "c", "d", "e", "f").subList(3, 5),
|
||||
asList("a", "b", "c", "d", "e", "f").subList(3, 5)),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g").subList(0, 7),
|
||||
asList("a", "b", "c", "d", "e", "f", "g").subList(0, 7)),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0)),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5)),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10)),
|
||||
a(List.of(stringArray).subList(5, NUM_STRINGS),
|
||||
asList(Arrays.copyOfRange(stringArray, 5, NUM_STRINGS)))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="all")
|
||||
public Iterator<Object[]> all() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
sublists().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonsublists")
|
||||
public Iterator<Object[]> nonsublists() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAddLast(List<String> act, List<String> exp) {
|
||||
act.add("x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAddFirst(List<String> act, List<String> exp) {
|
||||
act.add(0, "x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotRemove(List<String> act, List<String> exp) {
|
||||
act.remove(0);
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotSet(List<String> act, List<String> exp) {
|
||||
act.set(0, "x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void contentsMatch(List<String> act, List<String> exp) {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed1() {
|
||||
List.of((Object)null); // force one-arg overload
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2a() {
|
||||
List.of("a", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2b() {
|
||||
List.of(null, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed3() {
|
||||
List.of("a", "b", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed4() {
|
||||
List.of("a", "b", "c", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed5() {
|
||||
List.of("a", "b", "c", "d", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed6() {
|
||||
List.of("a", "b", "c", "d", "e", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed7() {
|
||||
List.of("a", "b", "c", "d", "e", "f", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed8() {
|
||||
List.of("a", "b", "c", "d", "e", "f", "g", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed9() {
|
||||
List.of("a", "b", "c", "d", "e", "f", "g", "h", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed10() {
|
||||
List.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;
|
||||
List.of(array);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullArrayDisallowed() {
|
||||
List.of((Object[])null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureArrayCannotModifyList() {
|
||||
String[] array = stringArray.clone();
|
||||
List<String> list = List.of(array);
|
||||
array[0] = "xyzzy";
|
||||
assertEquals(list, Arrays.asList(stringArray));
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=NullPointerException.class)
|
||||
public void containsNullShouldThrowNPE(List<String> act, List<String> exp) {
|
||||
act.contains(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=NullPointerException.class)
|
||||
public void indexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
|
||||
act.indexOf(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=NullPointerException.class)
|
||||
public void lastIndexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
|
||||
act.lastIndexOf(null);
|
||||
}
|
||||
|
||||
// List.of().subList views should not be Serializable
|
||||
@Test(dataProvider="sublists")
|
||||
public void isNotSerializable(List<String> act, List<String> exp) {
|
||||
assertFalse(act instanceof Serializable);
|
||||
}
|
||||
|
||||
// ... but List.of() should be
|
||||
@Test(dataProvider="nonsublists")
|
||||
public void serialEquality(List<String> act, List<String> exp) {
|
||||
// assume that act.equals(exp) tested elsewhere
|
||||
List<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);
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> genList() {
|
||||
return new ArrayList<>(Arrays.asList(1, 2, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfResultsEqual() {
|
||||
List<Integer> orig = genList();
|
||||
List<Integer> copy = List.copyOf(orig);
|
||||
|
||||
assertEquals(orig, copy);
|
||||
assertEquals(copy, orig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfModifiedUnequal() {
|
||||
List<Integer> orig = genList();
|
||||
List<Integer> copy = List.copyOf(orig);
|
||||
orig.add(4);
|
||||
|
||||
assertNotEquals(orig, copy);
|
||||
assertNotEquals(copy, orig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfIdentity() {
|
||||
List<Integer> orig = genList();
|
||||
List<Integer> copy1 = List.copyOf(orig);
|
||||
List<Integer> copy2 = List.copyOf(copy1);
|
||||
|
||||
assertNotSame(orig, copy1);
|
||||
assertSame(copy1, copy2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfSubList() {
|
||||
List<Integer> orig = List.of(0, 1, 2, 3);
|
||||
List<Integer> sub = orig.subList(0, 3);
|
||||
List<Integer> copy = List.copyOf(sub);
|
||||
|
||||
assertNotSame(sub, copy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfSubSubList() {
|
||||
List<Integer> orig = List.of(0, 1, 2, 3);
|
||||
List<Integer> sub = orig.subList(0, 3).subList(0, 2);
|
||||
List<Integer> copy = List.copyOf(sub);
|
||||
|
||||
assertNotSame(sub, copy);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void copyOfRejectsNullCollection() {
|
||||
List<Integer> list = List.copyOf(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void copyOfRejectsNullElements() {
|
||||
List<Integer> list = List.copyOf(Arrays.asList(1, null, 3));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void copyOfRejectsNullElements2() {
|
||||
List<String> list = List.copyOf(Stream.of("a", null, "c").toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyOfCopiesNullAllowingList() {
|
||||
List<String> orig = Stream.of("a", "b", "c").toList();
|
||||
List<String> copy = List.copyOf(orig);
|
||||
|
||||
assertNotSame(orig, copy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iteratorShouldNotBeListIterator() {
|
||||
List<Integer> list = List.of(1, 2, 3, 4, 5);
|
||||
Iterator<Integer> it = list.iterator();
|
||||
it.next();
|
||||
try {
|
||||
((ListIterator<Integer>) it).previous();
|
||||
fail("ListIterator operation succeeded on Iterator");
|
||||
} catch (ClassCastException|UnsupportedOperationException ignore) { }
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void getFirst(List<String> act, List<String> exp) {
|
||||
if (!act.isEmpty()) {
|
||||
assertEquals(act.getFirst(), exp.getFirst());
|
||||
} else {
|
||||
assertThrows(NoSuchElementException.class, act::getFirst);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void getLast(List<String> act, List<String> exp) {
|
||||
if (!act.isEmpty()) {
|
||||
assertEquals(act.getLast(), exp.getLast());
|
||||
} else {
|
||||
assertThrows(NoSuchElementException.class, act::getLast);
|
||||
}
|
||||
}
|
||||
}
|
||||
362
test/jdk/java/util/List/LockStep.java
Normal file
362
test/jdk/java/util/List/LockStep.java
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* 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
|
||||
* @bug 6359979
|
||||
* @summary Compare List implementations for identical behavior
|
||||
* @author Martin Buchholz
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LockStep {
|
||||
final int DEFAULT_SIZE = 5;
|
||||
int size; // Running time is O(size**2)
|
||||
|
||||
int intArg(String[] args, int i, int defaultValue) {
|
||||
return args.length > i ? Integer.parseInt(args[i]) : defaultValue;
|
||||
}
|
||||
|
||||
boolean maybe(int n) { return rnd.nextInt(n) == 0; }
|
||||
|
||||
void test(String[] args) {
|
||||
size = intArg(args, 0, DEFAULT_SIZE);
|
||||
|
||||
lockSteps(new ArrayList(),
|
||||
new LinkedList(),
|
||||
new Vector());
|
||||
}
|
||||
|
||||
void equalLists(List... lists) {
|
||||
for (List list : lists)
|
||||
equalLists(list, lists[0]);
|
||||
}
|
||||
|
||||
void equalLists(List x, List y) {
|
||||
equal(x, y);
|
||||
equal(y, x);
|
||||
equal(x.size(), y.size());
|
||||
equal(x.isEmpty(), y.isEmpty());
|
||||
equal(x.hashCode(), y.hashCode());
|
||||
equal(x.toString(), y.toString());
|
||||
equal(x.toArray(), y.toArray());
|
||||
}
|
||||
|
||||
void lockSteps(List... lists) {
|
||||
for (int i = 0; i < lists.length; i++)
|
||||
if (maybe(4)) lists[i] = serialClone(lists[i]);
|
||||
for (final List list : lists)
|
||||
testEmptyList(list);
|
||||
for (int i = 0; i < size; i++) {
|
||||
ListFrobber adder = randomAdder();
|
||||
for (final List list : lists) {
|
||||
adder.frob(list);
|
||||
equal(list.size(), i+1);
|
||||
}
|
||||
equalLists(lists);
|
||||
}
|
||||
{
|
||||
final ListFrobber adder = randomAdder();
|
||||
final ListFrobber remover = randomRemover();
|
||||
for (final List list : lists) {
|
||||
|
||||
THROWS(ConcurrentModificationException.class,
|
||||
new F(){void f(){
|
||||
Iterator it = list.iterator();
|
||||
adder.frob(list);
|
||||
it.next();}},
|
||||
new F(){void f(){
|
||||
Iterator it = asSubList(list).iterator();
|
||||
remover.frob(list);
|
||||
it.next();}},
|
||||
new F(){void f(){
|
||||
Iterator it = asSubList(asSubList(list)).iterator();
|
||||
adder.frob(list);
|
||||
it.next();}},
|
||||
new F(){void f(){
|
||||
List subList = asSubList(list);
|
||||
remover.frob(list);
|
||||
subList.get(0);}},
|
||||
new F(){void f(){
|
||||
List sl = asSubList(list);
|
||||
List ssl = asSubList(sl);
|
||||
adder.frob(sl);
|
||||
ssl.get(0);}},
|
||||
new F(){void f(){
|
||||
List sl = asSubList(list);
|
||||
List ssl = asSubList(sl);
|
||||
remover.frob(sl);
|
||||
ssl.get(0);}});
|
||||
}
|
||||
}
|
||||
|
||||
for (final List l : lists) {
|
||||
final List sl = asSubList(l);
|
||||
final List ssl = asSubList(sl);
|
||||
ssl.add(0, 42);
|
||||
equal(ssl.get(0), 42);
|
||||
equal(sl.get(0), 42);
|
||||
equal(l.get(0), 42);
|
||||
final int s = l.size();
|
||||
final int rndIndex = rnd.nextInt(l.size());
|
||||
THROWS(IndexOutOfBoundsException.class,
|
||||
new F(){void f(){l.subList(rndIndex, rndIndex).get(0);}},
|
||||
new F(){void f(){l.subList(s/2, s).get(s/2 + 1);}},
|
||||
new F(){void f(){l.subList(s/2, s).get(-1);}}
|
||||
);
|
||||
THROWS(IllegalArgumentException.class,
|
||||
new F(){void f(){ l.subList(1, 0);}},
|
||||
new F(){void f(){ sl.subList(1, 0);}},
|
||||
new F(){void f(){ssl.subList(1, 0);}});
|
||||
}
|
||||
|
||||
equalLists(lists);
|
||||
|
||||
for (final List list : lists) {
|
||||
equalLists(list, asSubList(list));
|
||||
equalLists(list, asSubList(asSubList(list)));
|
||||
}
|
||||
for (final List list : lists)
|
||||
System.out.println(list);
|
||||
|
||||
for (int i = lists[0].size(); i > 0; i--) {
|
||||
ListFrobber remover = randomRemover();
|
||||
for (final List list : lists)
|
||||
remover.frob(list);
|
||||
equalLists(lists);
|
||||
}
|
||||
}
|
||||
|
||||
<T> List<T> asSubList(List<T> list) {
|
||||
return list.subList(0, list.size());
|
||||
}
|
||||
|
||||
void testEmptyCollection(Collection<?> c) {
|
||||
check(c.isEmpty());
|
||||
equal(c.size(), 0);
|
||||
equal(c.toString(),"[]");
|
||||
equal(c.toArray().length, 0);
|
||||
equal(c.toArray(new Object[0]).length, 0);
|
||||
|
||||
Object[] a = new Object[1]; a[0] = Boolean.TRUE;
|
||||
equal(c.toArray(a), a);
|
||||
equal(a[0], null);
|
||||
}
|
||||
|
||||
void testEmptyList(List list) {
|
||||
testEmptyCollection(list);
|
||||
equal(list.hashCode(), 1);
|
||||
equal(list, Collections.emptyList());
|
||||
}
|
||||
|
||||
final Random rnd = new Random();
|
||||
|
||||
abstract class ListFrobber { abstract void frob(List l); }
|
||||
|
||||
ListFrobber randomAdder() {
|
||||
final Integer e = rnd.nextInt(1024);
|
||||
final int subListCount = rnd.nextInt(3);
|
||||
final boolean atBeginning = rnd.nextBoolean();
|
||||
final boolean useIterator = rnd.nextBoolean();
|
||||
final boolean simpleIterator = rnd.nextBoolean();
|
||||
return new ListFrobber() {void frob(List l) {
|
||||
final int s = l.size();
|
||||
List ll = l;
|
||||
for (int i = 0; i < subListCount; i++)
|
||||
ll = asSubList(ll);
|
||||
if (! useIterator) {
|
||||
if (atBeginning) {
|
||||
switch (rnd.nextInt(3)) {
|
||||
case 0: ll.add(0, e); break;
|
||||
case 1: ll.subList(0, rnd.nextInt(s+1)).add(0, e); break;
|
||||
case 2: ll.subList(0, rnd.nextInt(s+1)).subList(0,0).add(0,e); break;
|
||||
default: throw new Error();
|
||||
}
|
||||
} else {
|
||||
switch (rnd.nextInt(3)) {
|
||||
case 0: check(ll.add(e)); break;
|
||||
case 1: ll.subList(s/2, s).add(s - s/2, e); break;
|
||||
case 2: ll.subList(s, s).subList(0, 0).add(0, e); break;
|
||||
default: throw new Error();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (atBeginning) {
|
||||
ListIterator it = ll.listIterator();
|
||||
equal(it.nextIndex(), 0);
|
||||
check(! it.hasPrevious());
|
||||
it.add(e);
|
||||
equal(it.previousIndex(), 0);
|
||||
equal(it.nextIndex(), 1);
|
||||
check(it.hasPrevious());
|
||||
} else {
|
||||
final int siz = ll.size();
|
||||
ListIterator it = ll.listIterator(siz);
|
||||
equal(it.previousIndex(), siz-1);
|
||||
check(! it.hasNext());
|
||||
it.add(e);
|
||||
equal(it.previousIndex(), siz);
|
||||
equal(it.nextIndex(), siz+1);
|
||||
check(! it.hasNext());
|
||||
check(it.hasPrevious());
|
||||
}
|
||||
}}};
|
||||
}
|
||||
|
||||
ListFrobber randomRemover() {
|
||||
final int position = rnd.nextInt(3);
|
||||
final int subListCount = rnd.nextInt(3);
|
||||
return new ListFrobber() {void frob(List l) {
|
||||
final int s = l.size();
|
||||
List ll = l;
|
||||
for (int i = 0; i < subListCount; i++)
|
||||
ll = asSubList(ll);
|
||||
switch (position) {
|
||||
case 0: // beginning
|
||||
switch (rnd.nextInt(3)) {
|
||||
case 0: ll.remove(0); break;
|
||||
case 1: {
|
||||
final Iterator it = ll.iterator();
|
||||
check(it.hasNext());
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
it.next();
|
||||
it.remove();
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
break;}
|
||||
case 2: {
|
||||
final ListIterator it = ll.listIterator();
|
||||
check(it.hasNext());
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
it.next();
|
||||
it.remove();
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
break;}
|
||||
default: throw new Error();
|
||||
}
|
||||
break;
|
||||
case 1: // midpoint
|
||||
switch (rnd.nextInt(3)) {
|
||||
case 0: ll.remove(s/2); break;
|
||||
case 1: {
|
||||
final ListIterator it = ll.listIterator(s/2);
|
||||
it.next();
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
final ListIterator it = ll.listIterator(s/2+1);
|
||||
it.previous();
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
default: throw new Error();
|
||||
}
|
||||
break;
|
||||
case 2: // end
|
||||
switch (rnd.nextInt(3)) {
|
||||
case 0: ll.remove(s-1); break;
|
||||
case 1: ll.subList(s-1, s).clear(); break;
|
||||
case 2:
|
||||
final ListIterator it = ll.listIterator(s);
|
||||
check(! it.hasNext());
|
||||
check(it.hasPrevious());
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
it.previous();
|
||||
equal(it.nextIndex(), s-1);
|
||||
check(it.hasNext());
|
||||
it.remove();
|
||||
equal(it.nextIndex(), s-1);
|
||||
check(! it.hasNext());
|
||||
THROWS(IllegalStateException.class,
|
||||
new F(){void f(){it.remove();}});
|
||||
break;
|
||||
default: throw new Error();
|
||||
}
|
||||
break;
|
||||
default: throw new Error();
|
||||
}}};
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
<T> void equal(T[] x, T[] y) {check(Arrays.equals(x,y));}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new LockStep().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(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");}
|
||||
abstract class F {abstract void f() throws Throwable;}
|
||||
void THROWS(Class<? extends Throwable> k, F... fs) {
|
||||
for (F f : fs)
|
||||
try {f.f(); fail("Expected " + k.getName() + " not thrown");}
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
static byte[] serializedForm(Object obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new ObjectOutputStream(baos).writeObject(obj);
|
||||
return baos.toByteArray();
|
||||
} catch (IOException e) { throw new RuntimeException(e); }}
|
||||
static Object readObject(byte[] bytes)
|
||||
throws IOException, ClassNotFoundException {
|
||||
InputStream is = new ByteArrayInputStream(bytes);
|
||||
return new ObjectInputStream(is).readObject();}
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try { return (T) readObject(serializedForm(obj)); }
|
||||
catch (Exception e) { throw new RuntimeException(e); }}
|
||||
}
|
||||
97
test/jdk/java/util/List/NestedSubList.java
Normal file
97
test/jdk/java/util/List/NestedSubList.java
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8079136
|
||||
* @run testng NestedSubList
|
||||
* @summary Accessing a nested sublist leads to StackOverflowError
|
||||
*/
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
public class NestedSubList {
|
||||
|
||||
static final int NEST_LIMIT = 65536;
|
||||
|
||||
@Test(dataProvider="lists")
|
||||
public void testAccessToSublists(List<Integer> list, boolean modifiable) {
|
||||
Class<?> cls = list.getClass();
|
||||
for (int i = 0; i < NEST_LIMIT; ++i) {
|
||||
list = list.subList(0, 1);
|
||||
}
|
||||
|
||||
try {
|
||||
list.get(0);
|
||||
if (modifiable) {
|
||||
list.remove(0);
|
||||
list.add(0, 42);
|
||||
}
|
||||
} catch (StackOverflowError e) {
|
||||
fail("failed for " + cls);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public static Object[][] lists() {
|
||||
final boolean MODIFIABLE = true;
|
||||
final boolean NON_MODIFIABLE = false;
|
||||
List<Integer> c = Arrays.asList(42);
|
||||
|
||||
return new Object[][] {
|
||||
{c, NON_MODIFIABLE},
|
||||
{new ArrayList<>(c), MODIFIABLE},
|
||||
{new LinkedList<>(c), MODIFIABLE},
|
||||
{new MyList(), NON_MODIFIABLE},
|
||||
{new Vector<>(c), MODIFIABLE},
|
||||
{Collections.singletonList(42), NON_MODIFIABLE},
|
||||
{Collections.checkedList(c, Integer.class), NON_MODIFIABLE},
|
||||
{Collections.checkedList(new ArrayList<>(c), Integer.class), MODIFIABLE},
|
||||
{Collections.checkedList(new LinkedList<>(c), Integer.class), MODIFIABLE},
|
||||
{Collections.checkedList(new Vector<>(c), Integer.class), MODIFIABLE},
|
||||
{Collections.synchronizedList(c), NON_MODIFIABLE},
|
||||
{Collections.synchronizedList(new ArrayList<>(c)), MODIFIABLE},
|
||||
{Collections.synchronizedList(new LinkedList<>(c)), MODIFIABLE},
|
||||
{Collections.synchronizedList(new Vector<>(c)), MODIFIABLE},
|
||||
{Collections.unmodifiableList(c), NON_MODIFIABLE},
|
||||
{Collections.unmodifiableList(new ArrayList<>(c)), NON_MODIFIABLE},
|
||||
{Collections.unmodifiableList(new LinkedList<>(c)), NON_MODIFIABLE},
|
||||
{Collections.unmodifiableList(new Vector<>(c)), NON_MODIFIABLE},
|
||||
};
|
||||
}
|
||||
|
||||
static class MyList extends AbstractList<Integer> {
|
||||
public Integer get(int index) { return 42; }
|
||||
public int size() { return 1; }
|
||||
}
|
||||
}
|
||||
676
test/jdk/java/util/List/SubList.java
Normal file
676
test/jdk/java/util/List/SubList.java
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8079136
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run testng SubList
|
||||
* @summary Basic functionality of sublists
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
|
||||
public class SubList extends org.testng.Assert {
|
||||
|
||||
final Random rnd = RandomFactory.getRandom();
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Integer e = rnd.nextInt();
|
||||
subList.add(e);
|
||||
assertEquals(list.get(to), e);
|
||||
assertEquals(subList.size(), to - from + 1);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.add(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
subList.add(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testAddAtPos(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
int i = rnd.nextInt(1 + to - from);
|
||||
Integer e = rnd.nextInt();
|
||||
subList.add(i, e);
|
||||
assertEquals(list.get(from + i), e);
|
||||
assertEquals(subList.size(), to - from + 1);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModAddAtPos(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
int i = rnd.nextInt(1 + to - from);
|
||||
subList.add(i, 42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodAddAtPos(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
int i = rnd.nextInt(1 + to - from);
|
||||
subList.add(i, 42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testClear(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
subList.clear();
|
||||
assertTrue(subList.isEmpty());
|
||||
assertEquals(subList.size(), 0);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModClear(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.clear();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodClear(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
subList.clear();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testEquals(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList1 = list.subList(from, to);
|
||||
List<Integer> subList2 = list.subList(from, to);
|
||||
assertTrue(subList1.equals(subList2));
|
||||
assertEquals(subList1.hashCode(), subList2.hashCode());
|
||||
for (int i = 0; i != 16; ++i) {
|
||||
int from3 = rnd.nextInt(1 + list.size());
|
||||
int to3 = from3 + rnd.nextInt(1 + list.size() - from3);
|
||||
boolean equal = (to - from) == (to3 - from3);
|
||||
for (int j = 0; j < to - from && j < to3 - from3; ++j)
|
||||
equal &= list.get(from + j) == list.get(from3 + j);
|
||||
List<Integer> subList3 = list.subList(from3, to3);
|
||||
assertEquals(subList1.equals(subList3), equal);
|
||||
}
|
||||
}
|
||||
|
||||
// @Test(dataProvider = "modifiable",
|
||||
// expectedExceptions = ConcurrentModificationException.class)
|
||||
// public void testModEquals(List<Integer> list, int from, int to) {
|
||||
// List<Integer> subList = list.subList(from, to);
|
||||
// list.add(42);
|
||||
// subList.equals(subList);
|
||||
// }
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModHashCode(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.hashCode();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testGet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int i = 0; i < to - from; ++i)
|
||||
assertEquals(list.get(from + i), subList.get(i));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModGet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.get(from);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testIndexOf(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
if (from < to) {
|
||||
Integer e = list.get(from);
|
||||
int j = subList.indexOf(e);
|
||||
assertTrue(j == 0);
|
||||
}
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
Integer e = list.get(i);
|
||||
int j = subList.indexOf(e);
|
||||
if (i < from || i >= to) {
|
||||
assertTrue(j == -1 || subList.get(j) == e);
|
||||
} else {
|
||||
assertTrue(j >= 0);
|
||||
assertTrue(j <= i - from);
|
||||
assertEquals(subList.get(j), e);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
Integer r = rnd.nextInt();
|
||||
if (list.contains(r)) continue;
|
||||
int j = subList.indexOf(r);
|
||||
assertTrue(j == -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModIndexOf(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.indexOf(from);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testIterator(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(list.get(i), it.next());
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModIteratorNext(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
list.add(42);
|
||||
it.next();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testIteratorRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(list.get(from), it.next());
|
||||
it.remove();
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
assertTrue(subList.isEmpty());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModIteratorRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
it.next();
|
||||
list.add(42);
|
||||
it.remove();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodIteratorRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
it.next();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testIteratorForEachRemaining(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int k = 0; k < 16; ++k) {
|
||||
int r = from + rnd.nextInt(1 + to - from);
|
||||
Iterator<Integer> it = subList.iterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
if (i == r) {
|
||||
Iterator<Integer> jt = list.listIterator(r);
|
||||
it.forEachRemaining(x ->
|
||||
assertTrue(jt.hasNext() && x == jt.next()));
|
||||
break;
|
||||
}
|
||||
assertEquals(list.get(i), it.next());
|
||||
}
|
||||
it.forEachRemaining(x -> fail());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testLastIndexOf(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
if (from < to) {
|
||||
Integer e = list.get(to - 1);
|
||||
int j = subList.lastIndexOf(e);
|
||||
assertTrue(j == to - from - 1);
|
||||
}
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
Integer e = list.get(i);
|
||||
int j = subList.lastIndexOf(e);
|
||||
if (i < from || i >= to) {
|
||||
assertTrue(j == -1 || subList.get(j) == e);
|
||||
} else {
|
||||
assertTrue(j >= 0 && j >= i - from);
|
||||
assertEquals(subList.get(j), e);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
Integer r = rnd.nextInt();
|
||||
if (list.contains(r)) continue;
|
||||
int j = subList.lastIndexOf(r);
|
||||
assertTrue(j == -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModLastIndexOf(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.lastIndexOf(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable")
|
||||
public void testListIterator(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(it.nextIndex() == i - from);
|
||||
assertEquals(list.get(i), it.next());
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModListIteratorNext(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
list.add(42);
|
||||
it.next();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testListIteratorSet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(it.nextIndex() == i - from);
|
||||
assertEquals(list.get(i), it.next());
|
||||
Integer e = rnd.nextInt();
|
||||
it.set(e);
|
||||
assertEquals(list.get(i), e);
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModListIteratorSet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
it.next();
|
||||
list.add(42);
|
||||
it.set(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unsettable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodListIteratorSet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
it.next();
|
||||
it.set(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable")
|
||||
public void testListIteratorPrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(subList.size());
|
||||
for (int i = to - 1; i >= from; --i) {
|
||||
assertTrue(it.hasPrevious());
|
||||
assertTrue(it.previousIndex() == i - from);
|
||||
assertEquals(list.get(i), it.previous());
|
||||
}
|
||||
assertFalse(it.hasPrevious());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModListIteratorPrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(to - from);
|
||||
list.add(42);
|
||||
it.previous();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testListIteratorSetPrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(subList.size());
|
||||
for (int i = to - 1; i >= from; --i) {
|
||||
assertTrue(it.hasPrevious());
|
||||
assertTrue(it.previousIndex() == i - from);
|
||||
assertEquals(list.get(i), it.previous());
|
||||
Integer e = rnd.nextInt();
|
||||
it.set(e);
|
||||
assertEquals(list.get(i), e);
|
||||
}
|
||||
assertFalse(it.hasPrevious());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unsettable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodListIteratorSetPrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(to - from);
|
||||
it.previous();
|
||||
it.set(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testListIteratorAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
int r = rnd.nextInt(1 + subList.size());
|
||||
ListIterator<Integer> it = subList.listIterator(r);
|
||||
Integer e = rnd.nextInt();
|
||||
it.add(e);
|
||||
assertEquals(it.previous(), e);
|
||||
assertEquals(list.get(from + r), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodListIteratorAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
int r = rnd.nextInt(1 + subList.size());
|
||||
ListIterator<Integer> it = subList.listIterator(r);
|
||||
it.add(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModListIteratorAdd(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
it.next();
|
||||
list.add(42);
|
||||
it.add(42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testListIteratorRemoveNext(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
for (int i = from; i < to; ++i) {
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(it.nextIndex() == 0);
|
||||
assertEquals(list.get(from), it.next());
|
||||
it.remove();
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
assertTrue(subList.isEmpty());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodListIteratorRemoveNext(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
it.next();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModListIteratorRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator();
|
||||
it.next();
|
||||
list.add(42);
|
||||
it.remove();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testListIteratorRemovePrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(subList.size());
|
||||
for (int i = to - 1; i >= from; --i) {
|
||||
assertTrue(it.hasPrevious());
|
||||
assertTrue(it.previousIndex() == i - from);
|
||||
assertEquals(list.get(i), it.previous());
|
||||
it.remove();
|
||||
}
|
||||
assertFalse(it.hasPrevious());
|
||||
assertTrue(subList.isEmpty());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodListIteratorRemovePrevious(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
ListIterator<Integer> it = subList.listIterator(subList.size());
|
||||
it.previous();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (subList.isEmpty()) break;
|
||||
int r = rnd.nextInt(subList.size());
|
||||
Integer e = list.get(from + r);
|
||||
assertEquals(subList.remove(r), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unresizable",
|
||||
expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testUnmodRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
int r = rnd.nextInt(subList.size());
|
||||
subList.remove(r);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModRemove(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.remove(0);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable")
|
||||
public void testSet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int i = 0; i < to - from; ++i) {
|
||||
Integer e0 = list.get(from + i);
|
||||
Integer e1 = rnd.nextInt();
|
||||
assertEquals(subList.set(i, e1), e0);
|
||||
assertEquals(list.get(from + i), e1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modifiable",
|
||||
expectedExceptions = ConcurrentModificationException.class)
|
||||
public void testModSet(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
list.add(42);
|
||||
subList.set(0, 42);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "all")
|
||||
public void testSubList(List<Integer> list, int from, int to) {
|
||||
List<Integer> subList = list.subList(from, to);
|
||||
for (int i = 0; i < 16 && from < to; ++i) {
|
||||
int from1 = rnd.nextInt(to - from);
|
||||
int to1 = from1 + 1 + rnd.nextInt(to - from - from1);
|
||||
List<Integer> subSubList = subList.subList(from1, to1);
|
||||
for (int j = 0; j < to1 - from1; ++j)
|
||||
assertEquals(list.get(from + from1 + j), subSubList.get(j));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All kinds of lists
|
||||
*/
|
||||
@DataProvider
|
||||
public static Object[][] all() {
|
||||
Object[][] l1 = modifiable();
|
||||
Object[][] l2 = unresizable();
|
||||
Object[][] res = Arrays.copyOf(l1, l1.length + l2.length);
|
||||
System.arraycopy(l2, 0, res, l1.length, l2.length);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists that allow any modifications: resizing and setting values
|
||||
*/
|
||||
@DataProvider
|
||||
public static Object[][] modifiable() {
|
||||
final List<Integer> c1 = Arrays.asList(42);
|
||||
final List<Integer> c9 = Arrays.asList(40, 41, 42, 43, 44, 45, -1,
|
||||
Integer.MIN_VALUE, 1000500);
|
||||
|
||||
return new Object[][] {
|
||||
{new ArrayList<>(c1), 0, 1},
|
||||
{new LinkedList<>(c1), 0, 1},
|
||||
{new Vector<>(c1), 0, 1},
|
||||
{new ArrayList<>(c1).subList(0, 1), 0, 1},
|
||||
{new LinkedList<>(c1).subList(0, 1), 0, 1},
|
||||
{new Vector<>(c1).subList(0, 1), 0, 1},
|
||||
{Collections.checkedList(new ArrayList<>(c1), Integer.class), 0, 1},
|
||||
{Collections.checkedList(new LinkedList<>(c1), Integer.class), 0, 1},
|
||||
{Collections.checkedList(new Vector<>(c1), Integer.class), 0, 1},
|
||||
{Collections.synchronizedList(new ArrayList<>(c1)), 0, 1},
|
||||
{Collections.synchronizedList(new LinkedList<>(c1)), 0, 1},
|
||||
{Collections.synchronizedList(new Vector<>(c1)), 0, 1},
|
||||
|
||||
{new ArrayList<>(c9), 2, 5},
|
||||
{new LinkedList<>(c9), 2, 5},
|
||||
{new Vector<>(c9), 2, 5},
|
||||
{new ArrayList<>(c9).subList(1, 8), 1, 4},
|
||||
{new LinkedList<>(c9).subList(1, 8), 1, 4},
|
||||
{new Vector<>(c9).subList(1, 8), 1, 4},
|
||||
{Collections.checkedList(new ArrayList<>(c9), Integer.class), 2, 5},
|
||||
{Collections.checkedList(new LinkedList<>(c9), Integer.class), 2, 5},
|
||||
{Collections.checkedList(new Vector<>(c9), Integer.class), 2, 5},
|
||||
{Collections.synchronizedList(new ArrayList<>(c9)), 2, 5},
|
||||
{Collections.synchronizedList(new LinkedList<>(c9)), 2, 5},
|
||||
{Collections.synchronizedList(new Vector<>(c9)), 2, 5},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists that don't allow resizing, but allow setting values
|
||||
*/
|
||||
@DataProvider
|
||||
public static Object[][] unresizable() {
|
||||
final List<Integer> c1 = Arrays.asList(42);
|
||||
final List<Integer> c9 = Arrays.asList(40, 41, 42, 43, 44, 45, -1,
|
||||
Integer.MIN_VALUE, 1000500);
|
||||
|
||||
Object[][] l1 = unsettable();
|
||||
Object[][] l2 = {
|
||||
{c1, 0, 1},
|
||||
{c1.subList(0, 1), 0, 1},
|
||||
{Collections.checkedList(c1, Integer.class), 0, 1},
|
||||
{Collections.synchronizedList(c1), 0, 1},
|
||||
{c9, 0, 4},
|
||||
{c9, 4, 6},
|
||||
{c9.subList(1, 8), 1, 4},
|
||||
{c9.subList(1, 8), 0, 7},
|
||||
{Collections.checkedList(c9, Integer.class), 3, 6},
|
||||
{Collections.synchronizedList(c9), 3, 5},
|
||||
};
|
||||
Object[][] res = Arrays.copyOf(l1, l1.length + l2.length);
|
||||
System.arraycopy(l2, 0, res, l1.length, l2.length);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists that don't allow either resizing or setting values
|
||||
*/
|
||||
@DataProvider
|
||||
public static Object[][] unsettable() {
|
||||
final List<Integer> c1 = Arrays.asList(42);
|
||||
final List<Integer> c9 = Arrays.asList(40, 41, 42, 43, 44, 45, -1,
|
||||
Integer.MIN_VALUE, 1000500);
|
||||
|
||||
return new Object[][] {
|
||||
{new MyList(1), 0, 1},
|
||||
{new MyList(1).subList(0, 1), 0, 1},
|
||||
{Collections.singletonList(42), 0, 1},
|
||||
{Collections.singletonList(42).subList(0, 1), 0, 1},
|
||||
{Collections.unmodifiableList(c1), 0, 1},
|
||||
{Collections.unmodifiableList(new ArrayList<>(c1)), 0, 1},
|
||||
{Collections.unmodifiableList(new LinkedList<>(c1)), 0, 1},
|
||||
{Collections.unmodifiableList(new Vector<>(c1)), 0, 1},
|
||||
|
||||
{new MyList(9), 3, 6},
|
||||
{new MyList(9).subList(2, 8), 3, 6},
|
||||
{Collections.unmodifiableList(c9), 3, 6},
|
||||
{Collections.unmodifiableList(new ArrayList<>(c9)), 3, 6},
|
||||
{Collections.unmodifiableList(new LinkedList<>(c9)), 3, 6},
|
||||
{Collections.unmodifiableList(new Vector<>(c9)), 3, 6},
|
||||
};
|
||||
}
|
||||
|
||||
static class MyList extends AbstractList<Integer> {
|
||||
private int size;
|
||||
MyList(int s) { size = s; }
|
||||
public Integer get(int index) { return 42; }
|
||||
public int size() { return size; }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue