/*
* Copyright 2013 Cameron Beccario
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.nullschool.collect;
import java.util.*;
import static java.util.Collections.reverseOrder;
import static org.junit.Assert.*;
/**
* 2013-03-13<p/>
*
* A set of utility methods that perform generic tests on collections.<p/>
*
* Many of these utility methods perform a side-by-side comparison of two collections. The first {@code expected}
* collection is known to have proper behavior. The second {@code actual} collection is checked to ensure it
* exhibits the same behavior as the {@code expected} collection when a series of operations are applied to both.
*
* @author Cameron Beccario
*/
public class CollectionTestingTools {
private CollectionTestingTools() {
throw new AssertionError();
}
public static final class NullSafeReverseComparator<T> implements Comparator<T> {
@Override public int compare(T left, T right) {
if (left == null) {
return right == null ? 0 : 1;
}
return right == null ? -1 : reverseOrder().compare(left, right);
}
@Override public boolean equals(Object obj) { return obj instanceof NullSafeReverseComparator; }
@Override public int hashCode() { return 1; }
}
private static <E> E nth(Collection<E> c, int n) {
Iterator<E> iter = c.iterator();
int i = 0;
while (i++ < n) {
iter.next();
}
return iter.next();
}
private static <K> K nth(Map<K, ?> m, int n) {
MapIterator<K, ?> iter = IteratorTools.newMapIterator(m);
int i = 0;
while (i++ < n) {
iter.next();
}
return iter.next();
}
@SafeVarargs
public static <T> Set<T> newSet(T... a) {
return new LinkedHashSet<>(Arrays.asList(a));
}
@SafeVarargs
public static <T> SortedSet<T> newSortedSet(Comparator<? super T> comparator, T... a) {
TreeSet<T> set = new TreeSet<>(comparator);
Collections.addAll(set, a);
return set;
}
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> newMap(Object... keysAndValues) {
Map<K, V> map = new LinkedHashMap<>();
for (int i = 0; i < keysAndValues.length; i += 2) {
map.put((K)keysAndValues[i], (V)keysAndValues[i + 1]);
}
return map;
}
@SuppressWarnings("unchecked")
public static <K, V> SortedMap<K, V> newSortedMap(Comparator<? super K> comparator, Object... keysAndValues) {
TreeMap<K, V> map = new TreeMap<>(comparator);
for (int i = 0; i < keysAndValues.length; i += 2) {
map.put((K)keysAndValues[i], (V)keysAndValues[i + 1]);
}
return map;
}
public static <K, V> Map.Entry<K, V> newEntry(K key, V value) {
return new AbstractMap.SimpleImmutableEntry<>(key, value);
}
@SuppressWarnings({"unchecked", "ConstantConditions"})
public static void assert_collection_immutable(Collection c) {
try { c.add(1); fail(); } catch (UnsupportedOperationException | ClassCastException ignored) {}
try { c.add(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.addAll(Arrays.asList(1)); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.addAll(Arrays.asList()); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.addAll(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.remove(1); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.remove(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.removeAll(Arrays.asList(1)); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.removeAll(Arrays.asList()); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.removeAll(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.retainAll(Arrays.asList(1)); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.retainAll(Arrays.asList()); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.retainAll(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { c.clear(); fail(); } catch (UnsupportedOperationException ignored) {}
for (Iterator iter = c.iterator(); iter.hasNext(); iter.next()) {
try { iter.remove(); fail(); } catch (UnsupportedOperationException ignored) {}
}
}
@SuppressWarnings({"unchecked", "ConstantConditions"})
public static void assert_list_immutable(List l) {
assert_collection_immutable(l);
try { l.add(0, 1); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.addAll(0, Arrays.asList(1)); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.addAll(0, Arrays.asList()); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.addAll(0, null); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.set(0, 1); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.set(0, null); fail(); } catch (UnsupportedOperationException ignored) {}
try { l.remove(0); fail(); } catch (UnsupportedOperationException ignored) {}
for (ListIterator iter = l.listIterator(); iter.hasNext(); iter.next()) {
try { iter.add(1); fail(); } catch (UnsupportedOperationException ignored) {}
try { iter.add(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { iter.set(1); fail(); } catch (UnsupportedOperationException ignored) {}
try { iter.set(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { iter.remove(); fail(); } catch (UnsupportedOperationException ignored) {}
}
if (l.size() > 1) {
assert_list_immutable(l.subList(0, l.size() / 2));
}
}
public static void assert_set_immutable(Set s) {
assert_collection_immutable(s);
}
public static <E> void assert_sorted_set_immutable(SortedSet<E> s) {
assert_set_immutable(s);
if (!s.isEmpty()) {
assert_sorted_set_immutable(s.headSet(s.last()));
}
if (s.size() > 1) {
E from = nth(s, 1);
assert_sorted_set_immutable(s.tailSet(from));
assert_sorted_set_immutable(s.subSet(from, s.last()));
}
}
@SuppressWarnings({"unchecked", "ConstantConditions"})
public static void assert_map_immutable(Map m) {
try { m.put("a", 1); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.put(null, null); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.putAll(Collections.emptyMap()); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.putAll(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.remove(1); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.remove(null); fail(); } catch (UnsupportedOperationException ignored) {}
try { m.clear(); fail(); } catch (UnsupportedOperationException ignored) {}
if (m instanceof IterableMap) {
for (MapIterator iter = ((IterableMap)m).iterator(); iter.hasNext(); iter.next()) {
try { iter.remove(); fail(); } catch (UnsupportedOperationException ignored) {}
}
}
assert_set_immutable(m.keySet());
Collection values = m.values();
if (values instanceof List) {
assert_list_immutable((List)values);
}
else {
assert_collection_immutable(values);
}
assert_set_immutable(m.entrySet());
}
public static <K, V> void assert_sorted_map_immutable(SortedMap<K, V> m) {
assert_map_immutable(m);
if (!m.isEmpty()) {
assert_sorted_map_immutable(m.headMap(m.lastKey()));
}
if (m.size() > 1) {
K from = nth(m, 1);
assert_sorted_map_immutable(m.tailMap(from));
assert_sorted_map_immutable(m.subMap(from, m.lastKey()));
}
}
// =================================================================================================================
// collection comparisons
public static void compare_iterators(Iterator<?> expected, Iterator<?> actual) {
try { expected.remove(); fail(); } catch (IllegalStateException | UnsupportedOperationException ignored) {}
try { actual.remove(); fail(); } catch (IllegalStateException | UnsupportedOperationException ignored) {}
while (expected.hasNext()) {
assertTrue(actual.hasNext());
assertEquals(expected.next(), actual.next());
}
assertFalse(actual.hasNext());
try { expected.next(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.next(); fail(); } catch (NoSuchElementException ignored) {}
}
public static void compare_list_iterators(ListIterator<?> expected, ListIterator<?> actual) {
try { expected.remove(); fail(); } catch (IllegalStateException | UnsupportedOperationException ignored) {}
try { actual.remove(); fail(); } catch (IllegalStateException | UnsupportedOperationException ignored) {}
// walk to the end
while (expected.hasNext()) {
assertTrue(actual.hasNext());
assertEquals(expected.nextIndex(), actual.nextIndex());
assertEquals(expected.hasPrevious(), actual.hasPrevious());
assertEquals(expected.previousIndex(), actual.previousIndex());
assertEquals(expected.next(), actual.next());
}
assertFalse(actual.hasNext());
assertEquals(expected.nextIndex(), actual.nextIndex());
assertEquals(expected.hasPrevious(), actual.hasPrevious());
assertEquals(expected.previousIndex(), actual.previousIndex());
try { expected.next(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.next(); fail(); } catch (NoSuchElementException ignored) {}
// walk back to the beginning
while (expected.hasPrevious()) {
assertTrue(actual.hasPrevious());
assertEquals(expected.previousIndex(), actual.previousIndex());
assertEquals(expected.hasNext(), actual.hasNext());
assertEquals(expected.nextIndex(), actual.nextIndex());
assertEquals(expected.previous(), actual.previous());
}
assertFalse(actual.hasPrevious());
assertEquals(expected.previousIndex(), actual.previousIndex());
assertEquals(expected.hasNext(), actual.hasNext());
assertEquals(expected.nextIndex(), actual.nextIndex());
try { expected.previous(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.previous(); fail(); } catch (NoSuchElementException ignored) {}
}
public static void compare_collections(Collection<?> expected, Collection<?> actual) {
assertEquals(expected.size(), actual.size());
assertEquals(expected.isEmpty(), actual.isEmpty());
assertEquals(expected.toString(), actual.toString());
assertArrayEquals(expected.toArray(), actual.toArray());
assertEquals(expected.equals(new Object()), actual.equals(new Object()));
assertEquals(expected.equals(expected), actual.equals(actual));
Object[] expectedArray;
Object[] actualArray;
// Arrays correct size
expectedArray = new Object[expected.size()];
actualArray = new Object[actual.size()];
assertArrayEquals(
expected.toArray(expectedArray),
actual.toArray(actualArray));
// Arrays too big
expectedArray = new Object[expected.size() + 3];
actualArray = new Object[actual.size() + 3];
Arrays.fill(expectedArray, "foo");
Arrays.fill(actualArray, "foo");
assertArrayEquals(
expected.toArray(expectedArray),
actual.toArray(actualArray));
// Arrays too small
expectedArray = new Object[Math.max(0, expected.size() - 1)];
actualArray = new Object[Math.max(0, expected.size() - 1)];
assertArrayEquals(
expected.toArray(expectedArray),
actual.toArray(actualArray));
assertTrue(expected.containsAll(actual));
assertTrue(actual.containsAll(expected));
for (Object item : expected) {
assertTrue(actual.contains(item));
}
Object item = new Object();
try { assertFalse(expected.contains(item)); } catch (ClassCastException ignored) {}
try { assertFalse(actual.contains(item)); } catch (ClassCastException ignored) {}
compare_iterators(expected.iterator(), actual.iterator());
}
public static void compare_lists(List<?> expected, List<?> actual) {
compare_collections(expected, actual);
assertEquals(expected, actual);
assertEquals(actual, expected);
assertEquals(expected.hashCode(), actual.hashCode());
for (int i = 0; i < expected.size(); i++) {
Object expectedItem = expected.get(i);
Object actualItem = actual.get(i);
assertEquals(expectedItem, actualItem);
assertEquals(expected.indexOf(expectedItem), actual.indexOf(actualItem));
assertEquals(expected.lastIndexOf(expectedItem), actual.lastIndexOf(actualItem));
}
try { expected.get(-1); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { actual.get(-1); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { expected.get(expected.size()); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { actual.get(actual.size()); fail(); } catch (IndexOutOfBoundsException ignored) {}
compare_list_iterators(expected.listIterator(), actual.listIterator());
compare_list_iterators(expected.listIterator(expected.size()), actual.listIterator(actual.size()));
try { expected.listIterator(-1); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { actual.listIterator(-1); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { expected.listIterator(expected.size() + 1); fail(); } catch (IndexOutOfBoundsException ignored) {}
try { actual.listIterator(actual.size() + 1); fail(); } catch (IndexOutOfBoundsException ignored) {}
if (expected.size() > 1) {
compare_list_iterators(expected.listIterator(expected.size() / 2), actual.listIterator(actual.size() / 2));
compare_lists(expected.subList(1, expected.size() / 2), actual.subList(1, expected.size() / 2));
}
Object item = new Object();
try { assertEquals(-1, expected.indexOf(item)); } catch (ClassCastException ignored) {}
try { assertEquals(-1, actual.indexOf(item)); } catch (ClassCastException ignored) {}
try { assertEquals(-1, expected.lastIndexOf(item)); } catch (ClassCastException ignored) {}
try { assertEquals(-1, actual.lastIndexOf(item)); } catch (ClassCastException ignored) {}
}
public static void compare_sets(Set<?> expected, Set<?> actual) {
compare_collections(expected, actual);
assertEquals(expected, actual);
assertEquals(actual, expected);
assertEquals(expected.hashCode(), actual.hashCode());
}
@SafeVarargs
private static <E> void compare_ranges(SortedSet<E> expected, SortedSet<E> actual, E... rangePoints) {
// Iterate over points [P0, ..., Pn]. Compare all sub sets described by each pair [Pi-1, Pi].
// For good measure, also compare head and tail sets for each point Pi.
for (int i = 0; i < rangePoints.length; i++) {
E point = rangePoints[i];
compare_sorted_sets(expected.headSet(point), actual.headSet(point));
compare_sorted_sets(expected.tailSet(point), actual.tailSet(point));
if (i > 0) {
E previous = rangePoints[i - 1];
SortedSet<E> expectedSubSet = null;
SortedSet<E> actualSubSet = null;
Exception expectedException = null;
Exception actualException = null;
// Construct subsets from the current point and the previous point. These points might be
// inverted as part of the test. In this case, we expect construction of the subsets to both
// throw the same exception.
try {
expectedSubSet = expected.subSet(previous, point);
}
catch (IllegalArgumentException e) {
expectedException = e;
}
try {
actualSubSet = actual.subSet(previous, point);
}
catch (IllegalArgumentException e) {
actualException = e;
}
if (expectedException != null) {
assertNotNull(actualException);
}
else {
compare_sorted_sets(expectedSubSet, actualSubSet);
}
}
}
}
@SafeVarargs
public static <X, E> void compare_sorted_sets(SortedSet<X> expectedSet, SortedSet<E> actual, E... rangePoints) {
@SuppressWarnings("unchecked") SortedSet<E> expected = (SortedSet<E>)expectedSet;
compare_sets(expected, actual);
assertEquals(expected.comparator(), actual.comparator());
if (expected.isEmpty()) {
try { expected.first(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.first(); fail(); } catch (NoSuchElementException ignored) {}
try { expected.last(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.last(); fail(); } catch (NoSuchElementException ignored) {}
}
else {
assertEquals(expected.first(), actual.first());
assertEquals(expected.last(), actual.last());
// Compare the head sets of everything up to but not including the last item.
compare_sorted_sets(expected.headSet(expected.last()), actual.headSet(actual.last()));
if (expected.size() > 1) {
// Compare the tail sets of everything from the second item onwards.
E from = nth(expected, 1);
compare_sorted_sets(expected.tailSet(from), actual.tailSet(from));
}
}
compare_ranges(expected, actual, rangePoints);
}
public static void compare_entries(Map.Entry<?, ?> expected, Map.Entry<?, ?> actual) {
assertEquals(expected.getKey(), actual.getKey());
assertEquals("values unequal for key '" + expected.getKey() + "'.", expected.getValue(), actual.getValue());
assertEquals(expected, actual);
assertEquals(actual, expected);
assertEquals(expected.hashCode(), actual.hashCode());
assertEquals(expected.toString(), actual.toString());
}
public static void compare_maps(Map<?, ?> expected, Map<?, ?> actual) {
Iterator<? extends Map.Entry<?, ?>> actualIterator = actual.entrySet().iterator();
for (Map.Entry<?, ?> expectedEntry : expected.entrySet()) {
assertTrue(actualIterator.hasNext());
compare_entries(expectedEntry, actualIterator.next());
assertTrue(actual.containsKey(expectedEntry.getKey()));
assertTrue(actual.containsValue(expectedEntry.getValue()));
assertEquals(expectedEntry.getValue(), actual.get(expectedEntry.getKey()));
}
assertFalse(actualIterator.hasNext());
if (actual instanceof IterableMap) {
MapIterator<?, ?> iter = ((IterableMap)actual).iterator();
try { iter.value(); fail(); } catch (IllegalStateException ignored) {}
try { iter.entry(); fail(); } catch (IllegalStateException ignored) {}
try { iter.remove(); fail(); } catch (IllegalStateException | UnsupportedOperationException ignored) {}
Object lastValue = null;
Map.Entry<?, ?> lastEntry = null;
for (Map.Entry<?, ?> expectedEntry : expected.entrySet()) {
assertTrue(iter.hasNext());
assertEquals(expectedEntry.getKey(), iter.next());
assertEquals(expectedEntry.getValue(), lastValue = iter.value());
compare_entries(expectedEntry, lastEntry = iter.entry());
}
assertFalse(iter.hasNext());
try { iter.next(); fail(); } catch (NoSuchElementException ignored) {}
if (!actual.isEmpty()) {
// make sure the iterator still returns the last value and entry after the failed call to next.
assertEquals(lastValue, iter.value());
assertEquals(lastEntry, iter.entry());
}
}
assertEquals(expected.size(), actual.size());
assertEquals(expected.isEmpty(), actual.isEmpty());
assertEquals(expected, actual);
assertEquals(actual, expected);
assertEquals(expected.hashCode(), actual.hashCode());
assertEquals(expected.toString(), actual.toString());
assertEquals(expected.equals(new Object()), actual.equals(new Object()));
assertEquals(expected.equals(expected), actual.equals(actual));
Object item = new Object();
try { assertFalse(expected.containsKey(item)); } catch (ClassCastException ignored) {}
try { assertFalse(actual.containsKey(item)); } catch (ClassCastException ignored) {}
try { assertFalse(expected.containsValue(item)); } catch (ClassCastException ignored) {}
try { assertFalse(actual.containsValue(item)); } catch (ClassCastException ignored) {}
try { assertNull(expected.get(item)); } catch (ClassCastException ignored) {}
try { assertNull(actual.get(item)); } catch (ClassCastException ignored) {}
compare_sets(expected.keySet(), actual.keySet());
compare_collections(expected.values(), actual.values());
compare_sets(expected.entrySet(), actual.entrySet());
Map.Entry entry = newEntry(new Object(), new Object());
try { assertFalse(expected.entrySet().contains(entry)); } catch (ClassCastException ignored) {}
try { assertFalse(actual.entrySet().contains(entry)); } catch (ClassCastException ignored) {}
}
@SafeVarargs
private static <K, V> void compare_ranges(SortedMap<K, V> expected, SortedMap<K, V> actual, K... rangePoints) {
// Iterate over points [P0, ..., Pn]. Compare all sub maps described by each pair [Pi-1, Pi].
// For good measure, also compare head and tail maps for each point Pi.
for (int i = 0; i < rangePoints.length; i++) {
K point = rangePoints[i];
compare_sorted_maps(expected.headMap(point), actual.headMap(point));
compare_sorted_maps(expected.tailMap(point), actual.tailMap(point));
if (i > 0) {
K previous = rangePoints[i - 1];
SortedMap<K, V> expectedSubMap = null;
SortedMap<K, V> actualSubMap = null;
Exception expectedException = null;
Exception actualException = null;
// Construct sub maps from the current point and the previous point. These points might be
// inverted as part of the test. In this case, we expect construction of the sub maps to both
// throw the same exception.
try {
expectedSubMap = expected.subMap(previous, point);
}
catch (IllegalArgumentException e) {
expectedException = e;
}
try {
actualSubMap = actual.subMap(previous, point);
}
catch (IllegalArgumentException e) {
actualException = e;
}
if (expectedException != null) {
assertNotNull(actualException);
}
else {
compare_sorted_maps(expectedSubMap, actualSubMap);
}
}
}
}
@SafeVarargs
public static <XK, XV, K, V> void compare_sorted_maps(
SortedMap<XK, XV> expectedMap,
SortedMap<K, V> actual,
K... rangePoints) {
@SuppressWarnings("unchecked") SortedMap<K, V> expected = (SortedMap<K, V>)expectedMap;
compare_maps(expected, actual);
assertEquals(expected.comparator(), actual.comparator());
if (expected.isEmpty()) {
try { expected.firstKey(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.firstKey(); fail(); } catch (NoSuchElementException ignored) {}
try { expected.lastKey(); fail(); } catch (NoSuchElementException ignored) {}
try { actual.lastKey(); fail(); } catch (NoSuchElementException ignored) {}
}
else {
assertEquals(expected.firstKey(), actual.firstKey());
assertEquals(expected.lastKey(), actual.lastKey());
// Compare the head maps of everything up to but not including the last item.
compare_sorted_maps(expected.headMap(expected.lastKey()), actual.headMap(actual.lastKey()));
if (expected.size() > 1) {
// Compare the tail maps of everything from the second item onwards.
K from = nth(expected, 1);
compare_sorted_maps(expected.tailMap(from), actual.tailMap(from));
}
}
compare_ranges(expected, actual, rangePoints);
}
// =================================================================================================================
// collection mutations
@SafeVarargs
public static <E> void add(Collection<E> expected, Collection<E> actual, E... elements) {
for (E e : elements) {
boolean expectedResult = expected.add(e);
boolean actualResult = actual.add(e);
assertEquals(expectedResult, actualResult);
}
}
@SafeVarargs
public static <E> void addAll(Collection<E> expected, Collection<E> actual, E... elements) {
Collection<E> c = Collections.unmodifiableCollection(Arrays.asList(elements));
boolean expectedResult = expected.addAll(c);
boolean actualResult = actual.addAll(c);
assertEquals(expectedResult, actualResult);
}
@SafeVarargs
public static <E> void remove(Collection<E> expected, Collection<E> actual, E... elements) {
for (E e : elements) {
boolean expectedResult = expected.remove(e);
boolean actualResult = actual.remove(e);
assertEquals(expectedResult, actualResult);
}
}
@SafeVarargs
public static <E> void removeAll(Collection<E> expected, Collection<E> actual, E... elements) {
Collection<E> c = Collections.unmodifiableCollection(Arrays.asList(elements));
boolean expectedResult = expected.removeAll(c);
boolean actualResult = actual.removeAll(c);
assertEquals(expectedResult, actualResult);
}
@SafeVarargs
public static <E> void retainAll(Collection<E> expected, Collection<E> actual, E... elements) {
Collection<E> c = Collections.unmodifiableCollection(Arrays.asList(elements));
boolean expectedResult = expected.retainAll(c);
boolean actualResult = actual.retainAll(c);
assertEquals(expectedResult, actualResult);
}
@SafeVarargs
public static <E> void remove_by_iterator(Collection<E> expected, Collection<E> actual, E... elements) {
List<E> elementsToRemove = Arrays.asList(elements);
Iterator<E> expectedIterator = expected.iterator();
Iterator<E> actualIterator = actual.iterator();
try { expectedIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
try { actualIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
while (expectedIterator.hasNext()) {
assertTrue(actualIterator.hasNext());
E e = expectedIterator.next();
assertEquals(e, actualIterator.next());
if (elementsToRemove.contains(e)) {
expectedIterator.remove();
actualIterator.remove();
try { expectedIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
try { actualIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
}
}
assertFalse(actualIterator.hasNext());
}
public static <K, V> void put(Map<K, V> expected, Map<K, V> actual, K key, V value) {
V expectedExisting = expected.put(key, value);
V actualExisting = actual.put(key, value);
assertEquals(expectedExisting, actualExisting);
}
public static <K, V> void putAll(Map<K, V> expected, Map<K, V> actual, K k0, V v0, K k1, V v1) {
Map<K, V> map = Collections.unmodifiableMap(CollectionTestingTools.<K, V>newMap(k0, v0, k1, v1));
expected.putAll(map);
actual.putAll(map);
}
public static <K, V> void remove(Map<K, V> expected, Map<K, V> actual, K key) {
V expectedExisting = expected.remove(key);
V actualExisting = actual.remove(key);
assertEquals(expectedExisting, actualExisting);
}
@SafeVarargs
public static <K, V> void remove_by_map_iterator(Map<K, V> expected, IterableMap<K, V> actual, K... keys) {
Set<K> keysToRemove = new HashSet<>(Arrays.asList(keys));
Iterator<Map.Entry<K, V>> expectedIterator = expected.entrySet().iterator();
MapIterator<K, V> actualIterator = actual.iterator();
try { expectedIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
try { actualIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
while (expectedIterator.hasNext()) {
assertTrue(actualIterator.hasNext());
Map.Entry<K, V> e = expectedIterator.next();
K actualKey = actualIterator.next();
V actualValue = actualIterator.value();
assertEquals(e.getKey(), actualKey);
assertEquals(e.getValue(), actualValue);
assertEquals(e, actualIterator.entry());
if (keysToRemove.contains(e.getKey())) {
expectedIterator.remove();
actualIterator.remove();
try { expectedIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
try { actualIterator.remove(); fail(); } catch (IllegalStateException ignored) {}
}
}
assertFalse(actualIterator.hasNext());
}
}