/*
* 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 org.junit.Test;
import java.util.*;
import static java.util.Collections.*;
import static net.nullschool.collect.CollectionTestingTools.*;
import static net.nullschool.collect.IteratorTools.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.mockito.BDDMockito.*;
/**
* 2013-02-12<p/>
*
* @author Cameron Beccario
*/
public class AbstractIterableMapTest {
private static final class MockIterableMap<K, V> extends AbstractIterableMap<K, V> {
private final LinkedHashMap<K, V> inner = new LinkedHashMap<>();
MockIterableMap() {}
MockIterableMap(Map<? extends K, ? extends V> map) { inner.putAll(map); }
@Override public int size() { return inner.size(); }
@Override public V put(K key, V value) { return inner.put(key, value); }
@Override public MapIterator<K, V> iterator() { return newMapIterator(inner); }
}
// =================================================================================================================
// Map comparison tests
@Test
public void test_empty_map() {
compare_maps(emptyMap(), new MockIterableMap<>(emptyMap()));
}
@Test
public void test_singleton_map() {
Map<String, Integer> expected = singletonMap("a", 1);
compare_maps(expected, new MockIterableMap<>(expected));
}
@Test
public void test_map_with_several_values() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", 4, "e", 5);
compare_maps(expected, new MockIterableMap<>(expected));
}
@Test
public void test_map_with_nulls() {
Map<String, Integer> expected;
expected = newMap("a", null);
compare_maps(expected, new MockIterableMap<>(expected));
expected = newMap(null, 5);
compare_maps(expected, new MockIterableMap<>(expected));
expected = newMap(null, null);
compare_maps(expected, new MockIterableMap<>(expected));
}
@Test
public void test_inequality() {
Map<String, Integer> a;
IterableMap<String, Integer> b;
// differ by size
a = newMap("a", 1, "b", 2);
b = new MockIterableMap<>(singletonMap("a", 1));
assertNotEquals(a, b);
assertNotEquals(b, a);
// differ by keys
a = singletonMap("a", 1);
b = new MockIterableMap<>(singletonMap("b", 1));
assertNotEquals(a, b);
assertNotEquals(b, a);
// differ by values
a = singletonMap("a", 1);
b = new MockIterableMap<>(singletonMap("a", 2));
assertNotEquals(a, b);
assertNotEquals(b, a);
// differ by values of null keys
a = singletonMap(null, 1);
b = new MockIterableMap<>(singletonMap((String)null, 2));
assertNotEquals(a, b);
assertNotEquals(b, a);
// differ by keys with null values.
a = singletonMap("b", null);
b = new MockIterableMap<>(singletonMap("a", (Integer)null));
assertNotEquals(a, b);
assertNotEquals(b, a);
}
@Test
public void test_map_containing_self() {
Map<Object, Object> expected = new LinkedHashMap<>();
expected.put(expected, expected);
Map<Object, Object> actual = new MockIterableMap<>();
actual.put(actual, actual);
assertEquals(expected.toString(), actual.toString());
}
// =================================================================================================================
// Map mutation tests
@Test
public void test_map_put() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
Map<String, Integer> actual = new MockIterableMap<>(expected);
// put new
put(expected, actual, "d", 4);
compare_maps(expected, actual);
// replace value
put(expected, actual, "a", -1);
compare_maps(expected, actual);
// put null key
put(expected, actual, null, 10);
compare_maps(expected, actual);
// replace
put(expected, actual, null, 11);
compare_maps(expected, actual);
// put null value
put(expected, actual, "e", null);
compare_maps(expected, actual);
// replace
put(expected, actual, "e", 5);
compare_maps(expected, actual);
}
@Test
public void test_map_put_null_entry() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
Map<String, Integer> actual = new MockIterableMap<>(expected);
// put null entry
put(expected, actual, null, null);
compare_maps(expected, actual);
}
@Test
public void test_map_putAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
Map<String, Integer> actual = new MockIterableMap<>(expected);
// put existing and new
putAll(expected, actual, "a", -1, "d", 4);
compare_maps(expected, actual);
// put null keys and values
putAll(expected, actual, "e", null, null, 10);
compare_maps(expected, actual);
// putAll empty
expected.putAll(Collections.<String, Integer>emptyMap());
actual.putAll(Collections.<String, Integer>emptyMap());
compare_maps(expected, actual);
}
@Test
public void test_map_putAll_iterableMap() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
Map<String, Integer> actual = new MockIterableMap<>(expected);
// invoke putAll with an IterableMap argument
IterableMap<String, Integer> im = new MockIterableMap<>(singletonMap("x", 0));
expected.putAll(im);
actual.putAll(im);
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_map_null_putAll() {
new MockIterableMap<>().putAll(null);
}
@Test
public void test_map_remove() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
Map<String, Integer> actual = new MockIterableMap<>(expected);
// remove existing
remove(expected, actual, "c");
compare_maps(expected, actual);
// remove non-existing
remove(expected, actual, "x");
compare_maps(expected, actual);
// remove null key
remove(expected, actual, null);
compare_maps(expected, actual);
}
@Test
public void test_map_clear() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
Map<String, Integer> actual = new MockIterableMap<>(expected);
expected.clear();
actual.clear();
compare_maps(expected, actual);
}
@Test
public void test_map_iterator_remove() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
// remove existing
remove_by_map_iterator(expected, actual, "b");
compare_maps(expected, actual);
// remove non-existing
remove_by_map_iterator(expected, actual, "x");
compare_maps(expected, actual);
// remove null key
remove_by_map_iterator(expected, actual, new String[] {null});
compare_maps(expected, actual);
}
@Test
public void test_map_iterator_remove_multiple() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
remove_by_map_iterator(expected, actual, "c", "b");
compare_maps(expected, actual);
}
@Test
public void test_map_iterator_remove_all() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
remove_by_map_iterator(expected, actual, "c", "a", "b");
compare_maps(expected, actual);
}
@Test
public void test_map_entry_setValue() {
IterableMap<String, Integer> map = new MockIterableMap<>(singletonMap("a", 1));
for (MapIterator<String, Integer> iter = map.iterator(); iter.hasNext();) {
iter.next();
iter.entry().setValue(9);
}
compare_maps(singletonMap("a", 9), map);
}
@Test(expected = UnsupportedOperationException.class)
public void test_map_put_throws() {
@SuppressWarnings("unchecked") IterableMap<Object, Object> map = mock(AbstractIterableMap.class);
given(map.put(any(), any())).willCallRealMethod();
map.put(new Object(), new Object());
}
// =================================================================================================================
// KeySet mutation tests
@Test
public void test_keySet_remove() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
remove(expected.keySet(), actual.keySet(), "a", "c", null, "d");
compare_maps(expected, actual);
}
@Test
public void test_keySet_removeAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
removeAll(expected.keySet(), actual.keySet(), "a", "c", null, "d");
compare_maps(expected, actual);
// noinspection RedundantArrayCreation
removeAll(expected.keySet(), actual.keySet(), new String[0]);
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_keySet_removeAll_throws() {
new MockIterableMap<>(singletonMap("a", 1)).keySet().removeAll(null);
}
@Test
public void test_keySet_retainAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
retainAll(expected.keySet(), actual.keySet(), "a", "c", null, "d");
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_keySet_retainAll_throws() {
new MockIterableMap<>(singletonMap("a", 1)).keySet().retainAll(null);
}
@Test
public void test_keySet_clear() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, null, 4);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
expected.keySet().clear();
actual.keySet().clear();
compare_maps(expected, actual);
}
@Test(expected = UnsupportedOperationException.class)
public void test_keySet_add_throws() {
new MockIterableMap<>().keySet().add("a");
}
@Test(expected = UnsupportedOperationException.class)
public void test_keySet_addAll_throws() {
new MockIterableMap<>().keySet().addAll(Arrays.asList("a"));
}
// =================================================================================================================
// Values collection mutation tests
@Test
public void test_values_remove() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, "x", 1);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
remove(expected.values(), actual.values(), 1, 3, null, 5);
compare_maps(expected, actual);
}
@Test
public void test_values_removeAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, "x", 1);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
removeAll(expected.values(), actual.values(), 1, 3, null, 5);
compare_maps(expected, actual);
// noinspection RedundantArrayCreation
removeAll(expected.values(), actual.values(), new Integer[0]);
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_values_removeAll_throws() {
// noinspection ConstantConditions
new MockIterableMap<>(singletonMap("a", 1)).values().removeAll(null);
}
@Test
public void test_values_retainAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, "x", 1);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
retainAll(expected.values(), actual.values(), 1, 3, null, 5);
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_values_retainAll_throws() {
// noinspection ConstantConditions
new MockIterableMap<>(singletonMap("a", 1)).values().retainAll(null);
}
@Test
public void test_values_clear() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, "x", 1);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
expected.values().clear();
actual.values().clear();
compare_maps(expected, actual);
}
@Test(expected = UnsupportedOperationException.class)
public void test_values_add_throws() {
new MockIterableMap<>().values().add(1);
}
@Test(expected = UnsupportedOperationException.class)
public void test_values_addAll_throws() {
new MockIterableMap<>().values().addAll(Arrays.asList(1));
}
// =================================================================================================================
// EntrySet mutation tests
@Test
public void test_entrySet_remove() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, null, 5);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
remove(
expected.entrySet(),
actual.entrySet(),
newEntry("a", 1),
newEntry("d", (Integer)null),
newEntry((String)null, 5),
newEntry("c", 4),
newEntry("x", 2),
newEntry("z", 9));
compare_maps(expected, actual);
}
@Test
public void test_entrySet_removeAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, null, 5);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
removeAll(
expected.entrySet(),
actual.entrySet(),
newEntry("a", 1),
newEntry("d", (Integer)null),
newEntry((String)null, 5),
newEntry("c", 4),
newEntry("x", 2),
newEntry("z", 9));
compare_maps(expected, actual);
removeAll(expected.entrySet(), actual.entrySet());
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_entrySet_removeAll_throws() {
// noinspection ConstantConditions
new MockIterableMap<>(singletonMap("a", 1)).entrySet().removeAll(null);
}
@Test
public void test_entrySet_retainAll() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, null, 5);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
retainAll(
expected.entrySet(),
actual.entrySet(),
newEntry("a", 1),
newEntry("d", (Integer)null),
newEntry((String)null, 5),
newEntry("c", 4),
newEntry("x", 2),
newEntry("z", 9));
compare_maps(expected, actual);
}
@Test(expected = NullPointerException.class)
public void test_entrySet_retainAll_throws() {
// noinspection ConstantConditions
new MockIterableMap<>(singletonMap("a", 1)).entrySet().retainAll(null);
}
@Test
public void test_entrySet_clear() {
Map<String, Integer> expected = newMap("a", 1, "b", 2, "c", 3, "d", null, null, 5);
IterableMap<String, Integer> actual = new MockIterableMap<>(expected);
expected.entrySet().clear();
actual.entrySet().clear();
compare_maps(expected, actual);
}
@Test(expected = UnsupportedOperationException.class)
public void test_entrySet_add_throws() {
new MockIterableMap<String, Integer>().entrySet().add(newEntry("a", 1));
}
@Test(expected = UnsupportedOperationException.class)
public void test_entrySet_addAll_throws() {
new MockIterableMap<String, Integer>().entrySet().addAll(Arrays.asList(newEntry("a", 1)));
}
}