/* * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * @test * @summary Unit tests for extension methods on List * @bug 8023367 8037106 * @library ../Collection/testlibrary * @build CollectionAsserts CollectionSupplier ExtendsAbstractList * @run testng ListDefaults
*/ publicclass ListDefaults {
// Suppliers of lists that can support structural modifications privatestaticfinal 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 privatestaticfinal 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())
);
// call the callback for each recursive subList privatevoid 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) publicstatic 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 publicvoid 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;
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 publicvoid 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;
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 privatevoid 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 publicvoid testReplaceAll() { finalint 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;
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); finalint 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 publicvoid 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(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 publicvoid 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 publicvoid 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 publicvoid 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 publicvoid 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);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.