undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
901
test/jdk/java/util/SequencedCollection/Basic.java
Normal file
901
test/jdk/java/util/SequencedCollection/Basic.java
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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.*;
|
||||
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 List<String> sylist(List<String> list) {
|
||||
return Collections.synchronizedList(list);
|
||||
}
|
||||
|
||||
static List<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[] { "SynchList", sylist(new ArrayList<>(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[] { "SynchList", sylist(new ArrayList<>()), 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 },
|
||||
new Object[] { "SynchList", sylist(new ArrayList<>(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[] { "SynchList", sylist(new ArrayList<>(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[] { "SynchList", sylist(new ArrayList<>()), 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[] { "SynchList", sylist(new ArrayList<>(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[] { "SynchList", sylist(new ArrayList<>(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) },
|
||||
new Object[] { "SynchList", sylist(new ArrayList<>(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();
|
||||
}
|
||||
|
||||
// These Lists don't all implement RandomAccess; they're Lists that should be
|
||||
// tested for proper propagation of the RandomAccess markers.
|
||||
@DataProvider(name="randomAccessLists")
|
||||
public Iterator<Object[]> randomAccessLists() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "ArrayList", new ArrayList<>(ORIGINAL) },
|
||||
new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()) },
|
||||
new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL) },
|
||||
new Object[] { "LinkedList", new LinkedList<>(ORIGINAL) },
|
||||
new Object[] { "ListOf", ORIGINAL },
|
||||
new Object[] { "SimpleList", new SimpleList<>(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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSynchListReversedAlwaysReturnsSameObject() {
|
||||
var list = sylist(ORIGINAL);
|
||||
var rev1 = list.reversed();
|
||||
var rev2 = list.reversed();
|
||||
assertSame(rev1, rev2);
|
||||
}
|
||||
|
||||
@Test(dataProvider="randomAccessLists")
|
||||
public void testRandomAccess(String label, List<String> list) {
|
||||
assertEquals(list.reversed() instanceof RandomAccess, list instanceof RandomAccess);
|
||||
|
||||
// Collections.synchronizedList() preservation of RandomAccess is somewhat
|
||||
// tested by java/util/Collection/MOAT.java but it might not have all these cases.
|
||||
assertEquals(sylist(list) instanceof RandomAccess, list instanceof RandomAccess);
|
||||
assertEquals(sylist(list).reversed() instanceof RandomAccess, sylist(list) instanceof RandomAccess);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue