17ce0976e4
Reviewed-by: alanb
858 lines
34 KiB
Java
858 lines
34 KiB
Java
/*
|
|
* Copyright (c) 2023, 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.*;
|
|
import java.util.*;
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
|
|
import static org.testng.Assert.assertEquals;
|
|
import static org.testng.Assert.assertSame;
|
|
import static org.testng.Assert.assertThrows;
|
|
import static org.testng.Assert.assertTrue;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8266571
|
|
* @summary Basic tests for SequencedCollection
|
|
* @modules java.base/java.util:open
|
|
* @build SimpleDeque SimpleList SimpleSortedSet
|
|
* @run testng Basic
|
|
*/
|
|
|
|
// TODO test that remove(obj) with duplicates removes the right element
|
|
|
|
public class Basic {
|
|
|
|
// ========== Data Providers ==========
|
|
|
|
static final List<String> ORIGINAL = List.of("a", "b", "c", "d", "e", "f", "g");
|
|
|
|
static List<String> cklist(List<String> contents) {
|
|
return Collections.checkedList(contents, String.class);
|
|
}
|
|
|
|
static NavigableSet<String> cknav(NavigableSet<String> set) {
|
|
return Collections.checkedNavigableSet(set, String.class);
|
|
}
|
|
|
|
static SortedSet<String> cksorted(SortedSet<String> set) {
|
|
return Collections.checkedSortedSet(set, String.class);
|
|
}
|
|
|
|
static SequencedSet<String> setFromMap(List<String> contents) {
|
|
var lhm = new LinkedHashMap<String, Boolean>();
|
|
var ss = Collections.newSequencedSetFromMap(lhm);
|
|
ss.addAll(contents);
|
|
return ss;
|
|
}
|
|
|
|
static SequencedCollection<String> ucoll(SequencedCollection<String> coll) {
|
|
return Collections.unmodifiableSequencedCollection(coll);
|
|
}
|
|
|
|
static SequencedCollection<String> ulist(List<String> list) {
|
|
return Collections.unmodifiableList(list);
|
|
}
|
|
|
|
static NavigableSet<String> unav(NavigableSet<String> set) {
|
|
return Collections.unmodifiableNavigableSet(set);
|
|
}
|
|
|
|
static SequencedSet<String> uset(SequencedSet<String> set) {
|
|
return Collections.unmodifiableSequencedSet(set);
|
|
}
|
|
|
|
static SortedSet<String> usorted(SortedSet<String> set) {
|
|
return Collections.unmodifiableSortedSet(set);
|
|
}
|
|
|
|
static <T> List<T> copyReversed(List<T> list) {
|
|
var r = new ArrayList<T>(list);
|
|
Collections.reverse(r);
|
|
return r;
|
|
}
|
|
|
|
@DataProvider(name="all")
|
|
public Iterator<Object[]> all() {
|
|
var result = new ArrayList<Object[]>();
|
|
populated().forEachRemaining(result::add);
|
|
empties().forEachRemaining(result::add);
|
|
return result.iterator();
|
|
}
|
|
|
|
@DataProvider(name="populated")
|
|
public Iterator<Object[]> populated() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()), ORIGINAL },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ListOf", ORIGINAL, ORIGINAL },
|
|
new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="empties")
|
|
public Iterator<Object[]> empties() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(), List.of() },
|
|
new Object[] { "ArrayList", new ArrayList<>(), List.of() },
|
|
new Object[] { "AsList", Arrays.asList(new String[0]), List.of() },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(), List.of() },
|
|
new Object[] { "EmptyList", Collections.emptyList(), List.of() },
|
|
new Object[] { "EmptyNavigableSet", Collections.emptyNavigableSet(), List.of() },
|
|
new Object[] { "EmptySortedSet", Collections.emptySortedSet(), List.of() },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(), List.of() },
|
|
new Object[] { "LinkedList", new LinkedList<>(), List.of() },
|
|
new Object[] { "ListOf", List.of(), List.of() },
|
|
new Object[] { "SetFromMap", setFromMap(List.of()), List.of() },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(), List.of() },
|
|
new Object[] { "SimpleList", new SimpleList<>(), List.of() },
|
|
new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(), List.of() },
|
|
new Object[] { "TreeSet", new TreeSet<>(), List.of() },
|
|
new Object[] { "UnmodColl", ucoll(new ArrayList<>()), List.of() },
|
|
new Object[] { "UnmodSet", uset(new LinkedHashSet<>()), List.of() }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="adds")
|
|
public Iterator<Object[]> adds() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="unpositionedAdd")
|
|
public Iterator<Object[]> unpositionedAdd() {
|
|
return Arrays.<Object[]>asList(
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="removes")
|
|
public Iterator<Object[]> removes() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="emptyRemoves")
|
|
public Iterator<Object[]> emptyRemoves() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(), List.of() },
|
|
new Object[] { "ArrayList", new ArrayList<>(), List.of() },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(), List.of() },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(), List.of() },
|
|
new Object[] { "LinkedList", new LinkedList<>(), List.of() },
|
|
new Object[] { "SetFromMap", setFromMap(List.of()), List.of() },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(), List.of() },
|
|
new Object[] { "SimpleList", new SimpleList<>(), List.of() },
|
|
new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(), List.of() },
|
|
new Object[] { "TreeSet", new TreeSet<>(), List.of() }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="serializable")
|
|
public Iterator<Object[]> serializable() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()), ORIGINAL },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "ListOf", ORIGINAL, ORIGINAL },
|
|
new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL },
|
|
new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="notSerializable")
|
|
public Iterator<Object[]> notSerializable() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL).reversed() },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL).reversed() },
|
|
new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()).reversed() },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL).reversed() },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL).reversed() },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL).reversed() },
|
|
new Object[] { "ListOf", ORIGINAL.reversed() },
|
|
new Object[] { "SetFromMap", setFromMap(ORIGINAL).reversed() },
|
|
new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)).reversed() },
|
|
new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)).reversed() }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="doubleReverse")
|
|
public Iterator<Object[]> doubleReverse() {
|
|
return Arrays.asList(
|
|
new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL) },
|
|
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL) },
|
|
new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()) },
|
|
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL) },
|
|
new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL) },
|
|
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL) },
|
|
new Object[] { "ListOf", ORIGINAL },
|
|
new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL) },
|
|
new Object[] { "SimpleList", new SimpleList<>(ORIGINAL) },
|
|
new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL) }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="unmodifiable")
|
|
public Iterator<Object[]> unmodifiable() {
|
|
return Arrays.asList(
|
|
new Object[] { "ListOf", ORIGINAL, ORIGINAL },
|
|
new Object[] { "ListOfSub", ORIGINAL.subList(1, 3), ORIGINAL.subList(1, 3) },
|
|
new Object[] { "SingleList", Collections.singletonList("a"), List.of("a") },
|
|
new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodList", ulist(new ArrayList<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodNav", unav(new TreeSet<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL },
|
|
new Object[] { "UnmodSorted", usorted(new TreeSet<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="checkedList")
|
|
public Iterator<Object[]> checkedList() {
|
|
return Arrays.<Object[]>asList(
|
|
new Object[] { "ChkList", cklist(new ArrayList<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="checkedNavSet")
|
|
public Iterator<Object[]> checkedNavSet() {
|
|
return Arrays.<Object[]>asList(
|
|
new Object[] { "ChkNav", cknav(new TreeSet<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
@DataProvider(name="checkedSortedSet")
|
|
public Iterator<Object[]> checkedSortedSet() {
|
|
return Arrays.<Object[]>asList(
|
|
new Object[] { "ChkSorted", cksorted(new TreeSet<>(ORIGINAL)), ORIGINAL }
|
|
).iterator();
|
|
}
|
|
|
|
// mode bit tests for subList testing
|
|
|
|
boolean reverseList(int mode) { return (mode & 1) != 0; }
|
|
boolean reverseSub(int mode) { return (mode & 2) != 0; }
|
|
boolean isReversed(int mode) { return reverseList(mode) ^ reverseSub(mode); }
|
|
|
|
List<String> applyMode(int mode, List<String> base) {
|
|
var list = reverseList(mode) ? base.reversed() : base;
|
|
var sub = list.subList(2, 5);
|
|
return reverseSub(mode) ? sub.reversed() : sub;
|
|
}
|
|
|
|
/**
|
|
* Generate cases for testing subLists. For each different List implementation, generate 4
|
|
* cases from the two bits of the testing mode int value:
|
|
*
|
|
* (bit 1) if true, the List is reversed
|
|
* (bit 2) if true, the subList is reversed
|
|
*
|
|
* @return the generated cases
|
|
*/
|
|
@DataProvider(name="subListMods")
|
|
public Iterator<Object[]> subListMods() {
|
|
var cases = new ArrayList<Object[]>();
|
|
for (int mode = 0; mode < 4; mode++) {
|
|
cases.addAll(Arrays.asList(
|
|
new Object[] { "ArrayList", mode, new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "COWAL", mode, new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", mode, new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", mode, new SimpleList<>(ORIGINAL), ORIGINAL }
|
|
));
|
|
}
|
|
return cases.iterator();
|
|
}
|
|
|
|
@DataProvider(name="iteratorMods")
|
|
public Iterator<Object[]> iteratorMods() {
|
|
var cases = new ArrayList<Object[]>();
|
|
for (boolean rev : List.of(false, true)) {
|
|
cases.addAll(Arrays.asList(
|
|
new Object[] { "ArrayList", rev, new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", rev, new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", rev, new SimpleList<>(ORIGINAL), ORIGINAL }
|
|
));
|
|
}
|
|
return cases.iterator();
|
|
}
|
|
|
|
@DataProvider(name="subListIteratorMods")
|
|
public Iterator<Object[]> subListIteratorMods() {
|
|
var cases = new ArrayList<Object[]>();
|
|
for (int mode = 0; mode < 4; mode++) {
|
|
cases.addAll(Arrays.asList(
|
|
new Object[] { "ArrayList", mode, new ArrayList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "LinkedList", mode, new LinkedList<>(ORIGINAL), ORIGINAL },
|
|
new Object[] { "SimpleList", mode, new SimpleList<>(ORIGINAL), ORIGINAL }
|
|
));
|
|
}
|
|
return cases.iterator();
|
|
}
|
|
|
|
// ========== Assertions ==========
|
|
|
|
/**
|
|
* Basic checks over the contents of a SequencedCollection,
|
|
* compared to a reference List, in one direction.
|
|
*
|
|
* @param seq the SequencedCollection under test
|
|
* @param ref the reference List
|
|
*/
|
|
public void checkContents1(SequencedCollection<String> seq, List<String> ref) {
|
|
var list1 = new ArrayList<String>();
|
|
for (var s : seq)
|
|
list1.add(s);
|
|
assertEquals(list1, ref);
|
|
|
|
var list2 = new ArrayList<String>();
|
|
seq.forEach(list2::add);
|
|
assertEquals(list2, ref);
|
|
|
|
var list3 = Arrays.asList(seq.toArray());
|
|
assertEquals(list3, ref);
|
|
|
|
var list4 = Arrays.asList(seq.toArray(new String[0]));
|
|
assertEquals(list4, ref);
|
|
|
|
var list5 = Arrays.asList(seq.toArray(String[]::new));
|
|
assertEquals(list5, ref);
|
|
|
|
var list6 = seq.stream().toList();
|
|
assertEquals(list6, ref);
|
|
|
|
var list7 = seq.parallelStream().toList();
|
|
assertEquals(list7, ref);
|
|
|
|
assertEquals(seq.size(), ref.size());
|
|
assertEquals(seq.isEmpty(), ref.isEmpty());
|
|
|
|
for (var s : ref) {
|
|
assertTrue(seq.contains(s));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check the contents of a SequencedCollection against a reference List,
|
|
* in both directions.
|
|
*
|
|
* @param seq the SequencedCollection under test
|
|
* @param ref the reference List
|
|
*/
|
|
public void checkContents(SequencedCollection<String> seq, List<String> ref) {
|
|
checkContents1(seq, ref);
|
|
|
|
var rref = copyReversed(ref);
|
|
var rseq = seq.reversed();
|
|
checkContents1(rseq, rref);
|
|
|
|
var rrseq = rseq.reversed();
|
|
checkContents1(rrseq, ref);
|
|
}
|
|
|
|
/**
|
|
* Check that modification operations will throw UnsupportedOperationException,
|
|
* in one direction.
|
|
*
|
|
* @param seq the SequencedCollection under test
|
|
*/
|
|
public void checkUnmodifiable1(SequencedCollection<String> seq) {
|
|
final var UOE = UnsupportedOperationException.class;
|
|
|
|
assertThrows(UOE, () -> seq.add("x"));
|
|
assertThrows(UOE, () -> seq.clear());
|
|
assertThrows(UOE, () -> { var it = seq.iterator(); it.next(); it.remove(); });
|
|
assertThrows(UOE, () -> seq.removeIf(x -> true));
|
|
|
|
assertThrows(UOE, () -> seq.addFirst("x"));
|
|
assertThrows(UOE, () -> seq.addLast("x"));
|
|
assertThrows(UOE, () -> seq.removeFirst());
|
|
assertThrows(UOE, () -> seq.removeLast());
|
|
|
|
// TODO these ops should throw unconditionally, but they don't in some implementations
|
|
// assertThrows(UOE, () -> seq.addAll(List.of()));
|
|
// assertThrows(UOE, () -> seq.remove("x"));
|
|
// assertThrows(UOE, () -> seq.removeAll(List.of()));
|
|
// assertThrows(UOE, () -> seq.removeIf(x -> false));
|
|
// assertThrows(UOE, () -> seq.retainAll(seq));
|
|
assertThrows(UOE, () -> seq.addAll(seq));
|
|
assertThrows(UOE, () -> seq.remove(seq.iterator().next()));
|
|
assertThrows(UOE, () -> seq.removeAll(seq));
|
|
assertThrows(UOE, () -> seq.retainAll(List.of()));
|
|
}
|
|
|
|
/**
|
|
* Check that modification operations will throw UnsupportedOperationException,
|
|
* in both directions.
|
|
*
|
|
* @param seq the SequencedCollection under test
|
|
*/
|
|
public void checkUnmodifiable(SequencedCollection<String> seq) {
|
|
checkUnmodifiable1(seq);
|
|
checkUnmodifiable1(seq.reversed());
|
|
}
|
|
|
|
static final Class<? extends Throwable> CCE = ClassCastException.class;
|
|
|
|
public void checkCheckedList(List<String> list) {
|
|
List<Object> objList = (List<Object>)(List)list;
|
|
assertThrows(CCE, () -> { objList.addFirst(new Object()); });
|
|
assertThrows(CCE, () -> { objList.addLast(new Object()); });
|
|
assertThrows(CCE, () -> { objList.reversed().addFirst(new Object()); });
|
|
assertThrows(CCE, () -> { objList.reversed().addLast(new Object()); });
|
|
}
|
|
|
|
public void checkCheckedNavSet(NavigableSet<String> set) {
|
|
NavigableSet<Object> objSet = (NavigableSet<Object>)(NavigableSet)set;
|
|
assertThrows(CCE, () -> { objSet.add(new Object()); });
|
|
assertThrows(CCE, () -> { objSet.reversed().add(new Object()); });
|
|
}
|
|
|
|
public void checkCheckedSortedSet(SortedSet<String> set) {
|
|
SortedSet<Object> objSet = (SortedSet<Object>)(SortedSet)set;
|
|
assertThrows(CCE, () -> { objSet.add(new Object()); });
|
|
assertThrows(CCE, () -> { objSet.reversed().add(new Object()); });
|
|
}
|
|
|
|
// ========== Tests ==========
|
|
|
|
@Test(dataProvider="all")
|
|
public void testFundamentals(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="populated")
|
|
public void testGetFirst(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
assertEquals(seq.getFirst(), ref.get(0));
|
|
assertEquals(seq.reversed().getFirst(), ref.get(ref.size() - 1));
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="populated")
|
|
public void testGetLast(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
assertEquals(seq.getLast(), ref.get(ref.size() - 1));
|
|
assertEquals(seq.reversed().getLast(), ref.get(0));
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="empties")
|
|
public void testEmptyGetFirst(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
assertThrows(NoSuchElementException.class, () -> seq.getFirst());
|
|
assertThrows(NoSuchElementException.class, () -> seq.reversed().getFirst());
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="empties")
|
|
public void testEmptyGetLast(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
assertThrows(NoSuchElementException.class, () -> seq.getLast());
|
|
assertThrows(NoSuchElementException.class, () -> seq.reversed().getLast());
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="adds")
|
|
public void testAddFirst(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add(0, "x");
|
|
seq.addFirst("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="adds")
|
|
public void testAddFirstRev(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add("x");
|
|
seq.reversed().addFirst("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="adds")
|
|
public void testAddLast(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add("x");
|
|
seq.addLast("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="adds")
|
|
public void testAddLastRev(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add(0, "x");
|
|
seq.reversed().addLast("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="unpositionedAdd")
|
|
public void testUnpositionedAdd(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add("x");
|
|
seq.add("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="unpositionedAdd")
|
|
public void testUnpositionedAddRev(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
ref.add("x");
|
|
seq.reversed().add("x");
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="removes")
|
|
public void testRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
var exp = ref.remove(0);
|
|
var act = seq.removeFirst();
|
|
assertEquals(act, exp);
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="removes")
|
|
public void testRemoveFirstRev(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
var exp = ref.remove(ref.size() - 1);
|
|
var act = seq.reversed().removeFirst();
|
|
assertEquals(act, exp);
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="removes")
|
|
public void testRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
var exp = ref.remove(ref.size() - 1);
|
|
var act = seq.removeLast();
|
|
assertEquals(act, exp);
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="removes")
|
|
public void testRemoveLastRev(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
var ref = new ArrayList<>(baseref);
|
|
var exp = ref.remove(0);
|
|
var act = seq.reversed().removeLast();
|
|
assertEquals(act, exp);
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="emptyRemoves")
|
|
public void testEmptyRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
assertThrows(NoSuchElementException.class, () -> seq.removeFirst());
|
|
assertThrows(NoSuchElementException.class, () -> seq.reversed().removeFirst());
|
|
checkContents(seq, baseref);
|
|
}
|
|
|
|
@Test(dataProvider="emptyRemoves")
|
|
public void testEmptyRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref) {
|
|
assertThrows(NoSuchElementException.class, () -> seq.removeLast());
|
|
assertThrows(NoSuchElementException.class, () -> seq.reversed().removeLast());
|
|
checkContents(seq, baseref);
|
|
}
|
|
|
|
@Test(dataProvider="serializable")
|
|
public void testSerializable(String label, SequencedCollection<String> seq, List<String> ref)
|
|
throws ClassNotFoundException, IOException
|
|
{
|
|
var baos = new ByteArrayOutputStream();
|
|
try (var oos = new ObjectOutputStream(baos)) {
|
|
oos.writeObject(seq);
|
|
}
|
|
|
|
try (var bais = new ByteArrayInputStream(baos.toByteArray());
|
|
var ois = new ObjectInputStream(bais)) {
|
|
var seq2 = (SequencedCollection<String>) ois.readObject();
|
|
checkContents(seq2, ref);
|
|
}
|
|
}
|
|
|
|
@Test(dataProvider="notSerializable")
|
|
public void testNotSerializable(String label, SequencedCollection<String> seq)
|
|
throws ClassNotFoundException, IOException
|
|
{
|
|
var baos = new ByteArrayOutputStream();
|
|
try (var oos = new ObjectOutputStream(baos)) {
|
|
assertThrows(ObjectStreamException.class, () -> oos.writeObject(seq));
|
|
}
|
|
}
|
|
|
|
@Test(dataProvider="doubleReverse")
|
|
public void testDoubleReverse(String label, SequencedCollection<String> seq) {
|
|
var rrseq = seq.reversed().reversed();
|
|
assertSame(rrseq, seq);
|
|
}
|
|
|
|
@Test(dataProvider="unmodifiable")
|
|
public void testUnmodifiable(String label, SequencedCollection<String> seq, List<String> ref) {
|
|
checkUnmodifiable(seq);
|
|
checkContents(seq, ref);
|
|
}
|
|
|
|
@Test(dataProvider="checkedList")
|
|
public void testCheckedList(String label, List<String> list, List<String> ref) {
|
|
checkCheckedList(list);
|
|
checkContents(list, ref);
|
|
}
|
|
|
|
@Test(dataProvider="checkedNavSet")
|
|
public void testCheckedNavSet(String label, NavigableSet<String> set, List<String> ref) {
|
|
checkCheckedNavSet(set);
|
|
checkContents(set, ref);
|
|
}
|
|
|
|
@Test(dataProvider="checkedSortedSet")
|
|
public void testCheckedSortedSet(String label, SortedSet<String> set, List<String> ref) {
|
|
checkCheckedSortedSet(set);
|
|
checkContents(set, ref);
|
|
}
|
|
|
|
// Indexes for subList modification tests:
|
|
// 0 1 2 3 4 5 6
|
|
// a, b, c, d, e, f, g
|
|
// c, d, e
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListGet(String label, int mode, List<String> list, List<String> base) {
|
|
var sub = applyMode(mode, list);
|
|
assertEquals(sub.getFirst(), isReversed(mode) ? "e" : "c");
|
|
assertEquals(sub.getLast(), isReversed(mode) ? "c" : "e");
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListAddFirst(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
refList.add(isReversed(mode) ? 5 : 2, "x");
|
|
sub.addFirst("x");
|
|
refSub.add(0, "x");
|
|
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListAddLast(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
refList.add(isReversed(mode) ? 2 : 5, "x");
|
|
sub.addLast("x");
|
|
refSub.add("x");
|
|
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListRemoveFirst(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
refList.remove(isReversed(mode) ? 4 : 2);
|
|
var act = sub.removeFirst();
|
|
var exp = refSub.remove(0);
|
|
|
|
assertEquals(act, exp);
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListRemoveLast(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
refList.remove(isReversed(mode) ? 2 : 4);
|
|
var act = sub.removeLast();
|
|
var exp = refSub.remove(refSub.size() - 1);
|
|
|
|
assertEquals(act, exp);
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListAddAllFirst(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
if (isReversed(mode))
|
|
refList.addAll(5, List.of("y", "x"));
|
|
else
|
|
refList.addAll(2, List.of("x", "y"));
|
|
sub.addAll(0, List.of("x", "y"));
|
|
refSub.addAll(0, List.of("x", "y"));
|
|
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListMods")
|
|
public void testSubListAddAllLast(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
if (isReversed(mode))
|
|
refList.addAll(2, List.of("y", "x"));
|
|
else
|
|
refList.addAll(5, List.of("x", "y"));
|
|
sub.addAll(List.of("x", "y"));
|
|
refSub.addAll(List.of("x", "y"));
|
|
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="iteratorMods")
|
|
public void testListIteratorAdd(String label, boolean rev, List<String> list, List<String> base) {
|
|
var ref = new ArrayList<>(base);
|
|
var it = (rev ? list.reversed() : list).listIterator();
|
|
|
|
ref.add(rev ? 5 : 2, "x");
|
|
it.next();
|
|
it.next();
|
|
it.add("x");
|
|
|
|
assertEquals(it.next(), rev ? "e" : "c");
|
|
checkContents(list, ref);
|
|
}
|
|
|
|
@Test(dataProvider="iteratorMods")
|
|
public void testListIteratorSet(String label, boolean rev, List<String> list, List<String> base) {
|
|
var ref = new ArrayList<>(base);
|
|
var it = (rev ? list.reversed() : list).listIterator();
|
|
|
|
ref.set(rev ? 5 : 1, "x");
|
|
it.next();
|
|
it.next();
|
|
it.set("x");
|
|
|
|
assertEquals(it.next(), rev ? "e" : "c");
|
|
checkContents(list, ref);
|
|
}
|
|
|
|
@Test(dataProvider="iteratorMods")
|
|
public void testListIteratorRemove(String label, boolean rev, List<String> list, List<String> base) {
|
|
var ref = new ArrayList<>(base);
|
|
var it = (rev ? list.reversed() : list).listIterator();
|
|
|
|
ref.remove(rev ? 5 : 1);
|
|
it.next();
|
|
it.next();
|
|
it.remove();
|
|
|
|
assertEquals(it.next(), rev ? "e" : "c");
|
|
checkContents(list, ref);
|
|
}
|
|
|
|
// SubList ListIterator modification tests.
|
|
|
|
@Test(dataProvider="subListIteratorMods")
|
|
public void testSubListIteratorAdd(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
var it = sub.listIterator();
|
|
it.next();
|
|
it.add("x");
|
|
refList.add(isReversed(mode) ? 4 : 3, "x");
|
|
refSub.add(1, "x");
|
|
|
|
assertEquals(it.next(), "d");
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListIteratorMods")
|
|
public void testSubListIteratorSet(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
var it = sub.listIterator();
|
|
it.next();
|
|
it.set("x");
|
|
refList.set(isReversed(mode) ? 4 : 2, "x");
|
|
refSub.set(0, "x");
|
|
|
|
assertEquals(it.next(), "d");
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
|
|
@Test(dataProvider="subListIteratorMods")
|
|
public void testSubListIteratorRemove(String label, int mode, List<String> list, List<String> base) {
|
|
var refList = new ArrayList<>(base);
|
|
var sub = applyMode(mode, list);
|
|
var refSub = new ArrayList<>(sub);
|
|
|
|
var it = sub.listIterator();
|
|
it.next();
|
|
it.remove();
|
|
refList.remove(isReversed(mode) ? 4 : 2);
|
|
refSub.remove(0);
|
|
|
|
assertEquals(it.next(), "d");
|
|
checkContents(sub, refSub);
|
|
checkContents(list, refList);
|
|
}
|
|
}
|