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:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View 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);
}
}

View 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);
}
}
}

View 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); }}
}

View 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; }
}
}

View 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; }
}
}