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);
|
||||
}
|
||||
}
|
||||
966
test/jdk/java/util/SequencedCollection/BasicMap.java
Normal file
966
test/jdk/java/util/SequencedCollection/BasicMap.java
Normal file
|
|
@ -0,0 +1,966 @@
|
|||
/*
|
||||
* 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 org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertSame;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8266571
|
||||
* @summary Basic tests for SequencedMap
|
||||
* @modules java.base/java.util:open
|
||||
* @build SimpleSortedMap
|
||||
* @run testng BasicMap
|
||||
*/
|
||||
|
||||
public class BasicMap {
|
||||
|
||||
// ========== Data Providers ==========
|
||||
|
||||
static final Class<? extends Throwable> CCE = ClassCastException.class;
|
||||
static final Class<? extends Throwable> NSEE = NoSuchElementException.class;
|
||||
static final Class<? extends Throwable> UOE = UnsupportedOperationException.class;
|
||||
|
||||
static final List<Map.Entry<String, Integer>> ORIGINAL =
|
||||
List.of(Map.entry("a", 1),
|
||||
Map.entry("b", 2),
|
||||
Map.entry("c", 3),
|
||||
Map.entry("d", 4),
|
||||
Map.entry("e", 5));
|
||||
|
||||
static <M extends SequencedMap<String, Integer>>
|
||||
M load(M map, List<Map.Entry<String, Integer>> mappings) {
|
||||
for (var e : mappings)
|
||||
map.put(e.getKey(), e.getValue());
|
||||
return map;
|
||||
}
|
||||
|
||||
static NavigableMap<String, Integer> cknav(NavigableMap<String, Integer> map) {
|
||||
return Collections.checkedNavigableMap(map, String.class, Integer.class);
|
||||
}
|
||||
|
||||
static SortedMap<String, Integer> cksorted(SortedMap<String, Integer> map) {
|
||||
return Collections.checkedSortedMap(map, String.class, Integer.class);
|
||||
}
|
||||
|
||||
static SequencedMap<String, Integer> umap(SequencedMap<String, Integer> map) {
|
||||
return Collections.unmodifiableSequencedMap(map);
|
||||
}
|
||||
|
||||
static SortedMap<String, Integer> usorted(SortedMap<String, Integer> map) {
|
||||
return Collections.unmodifiableSortedMap(map);
|
||||
}
|
||||
|
||||
static NavigableMap<String, Integer> unav(NavigableMap<String, Integer> map) {
|
||||
return Collections.unmodifiableNavigableMap(map);
|
||||
}
|
||||
|
||||
@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[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "SimpleSortedMap", load(new SimpleSortedMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", load(new TreeMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "UnmodMap", umap(load(new LinkedHashMap<>(), ORIGINAL)), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="empties")
|
||||
public Iterator<Object[]> empties() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "EmptyNavigableMap", Collections.emptyNavigableMap(), List.of() },
|
||||
new Object[] { "EmptySortedMap", Collections.emptySortedMap(), List.of() },
|
||||
new Object[] { "LinkedHashMap", new LinkedHashMap<>(), List.of() },
|
||||
new Object[] { "SimpleSortedMap", new SimpleSortedMap<>(), List.of() },
|
||||
new Object[] { "TreeMap", new TreeMap<>(), List.of() },
|
||||
new Object[] { "UnmodMap", umap(new LinkedHashMap<>()), List.of() }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="polls")
|
||||
public Iterator<Object[]> polls() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "SimpleSortedMap", load(new SimpleSortedMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", load(new TreeMap<>(), ORIGINAL), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="emptyPolls")
|
||||
public Iterator<Object[]> emptyPolls() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", new LinkedHashMap<>(), List.of() },
|
||||
new Object[] { "SimpleSortedMap", new SimpleSortedMap<>(), List.of() },
|
||||
new Object[] { "TreeMap", new TreeMap<>(), List.of() }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="puts")
|
||||
public Iterator<Object[]> puts() {
|
||||
return Arrays.<Object[]>asList(
|
||||
new Object[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="putUnpositioned")
|
||||
public Iterator<Object[]> putUnpositioned() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", false, load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "LinkedHashMap", true, load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="putThrows")
|
||||
public Iterator<Object[]> putThrows() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "SimpleSortedMap", load(new SimpleSortedMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", load(new TreeMap<>(), ORIGINAL), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="serializable")
|
||||
public Iterator<Object[]> serializable() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", load(new TreeMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "UnmodMap", umap(load(new LinkedHashMap<>(), ORIGINAL)), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="notSerializable")
|
||||
public Iterator<Object[]> notSerializable() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL).reversed() },
|
||||
new Object[] { "UnmodMap", umap(load(new LinkedHashMap<>(), ORIGINAL)).reversed() }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="doubleReverse")
|
||||
public Iterator<Object[]> doubleReverse() {
|
||||
return Arrays.<Object[]>asList(
|
||||
new Object[] { "LinkedHashMap", load(new LinkedHashMap<>(), ORIGINAL) }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="unmodifiable")
|
||||
public Iterator<Object[]> unmodifible() {
|
||||
return Arrays.<Object[]>asList(
|
||||
new Object[] { "UnmodMap", umap(load(new LinkedHashMap<>(), ORIGINAL)), ORIGINAL },
|
||||
new Object[] { "UnmodNav", unav(load(new TreeMap<>(), ORIGINAL)), ORIGINAL },
|
||||
new Object[] { "UnmodSorted", usorted(load(new TreeMap<>(), ORIGINAL)), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="checked")
|
||||
public Iterator<Object[]> checked() {
|
||||
return Arrays.<Object[]>asList(
|
||||
new Object[] { "ChkNav", cknav(load(new TreeMap<>(), ORIGINAL)), ORIGINAL },
|
||||
new Object[] { "ChkSorted", cksorted(load(new TreeMap<>(), ORIGINAL)), ORIGINAL }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
// mode bit tests
|
||||
|
||||
boolean reverseMap(int mode) { return (mode & 1) != 0; }
|
||||
boolean reverseView(int mode) { return (mode & 2) != 0; }
|
||||
boolean callLast(int mode) { return (mode & 4) != 0; }
|
||||
|
||||
boolean refLast(int mode) { return reverseMap(mode) ^ reverseView(mode) ^ callLast(mode); }
|
||||
|
||||
/**
|
||||
* Generate cases for testing the removeFirst and removeLast methods of map views. For each
|
||||
* different map implementation, generate 8 cases from the three bits of the testing mode
|
||||
* int value:
|
||||
*
|
||||
* (bit 1) if true, the backing map is reversed
|
||||
* (bit 2) if true, the view is reversed
|
||||
* (bit 4) if true, the last element of the view is to be removed, otherwise the first
|
||||
*
|
||||
* The three bits XORed together (by refLast(), above) indicate (if true) the last
|
||||
* or (if false) the first element of the reference entry list is to be removed.
|
||||
*
|
||||
* @return the generated cases
|
||||
*/
|
||||
@DataProvider(name="viewRemoves")
|
||||
public Iterator<Object[]> viewRemoves() {
|
||||
var cases = new ArrayList<Object[]>();
|
||||
for (int mode = 0; mode < 8; mode++) {
|
||||
cases.addAll(Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", mode, load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "SimpleSortedMap", mode, load(new SimpleSortedMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", mode, load(new TreeMap<>(), ORIGINAL), ORIGINAL }
|
||||
));
|
||||
}
|
||||
return cases.iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="emptyViewRemoves")
|
||||
public Iterator<Object[]> emptyViewRemoves() {
|
||||
var cases = new ArrayList<Object[]>();
|
||||
for (int mode = 0; mode < 8; mode++) {
|
||||
cases.addAll(Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", mode, new LinkedHashMap<>(), List.of() },
|
||||
new Object[] { "SimpleSortedMap", mode, new SimpleSortedMap<>(), List.of() },
|
||||
new Object[] { "TreeMap", mode, new TreeMap<>(), List.of() }
|
||||
));
|
||||
}
|
||||
return cases.iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="viewAddThrows")
|
||||
public Iterator<Object[]> viewAddThrows() {
|
||||
var cases = new ArrayList<Object[]>();
|
||||
for (int mode = 0; mode < 8; mode++) {
|
||||
cases.addAll(Arrays.asList(
|
||||
new Object[] { "LinkedHashMap", mode, load(new LinkedHashMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "SimpleSortedMap", mode, load(new SimpleSortedMap<>(), ORIGINAL), ORIGINAL },
|
||||
new Object[] { "TreeMap", mode, load(new TreeMap<>(), ORIGINAL), ORIGINAL }
|
||||
));
|
||||
}
|
||||
return cases.iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nullableEntries")
|
||||
public Iterator<Object[]> nullableEntries() {
|
||||
return Arrays.asList(
|
||||
new Object[] { "firstEntry" },
|
||||
new Object[] { "lastEntry" },
|
||||
new Object[] { "pollFirstEntry" },
|
||||
new Object[] { "pollLastEntry" }
|
||||
).iterator();
|
||||
}
|
||||
|
||||
// ========== Assertions ==========
|
||||
|
||||
/**
|
||||
* Basic checks over the contents of a SequencedMap, compared to a reference List of entries,
|
||||
* in one direction.
|
||||
*
|
||||
* @param map the SequencedMap under test
|
||||
* @param ref the reference list of entries
|
||||
*/
|
||||
public void checkContents1(SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
var list1 = new ArrayList<Map.Entry<String, Integer>>();
|
||||
map.forEach((k, v) -> list1.add(Map.entry(k, v)));
|
||||
assertEquals(list1, ref);
|
||||
|
||||
assertEquals(map.size(), ref.size());
|
||||
assertEquals(map.isEmpty(), ref.isEmpty());
|
||||
|
||||
for (var e : ref) {
|
||||
assertTrue(map.containsKey(e.getKey()));
|
||||
assertTrue(map.containsValue(e.getValue()));
|
||||
assertEquals(map.get(e.getKey()), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void checkContents(SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
checkContents1(map, ref);
|
||||
|
||||
var rref = new ArrayList<>(ref);
|
||||
Collections.reverse(rref);
|
||||
var rmap = map.reversed();
|
||||
checkContents1(rmap, rref);
|
||||
|
||||
var rrmap = rmap.reversed();
|
||||
checkContents1(rrmap, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the entrySet, keySet, or values view of a SequencedMap in one direction. The view
|
||||
* collection is ordered even though the collection type is not sequenced.
|
||||
*
|
||||
* @param <T> the element type of the view
|
||||
* @param mapView the actual map view
|
||||
* @param expElements list of the expected elements
|
||||
*/
|
||||
public <T> void checkView1(Collection<T> mapView, List<T> expElements) {
|
||||
var list1 = new ArrayList<T>();
|
||||
for (var k : mapView)
|
||||
list1.add(k);
|
||||
assertEquals(list1, expElements);
|
||||
|
||||
var list2 = new ArrayList<T>();
|
||||
mapView.forEach(list2::add);
|
||||
assertEquals(list2, expElements);
|
||||
|
||||
var list3 = Arrays.asList(mapView.toArray());
|
||||
assertEquals(list3, expElements);
|
||||
|
||||
var list4 = Arrays.asList(mapView.toArray(new Object[0]));
|
||||
assertEquals(list4, expElements);
|
||||
|
||||
var list5 = Arrays.asList(mapView.toArray(Object[]::new));
|
||||
assertEquals(list5, expElements);
|
||||
|
||||
var list6 = mapView.stream().toList();
|
||||
assertEquals(list6, expElements);
|
||||
|
||||
var list7 = mapView.parallelStream().toList();
|
||||
assertEquals(list7, expElements);
|
||||
|
||||
assertEquals(mapView.size(), expElements.size());
|
||||
assertEquals(mapView.isEmpty(), expElements.isEmpty());
|
||||
|
||||
for (var k : expElements) {
|
||||
assertTrue(mapView.contains(k));
|
||||
}
|
||||
|
||||
var it = mapView.iterator();
|
||||
if (expElements.isEmpty()) {
|
||||
assertFalse(it.hasNext());
|
||||
} else {
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(it.next(), expElements.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the sequenced entrySet, keySet, or values view of a SequencedMap in one direction.
|
||||
*
|
||||
* @param <T> the element type of the view
|
||||
* @param mapView the actual map view
|
||||
* @param expElements list of the expected elements
|
||||
*/
|
||||
public <T> void checkSeqView1(SequencedCollection<T> mapView, List<T> expElements) {
|
||||
checkView1(mapView, expElements);
|
||||
|
||||
if (expElements.isEmpty()) {
|
||||
assertThrows(NoSuchElementException.class, () -> mapView.getFirst());
|
||||
assertThrows(NoSuchElementException.class, () -> mapView.getLast());
|
||||
} else {
|
||||
assertEquals(mapView.getFirst(), expElements.get(0));
|
||||
assertEquals(mapView.getLast(), expElements.get(expElements.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the keySet and sequencedKeySet views of a map. It's possible to unify this with
|
||||
* the corresponding checks for values and entrySet views, but doing this adds a bunch
|
||||
* of generics and method references that tend to obscure more than they help.
|
||||
*
|
||||
* @param map the SequencedMap under test
|
||||
* @param refEntries expected contents of the map
|
||||
*/
|
||||
public void checkKeySet(SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> refEntries) {
|
||||
List<String> refKeys = refEntries.stream().map(Map.Entry::getKey).toList();
|
||||
List<String> rrefKeys = new ArrayList<>(refKeys);
|
||||
Collections.reverse(rrefKeys);
|
||||
SequencedMap<String, Integer> rmap = map.reversed();
|
||||
|
||||
checkView1(map.keySet(), refKeys);
|
||||
checkSeqView1(map.sequencedKeySet(), refKeys);
|
||||
checkSeqView1(map.sequencedKeySet().reversed(), rrefKeys);
|
||||
|
||||
checkView1(rmap.keySet(), rrefKeys);
|
||||
checkSeqView1(rmap.sequencedKeySet(), rrefKeys);
|
||||
checkSeqView1(rmap.sequencedKeySet().reversed(), refKeys);
|
||||
|
||||
checkView1(rmap.reversed().keySet(), refKeys);
|
||||
checkSeqView1(rmap.reversed().sequencedKeySet(), refKeys);
|
||||
checkSeqView1(rmap.reversed().sequencedKeySet().reversed(), rrefKeys);
|
||||
|
||||
assertEquals(map.keySet().hashCode(), rmap.keySet().hashCode());
|
||||
assertEquals(map.keySet().hashCode(), map.sequencedKeySet().hashCode());
|
||||
assertEquals(rmap.keySet().hashCode(), rmap.sequencedKeySet().hashCode());
|
||||
|
||||
// Don't use assertEquals(), as we really want to test the equals() methods.
|
||||
assertTrue(map.keySet().equals(map.sequencedKeySet()));
|
||||
assertTrue(map.sequencedKeySet().equals(map.keySet()));
|
||||
assertTrue(rmap.keySet().equals(map.sequencedKeySet()));
|
||||
assertTrue(rmap.sequencedKeySet().equals(map.keySet()));
|
||||
assertTrue(map.keySet().equals(rmap.sequencedKeySet()));
|
||||
assertTrue(map.sequencedKeySet().equals(rmap.keySet()));
|
||||
assertTrue(rmap.keySet().equals(rmap.sequencedKeySet()));
|
||||
assertTrue(rmap.sequencedKeySet().equals(rmap.keySet()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the values and sequencedValues views of a map.
|
||||
*
|
||||
* @param map the SequencedMap under test
|
||||
* @param refEntries expected contents of the map
|
||||
*/
|
||||
public void checkValues(SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> refEntries) {
|
||||
List<Integer> refValues = refEntries.stream().map(Map.Entry::getValue).toList();
|
||||
List<Integer> rrefValues = new ArrayList<>(refValues);
|
||||
Collections.reverse(rrefValues);
|
||||
SequencedMap<String, Integer> rmap = map.reversed();
|
||||
|
||||
checkView1(map.values(), refValues);
|
||||
checkSeqView1(map.sequencedValues(), refValues);
|
||||
checkSeqView1(map.sequencedValues().reversed(), rrefValues);
|
||||
|
||||
checkView1(rmap.values(), rrefValues);
|
||||
checkSeqView1(rmap.sequencedValues(), rrefValues);
|
||||
checkSeqView1(rmap.sequencedValues().reversed(), refValues);
|
||||
|
||||
checkView1(rmap.reversed().values(), refValues);
|
||||
checkSeqView1(rmap.reversed().sequencedValues(), refValues);
|
||||
checkSeqView1(rmap.reversed().sequencedValues().reversed(), rrefValues);
|
||||
|
||||
// No assertions over hashCode(), as Collection inherits Object.hashCode
|
||||
// which is usually but not guaranteed to give unequal results.
|
||||
|
||||
// It's permissible for an implementation to return the same instance for values()
|
||||
// as for sequencedValues(). Either they're the same instance, or they must be
|
||||
// unequal, because distinct collections should always be unequal.
|
||||
|
||||
var v = map.values();
|
||||
var sv = map.sequencedValues();
|
||||
assertTrue((v == sv) || ! (v.equals(sv) || sv.equals(v)));
|
||||
|
||||
var rv = rmap.values();
|
||||
var rsv = rmap.sequencedValues();
|
||||
assertTrue((rv == rsv) || ! (rv.equals(rsv) || rsv.equals(rv)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the entrySet and sequencedEntrySet views of a map.
|
||||
*
|
||||
* @param map the SequencedMap under test
|
||||
* @param refEntries expected contents of the map
|
||||
*/
|
||||
public void checkEntrySet(SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> refEntries) {
|
||||
List<Map.Entry<String, Integer>> rref = new ArrayList<>(refEntries);
|
||||
Collections.reverse(rref);
|
||||
SequencedMap<String, Integer> rmap = map.reversed();
|
||||
|
||||
checkView1(map.entrySet(), refEntries);
|
||||
checkSeqView1(map.sequencedEntrySet(), refEntries);
|
||||
checkSeqView1(map.sequencedEntrySet().reversed(), rref);
|
||||
|
||||
checkView1(rmap.entrySet(), rref);
|
||||
checkSeqView1(rmap.sequencedEntrySet(), rref);
|
||||
checkSeqView1(rmap.sequencedEntrySet().reversed(), refEntries);
|
||||
|
||||
checkView1(rmap.reversed().entrySet(), refEntries);
|
||||
checkSeqView1(rmap.reversed().sequencedEntrySet(), refEntries);
|
||||
checkSeqView1(rmap.reversed().sequencedEntrySet().reversed(), rref);
|
||||
|
||||
assertEquals(map.entrySet().hashCode(), rmap.entrySet().hashCode());
|
||||
assertEquals(map.entrySet().hashCode(), map.sequencedEntrySet().hashCode());
|
||||
assertEquals(map.sequencedEntrySet().hashCode(), map.entrySet().hashCode());
|
||||
|
||||
assertTrue(map.entrySet().equals(map.sequencedEntrySet()));
|
||||
assertTrue(map.sequencedEntrySet().equals(map.entrySet()));
|
||||
assertTrue(rmap.entrySet().equals(map.sequencedEntrySet()));
|
||||
assertTrue(rmap.sequencedEntrySet().equals(map.entrySet()));
|
||||
assertTrue(map.entrySet().equals(rmap.sequencedEntrySet()));
|
||||
assertTrue(map.sequencedEntrySet().equals(rmap.entrySet()));
|
||||
assertTrue(rmap.entrySet().equals(rmap.sequencedEntrySet()));
|
||||
assertTrue(rmap.sequencedEntrySet().equals(rmap.entrySet()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test attempted modifications to unmodifiable map views. The only mutating operation
|
||||
* map views can support is removal.
|
||||
*
|
||||
* @param <T> element type of the map view
|
||||
* @param view the map view
|
||||
*/
|
||||
public <T> void checkUnmodifiableView(Collection<T> view) {
|
||||
assertThrows(UOE, () -> view.clear());
|
||||
assertThrows(UOE, () -> { var it = view.iterator(); it.next(); it.remove(); });
|
||||
assertThrows(UOE, () -> { var t = view.iterator().next(); view.remove(t); });
|
||||
|
||||
// TODO these ops should throw unconditionally, but they don't in some implementations
|
||||
// assertThrows(UOE, () -> view.removeAll(List.of()));
|
||||
// assertThrows(UOE, () -> view.removeIf(x -> false));
|
||||
// assertThrows(UOE, () -> view.retainAll(view));
|
||||
assertThrows(UOE, () -> view.removeAll(view));
|
||||
assertThrows(UOE, () -> view.removeIf(x -> true));
|
||||
assertThrows(UOE, () -> view.retainAll(List.of()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test removal methods on unmodifiable sequenced map views.
|
||||
*
|
||||
* @param <T> element type of the map view
|
||||
* @param view the map view
|
||||
*/
|
||||
public <T> void checkUnmodifiableSeqView(SequencedCollection<T> view) {
|
||||
checkUnmodifiableView(view);
|
||||
assertThrows(UOE, () -> view.removeFirst());
|
||||
assertThrows(UOE, () -> view.removeLast());
|
||||
|
||||
var rview = view.reversed();
|
||||
checkUnmodifiableView(rview);
|
||||
assertThrows(UOE, () -> rview.removeFirst());
|
||||
assertThrows(UOE, () -> rview.removeLast());
|
||||
}
|
||||
|
||||
public void checkUnmodifiableEntry(SequencedMap<String, Integer> map) {
|
||||
assertThrows(UOE, () -> { map.firstEntry().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.lastEntry().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.sequencedEntrySet().getFirst().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.sequencedEntrySet().getLast().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.sequencedEntrySet().reversed().getFirst().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.sequencedEntrySet().reversed().getLast().setValue(99); });
|
||||
}
|
||||
|
||||
public void checkUnmodifiable1(SequencedMap<String, Integer> map) {
|
||||
assertThrows(UOE, () -> map.putFirst("x", 99));
|
||||
assertThrows(UOE, () -> map.putLast("x", 99));
|
||||
assertThrows(UOE, () -> { map.pollFirstEntry(); });
|
||||
assertThrows(UOE, () -> { map.pollLastEntry(); });
|
||||
|
||||
checkUnmodifiableEntry(map);
|
||||
checkUnmodifiableView(map.keySet());
|
||||
checkUnmodifiableView(map.values());
|
||||
checkUnmodifiableView(map.entrySet());
|
||||
checkUnmodifiableSeqView(map.sequencedKeySet());
|
||||
checkUnmodifiableSeqView(map.sequencedValues());
|
||||
checkUnmodifiableSeqView(map.sequencedEntrySet());
|
||||
}
|
||||
|
||||
public void checkUnmodifiable(SequencedMap<String, Integer> map) {
|
||||
checkUnmodifiable1(map);
|
||||
checkUnmodifiable1(map.reversed());
|
||||
}
|
||||
|
||||
// The putFirst/putLast operations aren't tested here, because the only instances of
|
||||
// checked, sequenced maps are SortedMap and NavigableMap, which don't support them.
|
||||
public void checkChecked(SequencedMap<String, Integer> map) {
|
||||
SequencedMap<Object, Object> objMap = (SequencedMap<Object, Object>)(SequencedMap)map;
|
||||
assertThrows(CCE, () -> { objMap.put(new Object(), 99); });
|
||||
assertThrows(CCE, () -> { objMap.put("x", new Object()); });
|
||||
assertThrows(CCE, () -> { objMap.sequencedEntrySet().iterator().next().setValue(new Object()); });
|
||||
assertThrows(CCE, () -> { objMap.sequencedEntrySet().reversed().iterator().next().setValue(new Object()); });
|
||||
assertThrows(CCE, () -> { objMap.reversed().put(new Object(), 99); });
|
||||
assertThrows(CCE, () -> { objMap.reversed().put("x", new Object()); });
|
||||
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().iterator().next().setValue(new Object()); });
|
||||
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().reversed().iterator().next().setValue(new Object()); });
|
||||
}
|
||||
|
||||
public void checkEntry(Map.Entry<String, Integer> entry, String key, Integer value) {
|
||||
assertEquals(entry.getKey(), key);
|
||||
assertEquals(entry.getValue(), value);
|
||||
}
|
||||
|
||||
// ========== Tests ==========
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void testFundamentals(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
checkContents(map, ref);
|
||||
checkEntrySet(map, ref);
|
||||
checkKeySet(map, ref);
|
||||
checkValues(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="populated")
|
||||
public void testFirstEntry(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertEquals(map.firstEntry(), ref.get(0));
|
||||
assertEquals(map.reversed().firstEntry(), ref.get(ref.size() - 1));
|
||||
assertThrows(UOE, () -> { map.firstEntry().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.reversed().firstEntry().setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="populated")
|
||||
public void testLastEntry(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertEquals(map.lastEntry(), ref.get(ref.size() - 1));
|
||||
assertEquals(map.reversed().lastEntry(), ref.get(0));
|
||||
assertThrows(UOE, () -> { map.lastEntry().setValue(99); });
|
||||
assertThrows(UOE, () -> { map.reversed().lastEntry().setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="empties")
|
||||
public void testEmptyFirstEntry(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertNull(map.firstEntry());
|
||||
assertNull(map.reversed().firstEntry());
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="empties")
|
||||
public void testEmptyLastEntry(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertNull(map.lastEntry());
|
||||
assertNull(map.reversed().lastEntry());
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="puts")
|
||||
public void testPutFirst(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(0, Map.entry("x", 99));
|
||||
map.putFirst("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="puts")
|
||||
public void testPutFirstRev(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
map.reversed().putFirst("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="puts")
|
||||
public void testPutLast(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
map.putLast("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="puts")
|
||||
public void testPutLastRev(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(0, Map.entry("x", 99));
|
||||
map.reversed().putLast("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposPut(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).put("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposPutAll(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).putAll(Map.of("x", 99));
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposPutIfAbsent(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).putIfAbsent("x", 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposCompute(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).compute("x", (k, v) -> 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposComputeIfAbsent(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).computeIfAbsent("x", k -> 99);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putUnpositioned")
|
||||
public void testUnposMerge(String label, boolean rev, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
ref.add(Map.entry("x", 99));
|
||||
(rev ? map.reversed() : map).merge("x", 99, /*unused*/ (k, v) -> -1);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="putThrows")
|
||||
public void testPutThrows(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
assertThrows(UOE, () -> map.putFirst("x", 99));
|
||||
assertThrows(UOE, () -> map.putLast("x", 99));
|
||||
assertThrows(UOE, () -> map.reversed().putFirst("x", 99));
|
||||
assertThrows(UOE, () -> map.reversed().putLast("x", 99));
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="polls")
|
||||
public void testPollFirst(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var act = map.pollFirstEntry();
|
||||
assertEquals(act, ref.remove(0));
|
||||
assertThrows(UOE, () -> { act.setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="polls")
|
||||
public void testPollFirstRev(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var act = map.reversed().pollFirstEntry();
|
||||
assertEquals(act, ref.remove(ref.size() - 1));
|
||||
assertThrows(UOE, () -> { act.setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="polls")
|
||||
public void testPollLast(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var act = map.pollLastEntry();
|
||||
assertEquals(act, ref.remove(ref.size() - 1));
|
||||
assertThrows(UOE, () -> { act.setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="polls")
|
||||
public void testPollLastRev(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var act = map.reversed().pollLastEntry();
|
||||
assertEquals(act, ref.remove(0));
|
||||
assertThrows(UOE, () -> { act.setValue(99); });
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="emptyPolls")
|
||||
public void testEmptyPollFirst(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertNull(map.pollFirstEntry());
|
||||
assertNull(map.reversed().pollFirstEntry());
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="emptyPolls")
|
||||
public void testEmptyPollLast(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
assertNull(map.pollLastEntry());
|
||||
assertNull(map.reversed().pollLastEntry());
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="serializable")
|
||||
public void testSerializable(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref)
|
||||
throws ClassNotFoundException, IOException
|
||||
{
|
||||
var baos = new ByteArrayOutputStream();
|
||||
try (var oos = new ObjectOutputStream(baos)) {
|
||||
oos.writeObject(map);
|
||||
}
|
||||
|
||||
try (var bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
var ois = new ObjectInputStream(bais)) {
|
||||
var map2 = (SequencedMap<String, Integer>) ois.readObject();
|
||||
checkContents(map2, ref);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider="notSerializable")
|
||||
public void testNotSerializable(String label, SequencedMap<String, Integer> map)
|
||||
throws ClassNotFoundException, IOException
|
||||
{
|
||||
var baos = new ByteArrayOutputStream();
|
||||
try (var oos = new ObjectOutputStream(baos)) {
|
||||
assertThrows(ObjectStreamException.class, () -> oos.writeObject(map));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider="doubleReverse")
|
||||
public void testDoubleReverse(String label, SequencedMap<String, Integer> map) {
|
||||
var rrmap = map.reversed().reversed();
|
||||
assertSame(rrmap, map);
|
||||
}
|
||||
|
||||
@Test(dataProvider="unmodifiable")
|
||||
public void testUnmodifiable(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
checkUnmodifiable(map);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="checked")
|
||||
public void testChecked(String label, SequencedMap<String, Integer> map, List<Map.Entry<String, Integer>> ref) {
|
||||
checkChecked(map);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a removal from the sequenedKeySet view is properly reflected in the original
|
||||
* backing map. The mode value indicates whether the backing map is reversed, whether the
|
||||
* sequencedKeySet view is reversed, and whether the removeFirst or removeLast is called
|
||||
* on the view. See the viewRemoves() dataProvider for details.
|
||||
*
|
||||
* @param label the implementation label
|
||||
* @param mode reversed and first/last modes
|
||||
* @param map the original map instance
|
||||
* @param baseref reference contents of the original map
|
||||
*/
|
||||
@Test(dataProvider="viewRemoves")
|
||||
public void testKeySetRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var exp = (refLast(mode) ? ref.remove(ref.size() - 1) : ref.remove(0)).getKey();
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var keySet = reverseView(mode) ? tempmap.sequencedKeySet().reversed() : tempmap.sequencedKeySet();
|
||||
var act = callLast(mode) ? keySet.removeLast() : keySet.removeFirst();
|
||||
assertEquals(act, exp);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedValues view.
|
||||
@Test(dataProvider="viewRemoves")
|
||||
public void testValuesRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var exp = (refLast(mode) ? ref.remove(ref.size() - 1) : ref.remove(0)).getValue();
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var values = reverseView(mode) ? tempmap.sequencedValues().reversed() : tempmap.sequencedValues();
|
||||
var act = callLast(mode) ? values.removeLast() : values.removeFirst();
|
||||
assertEquals(act, exp);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedEntrySet view.
|
||||
@Test(dataProvider="viewRemoves")
|
||||
public void testEntrySetRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var ref = new ArrayList<>(baseref);
|
||||
var exp = refLast(mode) ? ref.remove(ref.size() - 1) : ref.remove(0);
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var entrySet = reverseView(mode) ? tempmap.sequencedEntrySet().reversed() : tempmap.sequencedEntrySet();
|
||||
var act = callLast(mode) ? entrySet.removeLast() : entrySet.removeFirst();
|
||||
assertEquals(act, exp);
|
||||
checkContents(map, ref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedKeySet of an empty map.
|
||||
@Test(dataProvider="emptyViewRemoves")
|
||||
public void testEmptyKeySetRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var keySet = reverseView(mode) ? tempmap.sequencedKeySet().reversed() : tempmap.sequencedKeySet();
|
||||
if (callLast(mode))
|
||||
assertThrows(NSEE, () -> keySet.removeLast());
|
||||
else
|
||||
assertThrows(NSEE, () -> keySet.removeFirst());
|
||||
checkContents(map, baseref);
|
||||
|
||||
}
|
||||
|
||||
// As above, but for the sequencedValues view.
|
||||
@Test(dataProvider="emptyViewRemoves")
|
||||
public void testEmptyValuesRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var values = reverseView(mode) ? tempmap.sequencedValues().reversed() : tempmap.sequencedValues();
|
||||
if (callLast(mode))
|
||||
assertThrows(NSEE, () -> values.removeLast());
|
||||
else
|
||||
assertThrows(NSEE, () -> values.removeFirst());
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedEntrySet view.
|
||||
@Test(dataProvider="emptyViewRemoves")
|
||||
public void testEmptyEntrySetRemoves(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var entrySet = reverseView(mode) ? tempmap.sequencedEntrySet().reversed() : tempmap.sequencedEntrySet();
|
||||
if (callLast(mode))
|
||||
assertThrows(NSEE, () -> entrySet.removeLast());
|
||||
else
|
||||
assertThrows(NSEE, () -> entrySet.removeFirst());
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
// Test that addFirst/addLast on the sequencedKeySetView throw UnsupportedOperationException.
|
||||
@Test(dataProvider="viewAddThrows")
|
||||
public void testKeySetAddThrows(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var keySet = reverseView(mode) ? tempmap.sequencedKeySet().reversed() : tempmap.sequencedKeySet();
|
||||
if (callLast(mode))
|
||||
assertThrows(UOE, () -> keySet.addLast("x"));
|
||||
else
|
||||
assertThrows(UOE, () -> keySet.addFirst("x"));
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedValues view.
|
||||
@Test(dataProvider="viewAddThrows")
|
||||
public void testValuesAddThrows(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var values = reverseView(mode) ? tempmap.sequencedValues().reversed() : tempmap.sequencedValues();
|
||||
if (callLast(mode))
|
||||
assertThrows(UOE, () -> values.addLast(99));
|
||||
else
|
||||
assertThrows(UOE, () -> values.addFirst(99));
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
// As above, but for the sequencedEntrySet view.
|
||||
@Test(dataProvider="viewAddThrows")
|
||||
public void testEntrySetAddThrows(String label,
|
||||
int mode,
|
||||
SequencedMap<String, Integer> map,
|
||||
List<Map.Entry<String, Integer>> baseref) {
|
||||
var tempmap = reverseMap(mode) ? map.reversed() : map;
|
||||
var entrySet = reverseView(mode) ? tempmap.sequencedEntrySet().reversed() : tempmap.sequencedEntrySet();
|
||||
if (callLast(mode))
|
||||
assertThrows(UOE, () -> entrySet.addLast(Map.entry("x", 99)));
|
||||
else
|
||||
assertThrows(UOE, () -> entrySet.addFirst(Map.entry("x", 99)));
|
||||
checkContents(map, baseref);
|
||||
}
|
||||
|
||||
@Test(dataProvider="nullableEntries")
|
||||
public void testNullableKeyValue(String mode) {
|
||||
// TODO this relies on LHM to inherit SequencedMap default
|
||||
// methods which are actually being tested here.
|
||||
SequencedMap<String, Integer> map = new LinkedHashMap<>();
|
||||
map.put(null, 1);
|
||||
map.put("two", null);
|
||||
|
||||
switch (mode) {
|
||||
case "firstEntry" -> checkEntry(map.firstEntry(), null, 1);
|
||||
case "lastEntry" -> checkEntry(map.lastEntry(), "two", null);
|
||||
case "pollFirstEntry" -> checkEntry(map.pollFirstEntry(), null, 1);
|
||||
case "pollLastEntry" -> checkEntry(map.pollLastEntry(), "two", null);
|
||||
default -> throw new AssertionError("illegal mode " + mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
200
test/jdk/java/util/SequencedCollection/SimpleDeque.java
Normal file
200
test/jdk/java/util/SequencedCollection/SimpleDeque.java
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* 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.util.*;
|
||||
|
||||
/**
|
||||
* A complete Deque implementation that inherits the reversed() method
|
||||
* from SequencedCollection. Useful for testing ReverseOrderDequeView.
|
||||
* Underlying implementation provided by ArrayDeque.
|
||||
*/
|
||||
public class SimpleDeque<E> implements Deque<E> {
|
||||
|
||||
final Deque<E> deque;
|
||||
|
||||
public SimpleDeque() {
|
||||
deque = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
public SimpleDeque(Collection<? extends E> c) {
|
||||
deque = new ArrayDeque<>(c);
|
||||
}
|
||||
|
||||
// ========== Object ==========
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return deque.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return deque.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return deque.toString();
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
||||
public boolean add(E e) {
|
||||
return deque.add(e);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
return deque.addAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
deque.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return deque.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return deque.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return deque.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return deque.iterator();
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return deque.remove(o);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return deque.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return deque.retainAll(c);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return deque.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return deque.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return deque.toArray(a);
|
||||
}
|
||||
|
||||
// ========== Deque ==========
|
||||
|
||||
public void addFirst(E e) {
|
||||
deque.addFirst(e);
|
||||
}
|
||||
|
||||
public void addLast(E e) {
|
||||
deque.addLast(e);
|
||||
}
|
||||
|
||||
public boolean offerFirst(E e) {
|
||||
return deque.offerFirst(e);
|
||||
}
|
||||
|
||||
public boolean offerLast(E e) {
|
||||
return deque.offerLast(e);
|
||||
}
|
||||
|
||||
public E removeFirst() {
|
||||
return deque.removeFirst();
|
||||
}
|
||||
|
||||
public E removeLast() {
|
||||
return deque.removeLast();
|
||||
}
|
||||
|
||||
public E pollFirst() {
|
||||
return deque.pollFirst();
|
||||
}
|
||||
|
||||
public E pollLast() {
|
||||
return deque.pollLast();
|
||||
}
|
||||
|
||||
public E getFirst() {
|
||||
return deque.getFirst();
|
||||
}
|
||||
|
||||
public E getLast() {
|
||||
return deque.getLast();
|
||||
}
|
||||
|
||||
public E peekFirst() {
|
||||
return deque.peekFirst();
|
||||
}
|
||||
|
||||
public E peekLast() {
|
||||
return deque.peekLast();
|
||||
}
|
||||
|
||||
public boolean removeFirstOccurrence(Object o) {
|
||||
return deque.removeFirstOccurrence(o);
|
||||
}
|
||||
|
||||
public boolean removeLastOccurrence(Object o) {
|
||||
return deque.removeLastOccurrence(o);
|
||||
}
|
||||
|
||||
public boolean offer(E e) {
|
||||
return deque.offer(e);
|
||||
}
|
||||
|
||||
public E remove() {
|
||||
return deque.remove();
|
||||
}
|
||||
|
||||
public E poll() {
|
||||
return deque.poll();
|
||||
}
|
||||
|
||||
public E element() {
|
||||
return deque.element();
|
||||
}
|
||||
|
||||
public E peek() {
|
||||
return deque.peek();
|
||||
}
|
||||
|
||||
public void push(E e) {
|
||||
deque.push(e);
|
||||
}
|
||||
|
||||
public E pop() {
|
||||
return deque.pop();
|
||||
}
|
||||
|
||||
public Iterator<E> descendingIterator() {
|
||||
return deque.descendingIterator();
|
||||
}
|
||||
}
|
||||
152
test/jdk/java/util/SequencedCollection/SimpleList.java
Normal file
152
test/jdk/java/util/SequencedCollection/SimpleList.java
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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.util.*;
|
||||
|
||||
/**
|
||||
* A complete List implementation that inherits the reversed() method
|
||||
* from List. Useful for testing ReverseOrderListView.
|
||||
* Underlying implementation provided by ArrayList.
|
||||
*/
|
||||
public class SimpleList<E> implements List<E> {
|
||||
|
||||
final List<E> list;
|
||||
|
||||
public SimpleList() {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
|
||||
public SimpleList(Collection<? extends E> c) {
|
||||
list = new ArrayList<>(c);
|
||||
}
|
||||
|
||||
// ========== Object ==========
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return list.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return list.toString();
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
||||
public boolean add(E e) {
|
||||
return list.add(e);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
return list.addAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
list.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return list.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return list.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return list.remove(o);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return list.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return list.retainAll(c);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return list.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return list.toArray(a);
|
||||
}
|
||||
|
||||
// ========== List ==========
|
||||
|
||||
public void add(int index, E element) {
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
return list.addAll(index, c);
|
||||
}
|
||||
|
||||
public E get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
public int indexOf(Object o) {
|
||||
return list.indexOf(o);
|
||||
}
|
||||
|
||||
public int lastIndexOf(Object o) {
|
||||
return list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator() {
|
||||
return list.listIterator();
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
return list.listIterator(index);
|
||||
}
|
||||
|
||||
public E remove(int index) {
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
public E set(int index, E element) {
|
||||
return list.set(index, element);
|
||||
}
|
||||
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
return list.subList(fromIndex, toIndex);
|
||||
}
|
||||
}
|
||||
134
test/jdk/java/util/SequencedCollection/SimpleSortedMap.java
Normal file
134
test/jdk/java/util/SequencedCollection/SimpleSortedMap.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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.util.*;
|
||||
|
||||
/**
|
||||
* A SortedMap implementation that does not implement NavigableMap. Useful for
|
||||
* testing ReverseOrderSortedMapView. Underlying implementation provided by TreeMap.
|
||||
*/
|
||||
public class SimpleSortedMap<K,V> implements SortedMap<K,V> {
|
||||
final SortedMap<K,V> map;
|
||||
|
||||
public SimpleSortedMap() {
|
||||
map = new TreeMap<>();
|
||||
}
|
||||
|
||||
public SimpleSortedMap(Comparator<? super K> comparator) {
|
||||
map = new TreeMap<>(comparator);
|
||||
}
|
||||
|
||||
public SimpleSortedMap(Map<? extends K,? extends V> m) {
|
||||
map = new TreeMap<>(m);
|
||||
}
|
||||
|
||||
// ========== Object ==========
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return map.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
// ========== Map ==========
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
public Set<Map.Entry<K,V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K,? extends V> m) {
|
||||
map.putAll(m);
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
// ========== SortedMap ==========
|
||||
|
||||
public Comparator<? super K> comparator() {
|
||||
return map.comparator();
|
||||
}
|
||||
|
||||
public K firstKey() {
|
||||
return map.firstKey();
|
||||
}
|
||||
|
||||
public SortedMap<K,V> headMap(K toKey) {
|
||||
return map.headMap(toKey);
|
||||
}
|
||||
|
||||
public K lastKey() {
|
||||
return map.lastKey();
|
||||
}
|
||||
|
||||
public SortedMap<K,V> subMap(K fromKey, K toKey) {
|
||||
return map.subMap(fromKey, toKey);
|
||||
}
|
||||
|
||||
public SortedMap<K,V> tailMap(K fromKey) {
|
||||
return map.tailMap(fromKey);
|
||||
}
|
||||
}
|
||||
139
test/jdk/java/util/SequencedCollection/SimpleSortedSet.java
Normal file
139
test/jdk/java/util/SequencedCollection/SimpleSortedSet.java
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.util.*;
|
||||
|
||||
/**
|
||||
* A SortedSet implementation that does not implement NavigableSet. Useful for
|
||||
* testing ReverseOrderSortedSetView. Underlying implementation provided by TreeSet.
|
||||
*/
|
||||
public class SimpleSortedSet<E> implements SortedSet<E> {
|
||||
|
||||
final SortedSet<E> set;
|
||||
|
||||
public SimpleSortedSet() {
|
||||
set = new TreeSet<E>();
|
||||
}
|
||||
|
||||
public SimpleSortedSet(Collection<? extends E> c) {
|
||||
set = new TreeSet<>(c);
|
||||
}
|
||||
|
||||
public SimpleSortedSet(Comparator<? super E> comparator) {
|
||||
set = new TreeSet<>(comparator);
|
||||
}
|
||||
|
||||
// ========== Object ==========
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return set.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return set.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return set.toString();
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
||||
public boolean add(E e) {
|
||||
return set.add(e);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
return set.addAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
set.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return set.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return set.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return set.iterator();
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return set.remove(o);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return set.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return set.retainAll(c);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return set.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return set.toArray(a);
|
||||
}
|
||||
|
||||
// ========== SortedSet ==========
|
||||
|
||||
public Comparator<? super E> comparator() {
|
||||
return set.comparator();
|
||||
}
|
||||
|
||||
public E first() {
|
||||
return set.first();
|
||||
}
|
||||
|
||||
public SortedSet<E> headSet(E toElement) {
|
||||
return set.headSet(toElement);
|
||||
}
|
||||
|
||||
public E last() {
|
||||
return set.last();
|
||||
}
|
||||
|
||||
public SortedSet<E> subSet(E fromElement, E toElement) {
|
||||
return set.subSet(fromElement, toElement);
|
||||
}
|
||||
|
||||
public SortedSet<E> tailSet(E fromElement) {
|
||||
return set.tailSet(fromElement);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue