Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      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 com.google.common.collect;
     18 
     19 import static java.util.Arrays.asList;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 import com.google.common.annotations.GwtIncompatible;
     23 import com.google.common.testing.SerializableTester;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import java.io.Serializable;
     28 import java.util.Collections;
     29 import java.util.Iterator;
     30 import java.util.Map;
     31 import java.util.Map.Entry;
     32 import java.util.Set;
     33 
     34 /**
     35  * Common tests for any {@code BiMap}.
     36  *
     37  * @author Kevin Bourrillion
     38  */
     39 @GwtCompatible(emulated = true)
     40 public abstract class AbstractBiMapTest extends TestCase {
     41 
     42   protected abstract BiMap<Integer, String> create();
     43 
     44   protected BiMap<Integer, String> bimap;
     45   protected Set<Entry<Integer, String>> entrySet;
     46 
     47   // public for GWT
     48   @Override public void setUp() throws Exception {
     49     super.setUp();
     50     bimap = create();
     51     entrySet = bimap.entrySet();
     52   }
     53 
     54   public void testClear() {
     55     bimap.clear();
     56     assertTrue(bimap.isEmpty());
     57     putOneTwoThree();
     58     bimap.clear();
     59     assertTrue(bimap.isEmpty());
     60   }
     61 
     62   public void testContainsKey() {
     63     assertFalse(bimap.containsKey(null));
     64     assertFalse(bimap.containsKey(1));
     65     assertFalse(bimap.containsKey("one"));
     66 
     67     bimap.put(1, "one");
     68     assertTrue(bimap.containsKey(1));
     69 
     70     bimap.put(null, null);
     71     assertTrue(bimap.containsKey(null));
     72   }
     73 
     74   public void testContainsValue() {
     75     assertFalse(bimap.containsValue(null));
     76     assertFalse(bimap.containsValue(1));
     77     assertFalse(bimap.containsValue("one"));
     78 
     79     bimap.put(1, "one");
     80     assertTrue(bimap.containsValue("one"));
     81 
     82     bimap.put(null, null);
     83     assertTrue(bimap.containsValue(null));
     84   }
     85 
     86   public void testEquals() {
     87     BiMap<Integer, String> biMap = create();
     88     assertEquals(biMap, biMap);
     89     assertEquals(create(), biMap);
     90     biMap.put(1, null);
     91     assertFalse(create().equals(biMap));
     92   }
     93 
     94   public void testGet() {
     95     assertNull(bimap.get(1));
     96     assertNull(bimap.get(null));
     97     assertNull(bimap.get("bad"));
     98 
     99     bimap.put(1, "one");
    100     bimap.put(0, null);
    101     bimap.put(null, "nothing");
    102     assertEquals("one", bimap.get(1));
    103     assertNull(bimap.get(0));
    104     assertEquals("nothing", bimap.get(null));
    105     assertNull(bimap.get("bad"));
    106 
    107     bimap.forcePut(null, null);
    108     assertNull(bimap.get(null));
    109     bimap.remove(null);
    110     assertNull(bimap.get(null));
    111   }
    112 
    113   public void testInverseSimple() {
    114     BiMap<String, Integer> inverse = bimap.inverse();
    115     bimap.put(1, "one");
    116     bimap.put(2, "two");
    117     assertEquals(ImmutableMap.of("one", 1, "two", 2), inverse);
    118     // see InverseBiMapTest
    119 
    120     assertSame(bimap, inverse.inverse());
    121   }
    122 
    123   public void testInversePut() {
    124     BiMap<String, Integer> inverse = bimap.inverse();
    125     bimap.put(1, "one");
    126     bimap.inverse().put("two", 2);
    127     assertEquals(ImmutableMap.of("one", 1, "two", 2), inverse);
    128     assertEquals(ImmutableMap.of(1, "one", 2, "two"), bimap);
    129   }
    130 
    131   public void testIsEmpty() {
    132     assertTrue(bimap.isEmpty());
    133     bimap.put(1, "one");
    134     assertFalse(bimap.isEmpty());
    135     bimap.remove(1);
    136     assertTrue(bimap.isEmpty());
    137   }
    138 
    139   public void testPut() {
    140     bimap.put(1, "one");
    141     assertEquals(ImmutableMap.of(1, "one"), bimap);
    142 
    143     bimap.put(2, "two");
    144     assertEquals(ImmutableMap.of(1, "one", 2, "two"), bimap);
    145 
    146     bimap.put(2, "two");
    147     assertEquals(ImmutableMap.of(1, "one", 2, "two"), bimap);
    148 
    149     bimap.put(1, "ONE");
    150     assertEquals(ImmutableMap.of(1, "ONE", 2, "two"), bimap);
    151 
    152     try {
    153       bimap.put(3, "two");
    154       fail();
    155     } catch (IllegalArgumentException e) {
    156     }
    157     assertEquals(ImmutableMap.of(1, "ONE", 2, "two"), bimap);
    158 
    159     bimap.put(-1, null);
    160     bimap.put(null, "null");
    161     Map<Integer, String> expected = Maps.newHashMap();
    162     expected.put(1, "ONE");
    163     expected.put(2, "two");
    164     expected.put(-1, null);
    165     expected.put(null, "null");
    166 
    167     assertEquals(expected, bimap);
    168 
    169     bimap.remove(-1);
    170     bimap.put(null, null);
    171 
    172     expected.remove(-1);
    173     expected.put(null, null);
    174 
    175     assertEquals(expected, bimap);
    176   }
    177 
    178   public void testPutNull() {
    179     bimap.put(-1, null);
    180     assertTrue(bimap.containsValue(null));
    181     bimap.put(1, "one");
    182     assertTrue(bimap.containsValue(null));
    183   }
    184 
    185   public void testPutAll() {
    186     bimap.put(1, "one");
    187     Map<Integer, String> newEntries = ImmutableMap.of(2, "two", 3, "three");
    188     bimap.putAll(newEntries);
    189     assertEquals(ImmutableMap.of(1, "one", 2, "two", 3, "three"), bimap);
    190   }
    191 
    192   public void testForcePut() {
    193     assertNull(bimap.forcePut(1, "one"));
    194     assertEquals(ImmutableMap.of(1, "one"), bimap);
    195     assertEquals("one", bimap.forcePut(1, "one"));
    196     assertEquals(ImmutableMap.of(1, "one"), bimap);
    197     assertEquals("one", bimap.forcePut(1, "ONE"));
    198     assertEquals(ImmutableMap.of(1, "ONE"), bimap);
    199     assertNull(bimap.forcePut(-1, "ONE")); // key 1 disappears without a trace
    200     assertEquals(ImmutableMap.of(-1, "ONE"), bimap);
    201     assertNull(bimap.forcePut(2, "two"));
    202     assertEquals(ImmutableMap.of(-1, "ONE", 2, "two"), bimap);
    203     assertEquals("two", bimap.forcePut(2, "ONE"));
    204     assertEquals(ImmutableMap.of(2, "ONE"), bimap);
    205   }
    206 
    207   public void testRemove() {
    208     Map<Integer, String> map = Maps.newHashMap();
    209     map.put(0, null);
    210     map.put(1, "one");
    211     map.put(null, "null");
    212 
    213     bimap.putAll(map);
    214     assertNull(bimap.remove(0));
    215 
    216     map.remove(0);
    217     assertEquals(map, bimap);
    218 
    219     assertEquals("null", bimap.remove(null));
    220     assertEquals(Collections.singletonMap(1, "one"), bimap);
    221 
    222     assertNull(bimap.remove(15));
    223 
    224     assertEquals("one", bimap.remove(1));
    225     assertTrue(bimap.isEmpty());
    226   }
    227 
    228   public void testSize() {
    229     assertEquals(0, bimap.size());
    230     bimap.put(1, "one");
    231     assertEquals(1, bimap.size());
    232     bimap.put(1, "ONE");
    233     assertEquals(1, bimap.size());
    234     bimap.put(2, "two");
    235     assertEquals(2, bimap.size());
    236     bimap.forcePut(1, "two");
    237     assertEquals(1, bimap.size());
    238   }
    239 
    240   public void testToString() {
    241     bimap.put(1, "one");
    242     bimap.put(2, "two");
    243 
    244     String string = bimap.toString();
    245     String expected = string.startsWith("{1")
    246         ? "{1=one, 2=two}"
    247         : "{2=two, 1=one}";
    248     assertEquals(expected, bimap.toString());
    249   }
    250 
    251   // Entry Set
    252 
    253   public void testEntrySetAdd() {
    254     try {
    255       entrySet.add(Maps.immutableEntry(1, "one"));
    256       fail();
    257     } catch (UnsupportedOperationException expected) {
    258     }
    259   }
    260 
    261   public void testEntrySetAddAll() {
    262     try {
    263       entrySet.addAll(Collections.singleton(Maps.immutableEntry(1, "one")));
    264       fail();
    265     } catch (UnsupportedOperationException expected) {
    266     }
    267   }
    268 
    269   public void testEntrySetClear() {
    270     entrySet.clear();
    271     assertTrue(entrySet.isEmpty());
    272     assertTrue(bimap.isEmpty());
    273     putOneTwoThree();
    274     entrySet.clear();
    275     assertTrue(entrySet.isEmpty());
    276     assertTrue(bimap.isEmpty());
    277   }
    278 
    279   public void testEntrySetContains() {
    280     assertFalse(entrySet.contains(Maps.immutableEntry(1, "one")));
    281     bimap.put(1, "one");
    282     assertTrue(entrySet.contains(Maps.immutableEntry(1, "one")));
    283     assertFalse(entrySet.contains(Maps.immutableEntry(1, "")));
    284     assertFalse(entrySet.contains(Maps.immutableEntry(0, "one")));
    285     assertFalse(entrySet.contains(Maps.immutableEntry(1, null)));
    286     assertFalse(entrySet.contains(Maps.immutableEntry(null, "one")));
    287     assertFalse(entrySet.contains(Maps.immutableEntry(null, null)));
    288 
    289     bimap.put(null, null);
    290     assertTrue(entrySet.contains(Maps.immutableEntry(1, "one")));
    291     assertTrue(entrySet.contains(Maps.immutableEntry(null, null)));
    292     assertFalse(entrySet.contains(Maps.immutableEntry(1, "")));
    293     assertFalse(entrySet.contains(Maps.immutableEntry(0, "one")));
    294     assertFalse(entrySet.contains(Maps.immutableEntry(1, null)));
    295     assertFalse(entrySet.contains(Maps.immutableEntry(null, "one")));
    296 
    297     bimap.put(null, "null");
    298     bimap.put(0, null);
    299     assertTrue(entrySet.contains(Maps.immutableEntry(1, "one")));
    300     assertTrue(entrySet.contains(Maps.immutableEntry(null, "null")));
    301     assertTrue(entrySet.contains(Maps.immutableEntry(0, null)));
    302     assertFalse(entrySet.contains(Maps.immutableEntry(1, "")));
    303     assertFalse(entrySet.contains(Maps.immutableEntry(0, "one")));
    304     assertFalse(entrySet.contains(Maps.immutableEntry(1, null)));
    305     assertFalse(entrySet.contains(Maps.immutableEntry(null, "one")));
    306     assertFalse(entrySet.contains(Maps.immutableEntry(null, null)));
    307   }
    308 
    309   public void testEntrySetIsEmpty() {
    310     assertTrue(entrySet.isEmpty());
    311     bimap.put(1, "one");
    312     assertFalse(entrySet.isEmpty());
    313     bimap.remove(1);
    314     assertTrue(entrySet.isEmpty());
    315   }
    316 
    317   public void testEntrySetRemove() {
    318     putOneTwoThree();
    319     assertTrue(bimap.containsKey(1));
    320     assertTrue(bimap.containsValue("one"));
    321     assertTrue(entrySet.remove(Maps.immutableEntry(1, "one")));
    322     assertFalse(bimap.containsKey(1));
    323     assertFalse(bimap.containsValue("one"));
    324     assertEquals(2, bimap.size());
    325     assertEquals(2, bimap.inverse().size());
    326     assertFalse(entrySet.remove(Maps.immutableEntry(2, "three")));
    327     assertFalse(entrySet.remove(3));
    328     assertEquals(2, bimap.size());
    329     assertEquals(2, bimap.inverse().size());
    330   }
    331 
    332   public void testEntrySetRemoveAll() {
    333     putOneTwoThree();
    334     assertTrue(bimap.containsKey(1));
    335     assertTrue(bimap.containsValue("one"));
    336     assertTrue(entrySet.removeAll(
    337         Collections.singleton(Maps.immutableEntry(1, "one"))));
    338     assertFalse(bimap.containsKey(1));
    339     assertFalse(bimap.containsValue("one"));
    340     assertEquals(2, bimap.size());
    341     assertEquals(2, bimap.inverse().size());
    342   }
    343 
    344   public void testEntrySetValue() {
    345     bimap.put(1, "one");
    346     Entry<Integer, String> entry = bimap.entrySet().iterator().next();
    347     bimap.put(2, "two");
    348     assertEquals("one", entry.getValue());
    349     bimap.put(1, "one");
    350     assertEquals("one", entry.getValue());
    351     assertEquals("one", bimap.get(1));
    352     assertEquals(Integer.valueOf(1), bimap.inverse().get("one"));
    353     bimap.put(1, "uno");
    354     assertEquals("uno", entry.getValue());
    355     assertEquals("uno", bimap.get(1));
    356     assertEquals(Integer.valueOf(1), bimap.inverse().get("uno"));
    357     assertEquals(2, bimap.size());
    358     assertEquals(2, bimap.inverse().size());
    359     try {
    360       entry.setValue("two");
    361       fail();
    362     } catch (IllegalArgumentException expected) {}
    363     assertEquals("uno", entry.getValue());
    364     assertEquals("uno", bimap.get(1));
    365     assertEquals(Integer.valueOf(1), bimap.inverse().get("uno"));
    366     assertEquals(2, bimap.size());
    367     assertEquals(2, bimap.inverse().size());
    368   }
    369 
    370   public void testEntrySetValueRemovedEntry() {
    371     bimap.put(1, "a");
    372     Entry<Integer, String> entry = bimap.entrySet().iterator().next();
    373     bimap.clear();
    374     try {
    375       entry.setValue("b");
    376       fail();
    377     } catch (IllegalStateException expected) {}
    378     assertEquals(0, bimap.size());
    379     assertEquals(0, bimap.inverse().size());
    380   }
    381 
    382   public void testEntrySetValueRemovedEntryNullOldValue() {
    383     bimap.put(1, null);
    384     Entry<Integer, String> entry = bimap.entrySet().iterator().next();
    385     bimap.clear();
    386     try {
    387       entry.setValue("b");
    388       fail();
    389     } catch (IllegalStateException expected) {}
    390     assertEquals(0, bimap.size());
    391     assertEquals(0, bimap.inverse().size());
    392   }
    393 
    394   public void testEntrySetValueRemovedEntryAddedEqualEntry() {
    395     bimap.put(1, "a");
    396     Entry<Integer, String> entry = bimap.entrySet().iterator().next();
    397     bimap.clear();
    398     bimap.put(1, "a");
    399     try {
    400       entry.setValue("b");
    401       fail();
    402     } catch (IllegalStateException expected) {}
    403     assertEquals(1, bimap.size());
    404     assertEquals("a", bimap.get(1));
    405     assertEquals(1, bimap.inverse().size());
    406     assertEquals((Integer) 1, bimap.inverse().get("a"));
    407   }
    408 
    409   public void testKeySetIteratorRemove() {
    410     putOneTwoThree();
    411     Iterator<Integer> iterator = bimap.keySet().iterator();
    412     iterator.next();
    413     iterator.remove();
    414     assertEquals(2, bimap.size());
    415     assertEquals(2, bimap.inverse().size());
    416   }
    417 
    418   public void testKeySetRemoveAll() {
    419     putOneTwoThree();
    420     Set<Integer> keySet = bimap.keySet();
    421     assertTrue(keySet.removeAll(asList(1, 3)));
    422     assertEquals(1, bimap.size());
    423     assertTrue(keySet.contains(2));
    424   }
    425 
    426   public void testKeySetRetainAll() {
    427     putOneTwoThree();
    428     Set<Integer> keySet = bimap.keySet();
    429     assertTrue(keySet.retainAll(Collections.singleton(2)));
    430     assertEquals(1, bimap.size());
    431     assertTrue(keySet.contains(2));
    432   }
    433 
    434   public void testEntriesIteratorRemove() {
    435     putOneTwoThree();
    436     Iterator<Entry<Integer, String>> iterator = bimap.entrySet().iterator();
    437     iterator.next();
    438     iterator.remove();
    439     assertEquals(2, bimap.size());
    440     assertEquals(2, bimap.inverse().size());
    441   }
    442 
    443   public void testEntriesRetainAll() {
    444     putOneTwoThree();
    445     Set<Map.Entry<Integer, String>> entries = bimap.entrySet();
    446     Map.Entry<Integer, String> entry = Maps.immutableEntry(2, "two");
    447     assertTrue(entries.retainAll(Collections.singleton(entry)));
    448     assertEquals(1, bimap.size());
    449     assertTrue(bimap.containsKey(2));
    450   }
    451 
    452   public void testValuesIteratorRemove() {
    453     putOneTwoThree();
    454     Iterator<String> iterator = bimap.values().iterator();
    455     iterator.next();
    456     iterator.remove();
    457     assertEquals(2, bimap.size());
    458     assertEquals(2, bimap.inverse().size());
    459   }
    460 
    461   public void testValuesToArray() {
    462     bimap.put(1, "one");
    463     String[] array = new String[3];
    464     array[1] = "garbage";
    465     assertSame(array, bimap.values().toArray(array));
    466     assertEquals("one", array[0]);
    467     assertNull(array[1]);
    468   }
    469 
    470   public void testValuesToString() {
    471     bimap.put(1, "one");
    472     assertEquals("[one]", bimap.values().toString());
    473   }
    474 
    475   @GwtIncompatible("SerializableTester")
    476   public void testSerialization() {
    477     bimap.put(1, "one");
    478     bimap.put(2, "two");
    479     bimap.put(3, "three");
    480     bimap.put(null, null);
    481 
    482     BiMap<Integer, String> copy =
    483         SerializableTester.reserializeAndAssert(bimap);
    484     assertEquals(bimap.inverse(), copy.inverse());
    485   }
    486 
    487   void putOneTwoThree() {
    488     bimap.put(1, "one");
    489     bimap.put(2, "two");
    490     bimap.put(3, "three");
    491   }
    492 
    493   @GwtIncompatible("used only by @GwtIncompatible code")
    494   private static class BiMapPair implements Serializable {
    495     final BiMap<Integer, String> forward;
    496     final BiMap<String, Integer> backward;
    497 
    498     BiMapPair(BiMap<Integer, String> original) {
    499       this.forward = original;
    500       this.backward = original.inverse();
    501     }
    502 
    503     private static final long serialVersionUID = 0;
    504   }
    505 
    506   @GwtIncompatible("SerializableTester")
    507   public void testSerializationWithInverseEqual() {
    508     bimap.put(1, "one");
    509     bimap.put(2, "two");
    510     bimap.put(3, "three");
    511     bimap.put(null, null);
    512 
    513     BiMapPair pair = new BiMapPair(bimap);
    514     BiMapPair copy = SerializableTester.reserialize(pair);
    515     assertEquals(pair.forward, copy.forward);
    516     assertEquals(pair.backward, copy.backward);
    517 
    518     copy.forward.put(4, "four");
    519     copy.backward.put("five", 5);
    520     assertEquals(copy.backward, copy.forward.inverse());
    521     assertEquals(copy.forward, copy.backward.inverse());
    522 
    523     assertTrue(copy.forward.containsKey(4));
    524     assertTrue(copy.forward.containsKey(5));
    525     assertTrue(copy.backward.containsValue(4));
    526     assertTrue(copy.backward.containsValue(5));
    527     assertTrue(copy.forward.containsValue("four"));
    528     assertTrue(copy.forward.containsValue("five"));
    529     assertTrue(copy.backward.containsKey("four"));
    530     assertTrue(copy.backward.containsKey("five"));
    531   }
    532 
    533   /**
    534    * The sameness checks ensure that a bimap and its inverse remain consistent,
    535    * even after the deserialized instances are updated. Also, the relationship
    536    * {@code a == b.inverse()} should continue to hold after both bimaps are
    537    * serialized and deserialized together.
    538    */
    539   @GwtIncompatible("SerializableTester")
    540   public void testSerializationWithInverseSame() {
    541     bimap.put(1, "one");
    542     bimap.put(2, "two");
    543     bimap.put(3, "three");
    544     bimap.put(null, null);
    545 
    546     BiMapPair pair = new BiMapPair(bimap);
    547     BiMapPair copy = SerializableTester.reserialize(pair);
    548     assertSame(copy.backward, copy.forward.inverse());
    549     assertSame(copy.forward, copy.backward.inverse());
    550   }
    551 }
    552