| /* | |
| * Copyright 2018 The Android Open Source Project | |
| * | |
| * 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 androidx.collection; | |
| import static org.hamcrest.CoreMatchers.is; | |
| import static org.hamcrest.CoreMatchers.nullValue; | |
| import static org.hamcrest.MatcherAssert.assertThat; | |
| import androidx.arch.core.internal.SafeIterableMap; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| import java.util.ArrayList; | |
| import java.util.Iterator; | |
| import java.util.Map.Entry; | |
| @RunWith(JUnit4.class) | |
| public class SafeIterableMapTest { | |
| @Test | |
| public void testToString() { | |
| SafeIterableMap<Integer, String> map = from(1, 2, 3, 4).to("a", "b", "c", "d"); | |
| assertThat(map.toString(), is("[1=a, 2=b, 3=c, 4=d]")); | |
| } | |
| @Test | |
| public void testEmptyToString() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| assertThat(map.toString(), is("[]")); | |
| } | |
| @Test | |
| public void testOneElementToString() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1); | |
| assertThat(map.toString(), is("[1=true]")); | |
| } | |
| @Test | |
| public void testEquality1() { | |
| SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| assertThat(map1.equals(map2), is(true)); | |
| } | |
| @Test | |
| public void testEquality2() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| //noinspection ObjectEqualsNull | |
| assertThat(map.equals(null), is(false)); | |
| } | |
| @Test | |
| public void testEquality3() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| //noinspection EqualsBetweenInconvertibleTypes | |
| assertThat(map.equals(new ArrayList<>()), is(false)); | |
| } | |
| @Test | |
| public void testEquality4() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| assertThat(map.equals(new SafeIterableMap<Integer, Boolean>()), is(false)); | |
| } | |
| @Test | |
| public void testEquality5() { | |
| SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); | |
| SafeIterableMap<Integer, Boolean> map2 = mapOf(1); | |
| assertThat(map1.equals(map2), is(false)); | |
| } | |
| @Test | |
| public void testEquality6() { | |
| SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); | |
| SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 2, 3, 5); | |
| assertThat(map1.equals(map2), is(false)); | |
| } | |
| @Test | |
| public void testEquality7() { | |
| SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(1, 2, 3, 4); | |
| SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(1, 2, 3, 5); | |
| assertThat(map1.equals(map2), is(false)); | |
| } | |
| @Test | |
| public void testEquality8() { | |
| SafeIterableMap<Integer, Boolean> map1 = mapOf(); | |
| SafeIterableMap<Integer, Boolean> map2 = mapOf(); | |
| assertThat(map1.equals(map2), is(true)); | |
| } | |
| @Test | |
| public void testEqualityRespectsOrder() { | |
| SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); | |
| SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 3, 2, 4); | |
| assertThat(map1.equals(map2), is(false)); | |
| } | |
| @Test | |
| public void testPut() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| assertThat(map.putIfAbsent(5, 10), is((Integer) null)); | |
| assertThat(map, is(from(1, 2, 3, 4, 5).to(10, 20, 30, 40, 10))); | |
| } | |
| @Test | |
| public void testAddExisted() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 261, 40); | |
| assertThat(map.putIfAbsent(3, 239), is(261)); | |
| assertThat(map, is(from(1, 2, 3, 4).to(10, 20, 261, 40))); | |
| } | |
| @Test | |
| public void testRemoveLast() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| assertThat(map.remove(4), is(40)); | |
| assertThat(map, is(from(1, 2, 3).to(10, 20, 30))); | |
| } | |
| @Test | |
| public void testRemoveFirst() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| assertThat(map.remove(1), is(true)); | |
| assertThat(map, is(mapOf(2, 3, 4))); | |
| } | |
| @Test | |
| public void testRemoveMiddle() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| assertThat(map.remove(2), is(20)); | |
| assertThat(map.remove(3), is(30)); | |
| assertThat(map, is(from(1, 4).to(10, 40))); | |
| } | |
| @Test | |
| public void testRemoveNotExisted() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| assertThat(map.remove(5), is((Boolean) null)); | |
| assertThat(map, is(mapOf(1, 2, 3, 4))); | |
| } | |
| @Test | |
| public void testRemoveSole() { | |
| SafeIterableMap<Integer, Integer> map = from(1).to(261); | |
| assertThat(map.remove(1), is(261)); | |
| assertThat(map, is(new SafeIterableMap<Integer, Integer>())); | |
| } | |
| @Test | |
| public void testRemoveDuringIteration1() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| int index = 0; | |
| int[] expected = new int[]{1, 4}; | |
| for (Entry<Integer, Integer> i : map) { | |
| assertThat(i.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| assertThat(map.remove(2), is(20)); | |
| assertThat(map.remove(3), is(30)); | |
| } | |
| } | |
| } | |
| @Test | |
| public void testRemoveDuringIteration2() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2).to(10, 20); | |
| Iterator<Entry<Integer, Integer>> iter = map.iterator(); | |
| assertThat(map.remove(2), is(20)); | |
| assertThat(map.remove(1), is(10)); | |
| assertThat(iter.hasNext(), is(false)); | |
| } | |
| @Test | |
| public void testRemoveDuringIteration3() { | |
| SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); | |
| int index = 0; | |
| Iterator<Entry<Integer, Integer>> iter = map.iterator(); | |
| assertThat(map.remove(1), is(10)); | |
| assertThat(map.remove(2), is(20)); | |
| int[] expected = new int[]{3, 4}; | |
| while (iter.hasNext()) { | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| } | |
| @Test | |
| public void testRemoveDuringIteration4() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2); | |
| int[] expected = new int[]{1, 2}; | |
| int index = 0; | |
| for (Entry<Integer, Boolean> entry : map) { | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.remove(1); | |
| } | |
| } | |
| assertThat(index, is(2)); | |
| } | |
| @Test | |
| public void testAdditionDuringIteration() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{1, 2, 3, 4}; | |
| int index = 0; | |
| for (Entry<Integer, Boolean> entry : map) { | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.putIfAbsent(5, true); | |
| } | |
| } | |
| } | |
| @Test | |
| public void testReAdditionDuringIteration() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{1, 2, 4}; | |
| int index = 0; | |
| for (Entry<Integer, Boolean> entry : map) { | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.remove(3); | |
| map.putIfAbsent(3, true); | |
| } | |
| } | |
| } | |
| @Test | |
| public void testSize() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| assertThat(map.size(), is(4)); | |
| map.putIfAbsent(5, true); | |
| map.putIfAbsent(6, true); | |
| assertThat(map.size(), is(6)); | |
| map.remove(5); | |
| map.remove(5); | |
| assertThat(map.size(), is(5)); | |
| map.remove(1); | |
| map.remove(2); | |
| map.remove(4); | |
| map.remove(3); | |
| map.remove(6); | |
| assertThat(map.size(), is(0)); | |
| map.putIfAbsent(4, true); | |
| assertThat(map.size(), is(1)); | |
| assertThat(mapOf().size(), is(0)); | |
| } | |
| @Test | |
| public void testIteratorWithAdditions1() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{1, 2, 3, 5}; | |
| int index = 0; | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| while (iterator.hasNext()) { | |
| Entry<Integer, Boolean> entry = iterator.next(); | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 3) { | |
| map.remove(4); | |
| map.putIfAbsent(5, true); | |
| } | |
| } | |
| } | |
| @Test | |
| public void testIteratorWithAdditions2() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1); | |
| int[] expected = new int[]{1, 2, 3}; | |
| int index = 0; | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| while (iterator.hasNext()) { | |
| Entry<Integer, Boolean> entry = iterator.next(); | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.putIfAbsent(2, true); | |
| map.putIfAbsent(3, true); | |
| } | |
| } | |
| assertThat(index, is(3)); | |
| } | |
| @Test | |
| public void testIteratorWithAdditions3() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3); | |
| int[] expected = new int[]{1}; | |
| int index = 0; | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| while (iterator.hasNext()) { | |
| Entry<Integer, Boolean> entry = iterator.next(); | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| map.remove(2); | |
| map.remove(3); | |
| } | |
| assertThat(index, is(1)); | |
| } | |
| @Test | |
| public void testIteratorWithAdditions4() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| int[] expected = new int[]{1, 2, 3}; | |
| int index = 0; | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| map.putIfAbsent(1, true); | |
| while (iterator.hasNext()) { | |
| Entry<Integer, Boolean> entry = iterator.next(); | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.putIfAbsent(2, false); | |
| } | |
| if (index == 2) { | |
| map.putIfAbsent(3, false); | |
| } | |
| } | |
| assertThat(index, is(3)); | |
| } | |
| @Test | |
| public void testIteratorWithAddition5() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2); | |
| int[] expected = new int[]{1, 2}; | |
| int index = 0; | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| while (iterator.hasNext()) { | |
| Entry<Integer, Boolean> entry = iterator.next(); | |
| assertThat(entry.getKey(), is(expected[index++])); | |
| if (index == 1) { | |
| map.remove(1); | |
| } | |
| } | |
| assertThat(index, is(2)); | |
| } | |
| @Test | |
| public void testDescendingIteration() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{4, 3, 2, 1}; | |
| int index = 0; | |
| for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| assertThat(index, is(4)); | |
| } | |
| @Test | |
| public void testDescendingIterationRemove1() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{4, 3, 2}; | |
| int index = 0; | |
| for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { | |
| if (index == 1) { | |
| map.remove(1); | |
| } | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| assertThat(index, is(3)); | |
| assertThat(map.size(), is(3)); | |
| } | |
| @Test | |
| public void testDescendingIterationRemove2() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{3, 2, 1}; | |
| int index = 0; | |
| for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { | |
| if (index == 0) { | |
| map.remove(4); | |
| } | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| assertThat(index, is(3)); | |
| assertThat(map.size(), is(3)); | |
| } | |
| @Test | |
| public void testDescendingIterationRemove3() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{4, 1}; | |
| int index = 0; | |
| for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { | |
| if (index == 1) { | |
| map.remove(3); | |
| map.remove(2); | |
| } | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| assertThat(index, is(2)); | |
| assertThat(map.size(), is(2)); | |
| } | |
| @Test | |
| public void testDescendingIterationAddition() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); | |
| int[] expected = new int[]{4, 3, 2, 1}; | |
| int index = 0; | |
| for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { | |
| if (index == 0) { | |
| map.putIfAbsent(5, false); | |
| } | |
| assertThat(iter.next().getKey(), is(expected[index++])); | |
| } | |
| assertThat(index, is(4)); | |
| assertThat(map.size(), is(5)); | |
| } | |
| @Test | |
| public void testDescendingIteratorEmpty() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| Iterator<Entry<Integer, Boolean>> iterator = map.descendingIterator(); | |
| assertThat(iterator.hasNext(), is(false)); | |
| } | |
| @Test | |
| public void testIteratorEmpty() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iterator(); | |
| assertThat(iterator.hasNext(), is(false)); | |
| } | |
| @Test | |
| public void testIteratorWithAdditionEmpty() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); | |
| assertThat(iterator.hasNext(), is(false)); | |
| } | |
| @Test | |
| public void testEldest() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| assertThat(map.eldest(), nullValue()); | |
| map.putIfAbsent(1, false); | |
| assertThat(map.eldest().getKey(), is(1)); | |
| map.putIfAbsent(2, false); | |
| assertThat(map.eldest().getKey(), is(1)); | |
| map.remove(1); | |
| assertThat(map.eldest().getKey(), is(2)); | |
| map.remove(2); | |
| assertThat(map.eldest(), nullValue()); | |
| } | |
| @Test | |
| public void testNewest() { | |
| SafeIterableMap<Integer, Boolean> map = mapOf(); | |
| assertThat(map.newest(), nullValue()); | |
| map.putIfAbsent(1, false); | |
| assertThat(map.newest().getKey(), is(1)); | |
| map.putIfAbsent(2, false); | |
| assertThat(map.newest().getKey(), is(2)); | |
| map.remove(2); | |
| assertThat(map.eldest().getKey(), is(1)); | |
| map.remove(1); | |
| assertThat(map.newest(), nullValue()); | |
| } | |
| // for most operations we don't care about values, so we create map from key to true | |
| @SafeVarargs | |
| private static <K> SafeIterableMap<K, Boolean> mapOf(K... keys) { | |
| SafeIterableMap<K, Boolean> map = new SafeIterableMap<>(); | |
| for (K key : keys) { | |
| map.putIfAbsent(key, true); | |
| } | |
| return map; | |
| } | |
| @SafeVarargs | |
| private static <K> MapBuilder<K> from(K... keys) { | |
| return new MapBuilder<>(keys); | |
| } | |
| private static class MapBuilder<K> { | |
| final K[] mKeys; | |
| MapBuilder(K[] keys) { | |
| this.mKeys = keys; | |
| } | |
| @SafeVarargs | |
| public final <V> SafeIterableMap<K, V> to(V... values) { | |
| assertThat("Failed to build Map", mKeys.length, is(values.length)); | |
| SafeIterableMap<K, V> map = new SafeIterableMap<>(); | |
| for (int i = 0; i < mKeys.length; i++) { | |
| map.putIfAbsent(mKeys[i], values[i]); | |
| } | |
| return map; | |
| } | |
| } | |
| } | |