Home | History | Annotate | Download | only in collection
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.collection;
     18 
     19 import static org.hamcrest.CoreMatchers.is;
     20 import static org.hamcrest.CoreMatchers.nullValue;
     21 import static org.hamcrest.MatcherAssert.assertThat;
     22 
     23 import androidx.arch.core.internal.SafeIterableMap;
     24 
     25 import org.junit.Test;
     26 import org.junit.runner.RunWith;
     27 import org.junit.runners.JUnit4;
     28 
     29 import java.util.ArrayList;
     30 import java.util.Iterator;
     31 import java.util.Map.Entry;
     32 
     33 @RunWith(JUnit4.class)
     34 public class SafeIterableMapTest {
     35 
     36     @Test
     37     public void testToString() {
     38         SafeIterableMap<Integer, String> map = from(1, 2, 3, 4).to("a", "b", "c", "d");
     39         assertThat(map.toString(), is("[1=a, 2=b, 3=c, 4=d]"));
     40     }
     41 
     42     @Test
     43     public void testEmptyToString() {
     44         SafeIterableMap<Integer, Boolean> map = mapOf();
     45         assertThat(map.toString(), is("[]"));
     46     }
     47 
     48     @Test
     49     public void testOneElementToString() {
     50         SafeIterableMap<Integer, Boolean> map = mapOf(1);
     51         assertThat(map.toString(), is("[1=true]"));
     52     }
     53 
     54 
     55     @Test
     56     public void testEquality1() {
     57         SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(10, 20, 30, 40);
     58         SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(10, 20, 30, 40);
     59         assertThat(map1.equals(map2), is(true));
     60     }
     61 
     62     @Test
     63     public void testEquality2() {
     64         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
     65         //noinspection ObjectEqualsNull
     66         assertThat(map.equals(null), is(false));
     67     }
     68 
     69     @Test
     70     public void testEquality3() {
     71         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
     72         //noinspection EqualsBetweenInconvertibleTypes
     73         assertThat(map.equals(new ArrayList<>()), is(false));
     74     }
     75 
     76     @Test
     77     public void testEquality4() {
     78         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
     79         assertThat(map.equals(new SafeIterableMap<Integer, Boolean>()), is(false));
     80     }
     81 
     82     @Test
     83     public void testEquality5() {
     84         SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4);
     85         SafeIterableMap<Integer, Boolean> map2 = mapOf(1);
     86         assertThat(map1.equals(map2), is(false));
     87     }
     88 
     89     @Test
     90     public void testEquality6() {
     91         SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4);
     92         SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 2, 3, 5);
     93         assertThat(map1.equals(map2), is(false));
     94     }
     95 
     96     @Test
     97     public void testEquality7() {
     98         SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(1, 2, 3, 4);
     99         SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(1, 2, 3, 5);
    100         assertThat(map1.equals(map2), is(false));
    101     }
    102 
    103 
    104     @Test
    105     public void testEquality8() {
    106         SafeIterableMap<Integer, Boolean> map1 = mapOf();
    107         SafeIterableMap<Integer, Boolean> map2 = mapOf();
    108         assertThat(map1.equals(map2), is(true));
    109     }
    110 
    111     @Test
    112     public void testEqualityRespectsOrder() {
    113         SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4);
    114         SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 3, 2, 4);
    115         assertThat(map1.equals(map2), is(false));
    116     }
    117 
    118     @Test
    119     public void testPut() {
    120         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40);
    121         assertThat(map.putIfAbsent(5, 10), is((Integer) null));
    122         assertThat(map, is(from(1, 2, 3, 4, 5).to(10, 20, 30, 40, 10)));
    123     }
    124 
    125     @Test
    126     public void testAddExisted() {
    127         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 261, 40);
    128         assertThat(map.putIfAbsent(3, 239), is(261));
    129         assertThat(map, is(from(1, 2, 3, 4).to(10, 20, 261, 40)));
    130     }
    131 
    132     @Test
    133     public void testRemoveLast() {
    134         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40);
    135         assertThat(map.remove(4), is(40));
    136         assertThat(map, is(from(1, 2, 3).to(10, 20, 30)));
    137     }
    138 
    139     @Test
    140     public void testRemoveFirst() {
    141         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    142         assertThat(map.remove(1), is(true));
    143         assertThat(map, is(mapOf(2, 3, 4)));
    144     }
    145 
    146     @Test
    147     public void testRemoveMiddle() {
    148         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40);
    149         assertThat(map.remove(2), is(20));
    150         assertThat(map.remove(3), is(30));
    151         assertThat(map, is(from(1, 4).to(10, 40)));
    152     }
    153 
    154     @Test
    155     public void testRemoveNotExisted() {
    156         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    157         assertThat(map.remove(5), is((Boolean) null));
    158         assertThat(map, is(mapOf(1, 2, 3, 4)));
    159     }
    160 
    161     @Test
    162     public void testRemoveSole() {
    163         SafeIterableMap<Integer, Integer> map = from(1).to(261);
    164         assertThat(map.remove(1), is(261));
    165         assertThat(map, is(new SafeIterableMap<Integer, Integer>()));
    166     }
    167 
    168     @Test
    169     public void testRemoveDuringIteration1() {
    170         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40);
    171         int index = 0;
    172         int[] expected = new int[]{1, 4};
    173         for (Entry<Integer, Integer> i : map) {
    174             assertThat(i.getKey(), is(expected[index++]));
    175             if (index == 1) {
    176                 assertThat(map.remove(2), is(20));
    177                 assertThat(map.remove(3), is(30));
    178             }
    179         }
    180     }
    181 
    182     @Test
    183     public void testRemoveDuringIteration2() {
    184         SafeIterableMap<Integer, Integer> map = from(1, 2).to(10, 20);
    185         Iterator<Entry<Integer, Integer>> iter = map.iterator();
    186         assertThat(map.remove(2), is(20));
    187         assertThat(map.remove(1), is(10));
    188         assertThat(iter.hasNext(), is(false));
    189     }
    190 
    191     @Test
    192     public void testRemoveDuringIteration3() {
    193         SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40);
    194         int index = 0;
    195         Iterator<Entry<Integer, Integer>> iter = map.iterator();
    196         assertThat(map.remove(1), is(10));
    197         assertThat(map.remove(2), is(20));
    198         int[] expected = new int[]{3, 4};
    199         while (iter.hasNext()) {
    200             assertThat(iter.next().getKey(), is(expected[index++]));
    201         }
    202     }
    203 
    204     @Test
    205     public void testRemoveDuringIteration4() {
    206         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2);
    207         int[] expected = new int[]{1, 2};
    208         int index = 0;
    209         for (Entry<Integer, Boolean> entry : map) {
    210             assertThat(entry.getKey(), is(expected[index++]));
    211             if (index == 1) {
    212                 map.remove(1);
    213             }
    214         }
    215         assertThat(index, is(2));
    216     }
    217 
    218     @Test
    219     public void testAdditionDuringIteration() {
    220         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    221         int[] expected = new int[]{1, 2, 3, 4};
    222         int index = 0;
    223         for (Entry<Integer, Boolean> entry : map) {
    224             assertThat(entry.getKey(), is(expected[index++]));
    225             if (index == 1) {
    226                 map.putIfAbsent(5, true);
    227             }
    228         }
    229     }
    230 
    231     @Test
    232     public void testReAdditionDuringIteration() {
    233         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    234         int[] expected = new int[]{1, 2, 4};
    235         int index = 0;
    236         for (Entry<Integer, Boolean> entry : map) {
    237             assertThat(entry.getKey(), is(expected[index++]));
    238             if (index == 1) {
    239                 map.remove(3);
    240                 map.putIfAbsent(3, true);
    241             }
    242         }
    243     }
    244 
    245     @Test
    246     public void testSize() {
    247         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    248         assertThat(map.size(), is(4));
    249         map.putIfAbsent(5, true);
    250         map.putIfAbsent(6, true);
    251         assertThat(map.size(), is(6));
    252         map.remove(5);
    253         map.remove(5);
    254         assertThat(map.size(), is(5));
    255         map.remove(1);
    256         map.remove(2);
    257         map.remove(4);
    258         map.remove(3);
    259         map.remove(6);
    260         assertThat(map.size(), is(0));
    261         map.putIfAbsent(4, true);
    262         assertThat(map.size(), is(1));
    263         assertThat(mapOf().size(), is(0));
    264     }
    265 
    266     @Test
    267     public void testIteratorWithAdditions1() {
    268         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    269         int[] expected = new int[]{1, 2, 3, 5};
    270         int index = 0;
    271         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    272         while (iterator.hasNext()) {
    273             Entry<Integer, Boolean> entry = iterator.next();
    274             assertThat(entry.getKey(), is(expected[index++]));
    275             if (index == 3) {
    276                 map.remove(4);
    277                 map.putIfAbsent(5, true);
    278             }
    279         }
    280     }
    281 
    282     @Test
    283     public void testIteratorWithAdditions2() {
    284         SafeIterableMap<Integer, Boolean> map = mapOf(1);
    285         int[] expected = new int[]{1, 2, 3};
    286         int index = 0;
    287         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    288         while (iterator.hasNext()) {
    289             Entry<Integer, Boolean> entry = iterator.next();
    290             assertThat(entry.getKey(), is(expected[index++]));
    291             if (index == 1) {
    292                 map.putIfAbsent(2, true);
    293                 map.putIfAbsent(3, true);
    294             }
    295         }
    296         assertThat(index, is(3));
    297     }
    298 
    299 
    300     @Test
    301     public void testIteratorWithAdditions3() {
    302         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3);
    303         int[] expected = new int[]{1};
    304         int index = 0;
    305         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    306         while (iterator.hasNext()) {
    307             Entry<Integer, Boolean> entry = iterator.next();
    308             assertThat(entry.getKey(), is(expected[index++]));
    309             map.remove(2);
    310             map.remove(3);
    311         }
    312         assertThat(index, is(1));
    313     }
    314 
    315     @Test
    316     public void testIteratorWithAdditions4() {
    317         SafeIterableMap<Integer, Boolean> map = mapOf();
    318         int[] expected = new int[]{1, 2, 3};
    319         int index = 0;
    320         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    321         map.putIfAbsent(1, true);
    322         while (iterator.hasNext()) {
    323             Entry<Integer, Boolean> entry = iterator.next();
    324             assertThat(entry.getKey(), is(expected[index++]));
    325             if (index == 1) {
    326                 map.putIfAbsent(2, false);
    327             }
    328             if (index == 2) {
    329                 map.putIfAbsent(3, false);
    330             }
    331         }
    332         assertThat(index, is(3));
    333     }
    334 
    335     @Test
    336     public void testIteratorWithAddition5() {
    337         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2);
    338         int[] expected = new int[]{1, 2};
    339         int index = 0;
    340         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    341         while (iterator.hasNext()) {
    342             Entry<Integer, Boolean> entry = iterator.next();
    343             assertThat(entry.getKey(), is(expected[index++]));
    344             if (index == 1) {
    345                 map.remove(1);
    346             }
    347         }
    348         assertThat(index, is(2));
    349     }
    350 
    351     @Test
    352     public void testDescendingIteration() {
    353         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    354         int[] expected = new int[]{4, 3, 2, 1};
    355         int index = 0;
    356         for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) {
    357             assertThat(iter.next().getKey(), is(expected[index++]));
    358         }
    359         assertThat(index, is(4));
    360     }
    361 
    362     @Test
    363     public void testDescendingIterationRemove1() {
    364         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    365         int[] expected = new int[]{4, 3, 2};
    366         int index = 0;
    367         for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) {
    368             if (index == 1) {
    369                 map.remove(1);
    370             }
    371             assertThat(iter.next().getKey(), is(expected[index++]));
    372         }
    373         assertThat(index, is(3));
    374         assertThat(map.size(), is(3));
    375     }
    376 
    377     @Test
    378     public void testDescendingIterationRemove2() {
    379         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    380         int[] expected = new int[]{3, 2, 1};
    381         int index = 0;
    382         for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) {
    383             if (index == 0) {
    384                 map.remove(4);
    385             }
    386             assertThat(iter.next().getKey(), is(expected[index++]));
    387         }
    388         assertThat(index, is(3));
    389         assertThat(map.size(), is(3));
    390     }
    391 
    392     @Test
    393     public void testDescendingIterationRemove3() {
    394         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    395         int[] expected = new int[]{4, 1};
    396         int index = 0;
    397         for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) {
    398             if (index == 1) {
    399                 map.remove(3);
    400                 map.remove(2);
    401             }
    402             assertThat(iter.next().getKey(), is(expected[index++]));
    403         }
    404         assertThat(index, is(2));
    405         assertThat(map.size(), is(2));
    406     }
    407 
    408     @Test
    409     public void testDescendingIterationAddition() {
    410         SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4);
    411         int[] expected = new int[]{4, 3, 2, 1};
    412         int index = 0;
    413         for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) {
    414             if (index == 0) {
    415                 map.putIfAbsent(5, false);
    416             }
    417             assertThat(iter.next().getKey(), is(expected[index++]));
    418         }
    419         assertThat(index, is(4));
    420         assertThat(map.size(), is(5));
    421     }
    422 
    423     @Test
    424     public void testDescendingIteratorEmpty() {
    425         SafeIterableMap<Integer, Boolean> map = mapOf();
    426         Iterator<Entry<Integer, Boolean>> iterator = map.descendingIterator();
    427         assertThat(iterator.hasNext(), is(false));
    428     }
    429 
    430     @Test
    431     public void testIteratorEmpty() {
    432         SafeIterableMap<Integer, Boolean> map = mapOf();
    433         Iterator<Entry<Integer, Boolean>> iterator = map.iterator();
    434         assertThat(iterator.hasNext(), is(false));
    435     }
    436 
    437     @Test
    438     public void testIteratorWithAdditionEmpty() {
    439         SafeIterableMap<Integer, Boolean> map = mapOf();
    440         Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions();
    441         assertThat(iterator.hasNext(), is(false));
    442     }
    443 
    444     @Test
    445     public void testEldest() {
    446         SafeIterableMap<Integer, Boolean> map = mapOf();
    447         assertThat(map.eldest(), nullValue());
    448         map.putIfAbsent(1, false);
    449         assertThat(map.eldest().getKey(), is(1));
    450         map.putIfAbsent(2, false);
    451         assertThat(map.eldest().getKey(), is(1));
    452         map.remove(1);
    453         assertThat(map.eldest().getKey(), is(2));
    454         map.remove(2);
    455         assertThat(map.eldest(), nullValue());
    456     }
    457 
    458     @Test
    459     public void testNewest() {
    460         SafeIterableMap<Integer, Boolean> map = mapOf();
    461         assertThat(map.newest(), nullValue());
    462         map.putIfAbsent(1, false);
    463         assertThat(map.newest().getKey(), is(1));
    464         map.putIfAbsent(2, false);
    465         assertThat(map.newest().getKey(), is(2));
    466         map.remove(2);
    467         assertThat(map.eldest().getKey(), is(1));
    468         map.remove(1);
    469         assertThat(map.newest(), nullValue());
    470     }
    471 
    472 
    473     // for most operations we don't care about values, so we create map from key to true
    474     @SafeVarargs
    475     private static <K> SafeIterableMap<K, Boolean> mapOf(K... keys) {
    476         SafeIterableMap<K, Boolean> map = new SafeIterableMap<>();
    477         for (K key : keys) {
    478             map.putIfAbsent(key, true);
    479         }
    480         return map;
    481     }
    482 
    483     @SafeVarargs
    484     private static <K> MapBuilder<K> from(K... keys) {
    485         return new MapBuilder<>(keys);
    486     }
    487 
    488     private static class MapBuilder<K> {
    489         final K[] mKeys;
    490 
    491         MapBuilder(K[] keys) {
    492             this.mKeys = keys;
    493         }
    494 
    495         @SafeVarargs
    496         public final <V> SafeIterableMap<K, V> to(V... values) {
    497             assertThat("Failed to build Map", mKeys.length, is(values.length));
    498             SafeIterableMap<K, V> map = new SafeIterableMap<>();
    499             for (int i = 0; i < mKeys.length; i++) {
    500                 map.putIfAbsent(mKeys[i], values[i]);
    501             }
    502             return map;
    503         }
    504     }
    505 }
    506 
    507 
    508