1 /* 2 * Copyright (C) 2008 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 com.google.common.truth.Truth.assertThat; 20 21 import com.google.common.annotations.GwtCompatible; 22 import com.google.common.annotations.GwtIncompatible; 23 import com.google.common.base.Joiner; 24 import com.google.common.collect.ImmutableBiMap.Builder; 25 import com.google.common.collect.testing.MapInterfaceTest; 26 import com.google.common.collect.testing.features.CollectionFeature; 27 import com.google.common.collect.testing.features.CollectionSize; 28 import com.google.common.collect.testing.features.MapFeature; 29 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfGenerator; 30 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapGenerator; 31 import com.google.common.collect.testing.google.BiMapInverseTester; 32 import com.google.common.collect.testing.google.BiMapTestSuiteBuilder; 33 import com.google.common.testing.SerializableTester; 34 35 import junit.framework.Test; 36 import junit.framework.TestCase; 37 import junit.framework.TestSuite; 38 39 import java.util.Collections; 40 import java.util.LinkedHashMap; 41 import java.util.Map; 42 import java.util.Map.Entry; 43 import java.util.Set; 44 45 /** 46 * Tests for {@link ImmutableBiMap}. 47 * 48 * @author Jared Levy 49 */ 50 @GwtCompatible(emulated = true) 51 public class ImmutableBiMapTest extends TestCase { 52 53 // TODO: Reduce duplication of ImmutableMapTest code 54 55 @GwtIncompatible("suite") suite()56 public static Test suite() { 57 TestSuite suite = new TestSuite(); 58 59 suite.addTestSuite(MapTests.class); 60 suite.addTestSuite(InverseMapTests.class); 61 suite.addTestSuite(CreationTests.class); 62 suite.addTestSuite(BiMapSpecificTests.class); 63 64 suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapGenerator()) 65 .named("ImmutableBiMap") 66 .withFeatures(CollectionSize.ANY, 67 CollectionFeature.SERIALIZABLE, 68 CollectionFeature.KNOWN_ORDER, 69 MapFeature.REJECTS_DUPLICATES_AT_CREATION, 70 MapFeature.ALLOWS_ANY_NULL_QUERIES) 71 .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods()) 72 .createTestSuite()); 73 suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfGenerator()) 74 .named("ImmutableBiMap.copyOf") 75 .withFeatures(CollectionSize.ANY, 76 CollectionFeature.SERIALIZABLE, 77 CollectionFeature.KNOWN_ORDER, 78 MapFeature.ALLOWS_ANY_NULL_QUERIES) 79 .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods()) 80 .createTestSuite()); 81 82 return suite; 83 } 84 85 public static abstract class AbstractMapTests<K, V> 86 extends MapInterfaceTest<K, V> { AbstractMapTests()87 public AbstractMapTests() { 88 super(false, false, false, false, false); 89 } 90 makeEmptyMap()91 @Override protected Map<K, V> makeEmptyMap() { 92 throw new UnsupportedOperationException(); 93 } 94 95 private static final Joiner joiner = Joiner.on(", "); 96 assertMoreInvariants(Map<K, V> map)97 @Override protected void assertMoreInvariants(Map<K, V> map) { 98 99 BiMap<K, V> bimap = (BiMap<K, V>) map; 100 101 for (Entry<K, V> entry : map.entrySet()) { 102 assertEquals(entry.getKey() + "=" + entry.getValue(), 103 entry.toString()); 104 assertEquals(entry.getKey(), bimap.inverse().get(entry.getValue())); 105 } 106 107 assertEquals("{" + joiner.join(map.entrySet()) + "}", 108 map.toString()); 109 assertEquals("[" + joiner.join(map.entrySet()) + "]", 110 map.entrySet().toString()); 111 assertEquals("[" + joiner.join(map.keySet()) + "]", 112 map.keySet().toString()); 113 assertEquals("[" + joiner.join(map.values()) + "]", 114 map.values().toString()); 115 116 assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet()); 117 assertEquals(Sets.newHashSet(map.keySet()), map.keySet()); 118 } 119 } 120 121 public static class MapTests extends AbstractMapTests<String, Integer> { makeEmptyMap()122 @Override protected Map<String, Integer> makeEmptyMap() { 123 return ImmutableBiMap.of(); 124 } 125 makePopulatedMap()126 @Override protected Map<String, Integer> makePopulatedMap() { 127 return ImmutableBiMap.of("one", 1, "two", 2, "three", 3); 128 } 129 getKeyNotInPopulatedMap()130 @Override protected String getKeyNotInPopulatedMap() { 131 return "minus one"; 132 } 133 getValueNotInPopulatedMap()134 @Override protected Integer getValueNotInPopulatedMap() { 135 return -1; 136 } 137 } 138 139 public static class InverseMapTests 140 extends AbstractMapTests<String, Integer> { makeEmptyMap()141 @Override protected Map<String, Integer> makeEmptyMap() { 142 return ImmutableBiMap.of(); 143 } 144 makePopulatedMap()145 @Override protected Map<String, Integer> makePopulatedMap() { 146 return ImmutableBiMap.of(1, "one", 2, "two", 3, "three").inverse(); 147 } 148 getKeyNotInPopulatedMap()149 @Override protected String getKeyNotInPopulatedMap() { 150 return "minus one"; 151 } 152 getValueNotInPopulatedMap()153 @Override protected Integer getValueNotInPopulatedMap() { 154 return -1; 155 } 156 } 157 158 public static class CreationTests extends TestCase { testEmptyBuilder()159 public void testEmptyBuilder() { 160 ImmutableBiMap<String, Integer> map 161 = new Builder<String, Integer>().build(); 162 assertEquals(Collections.<String, Integer>emptyMap(), map); 163 assertEquals(Collections.<Integer, String>emptyMap(), map.inverse()); 164 assertSame(ImmutableBiMap.of(), map); 165 } 166 testSingletonBuilder()167 public void testSingletonBuilder() { 168 ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() 169 .put("one", 1) 170 .build(); 171 assertMapEquals(map, "one", 1); 172 assertMapEquals(map.inverse(), 1, "one"); 173 } 174 testBuilder()175 public void testBuilder() { 176 ImmutableBiMap<String, Integer> map 177 = ImmutableBiMap.<String, Integer>builder() 178 .put("one", 1) 179 .put("two", 2) 180 .put("three", 3) 181 .put("four", 4) 182 .put("five", 5) 183 .build(); 184 assertMapEquals(map, 185 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); 186 assertMapEquals(map.inverse(), 187 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); 188 } 189 testBuilderPutAllWithEmptyMap()190 public void testBuilderPutAllWithEmptyMap() { 191 ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() 192 .putAll(Collections.<String, Integer>emptyMap()) 193 .build(); 194 assertEquals(Collections.<String, Integer>emptyMap(), map); 195 } 196 testBuilderPutAll()197 public void testBuilderPutAll() { 198 Map<String, Integer> toPut = new LinkedHashMap<String, Integer>(); 199 toPut.put("one", 1); 200 toPut.put("two", 2); 201 toPut.put("three", 3); 202 Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>(); 203 moreToPut.put("four", 4); 204 moreToPut.put("five", 5); 205 206 ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() 207 .putAll(toPut) 208 .putAll(moreToPut) 209 .build(); 210 assertMapEquals(map, 211 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); 212 assertMapEquals(map.inverse(), 213 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); 214 } 215 testBuilderReuse()216 public void testBuilderReuse() { 217 Builder<String, Integer> builder = new Builder<String, Integer>(); 218 ImmutableBiMap<String, Integer> mapOne = builder 219 .put("one", 1) 220 .put("two", 2) 221 .build(); 222 ImmutableBiMap<String, Integer> mapTwo = builder 223 .put("three", 3) 224 .put("four", 4) 225 .build(); 226 227 assertMapEquals(mapOne, "one", 1, "two", 2); 228 assertMapEquals(mapOne.inverse(), 1, "one", 2, "two"); 229 assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4); 230 assertMapEquals(mapTwo.inverse(), 231 1, "one", 2, "two", 3, "three", 4, "four"); 232 } 233 testBuilderPutNullKey()234 public void testBuilderPutNullKey() { 235 Builder<String, Integer> builder = new Builder<String, Integer>(); 236 try { 237 builder.put(null, 1); 238 fail(); 239 } catch (NullPointerException expected) { 240 } 241 } 242 testBuilderPutNullValue()243 public void testBuilderPutNullValue() { 244 Builder<String, Integer> builder = new Builder<String, Integer>(); 245 try { 246 builder.put("one", null); 247 fail(); 248 } catch (NullPointerException expected) { 249 } 250 } 251 testBuilderPutNullKeyViaPutAll()252 public void testBuilderPutNullKeyViaPutAll() { 253 Builder<String, Integer> builder = new Builder<String, Integer>(); 254 try { 255 builder.putAll(Collections.<String, Integer>singletonMap(null, 1)); 256 fail(); 257 } catch (NullPointerException expected) { 258 } 259 } 260 testBuilderPutNullValueViaPutAll()261 public void testBuilderPutNullValueViaPutAll() { 262 Builder<String, Integer> builder = new Builder<String, Integer>(); 263 try { 264 builder.putAll(Collections.<String, Integer>singletonMap("one", null)); 265 fail(); 266 } catch (NullPointerException expected) { 267 } 268 } 269 testPuttingTheSameKeyTwiceThrowsOnBuild()270 public void testPuttingTheSameKeyTwiceThrowsOnBuild() { 271 Builder<String, Integer> builder = new Builder<String, Integer>() 272 .put("one", 1) 273 .put("one", 1); // throwing on this line would be even better 274 275 try { 276 builder.build(); 277 fail(); 278 } catch (IllegalArgumentException expected) { 279 assertTrue(expected.getMessage().contains("one")); 280 } 281 } 282 testOf()283 public void testOf() { 284 assertMapEquals( 285 ImmutableBiMap.of("one", 1), 286 "one", 1); 287 assertMapEquals( 288 ImmutableBiMap.of("one", 1).inverse(), 289 1, "one"); 290 assertMapEquals( 291 ImmutableBiMap.of("one", 1, "two", 2), 292 "one", 1, "two", 2); 293 assertMapEquals( 294 ImmutableBiMap.of("one", 1, "two", 2).inverse(), 295 1, "one", 2, "two"); 296 assertMapEquals( 297 ImmutableBiMap.of("one", 1, "two", 2, "three", 3), 298 "one", 1, "two", 2, "three", 3); 299 assertMapEquals( 300 ImmutableBiMap.of("one", 1, "two", 2, "three", 3).inverse(), 301 1, "one", 2, "two", 3, "three"); 302 assertMapEquals( 303 ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4), 304 "one", 1, "two", 2, "three", 3, "four", 4); 305 assertMapEquals( 306 ImmutableBiMap.of( 307 "one", 1, "two", 2, "three", 3, "four", 4).inverse(), 308 1, "one", 2, "two", 3, "three", 4, "four"); 309 assertMapEquals( 310 ImmutableBiMap.of( 311 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5), 312 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); 313 assertMapEquals( 314 ImmutableBiMap.of( 315 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5).inverse(), 316 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); 317 } 318 testOfNullKey()319 public void testOfNullKey() { 320 try { 321 ImmutableBiMap.of(null, 1); 322 fail(); 323 } catch (NullPointerException expected) { 324 } 325 326 try { 327 ImmutableBiMap.of("one", 1, null, 2); 328 fail(); 329 } catch (NullPointerException expected) { 330 } 331 } 332 testOfNullValue()333 public void testOfNullValue() { 334 try { 335 ImmutableBiMap.of("one", null); 336 fail(); 337 } catch (NullPointerException expected) { 338 } 339 340 try { 341 ImmutableBiMap.of("one", 1, "two", null); 342 fail(); 343 } catch (NullPointerException expected) { 344 } 345 } 346 testOfWithDuplicateKey()347 public void testOfWithDuplicateKey() { 348 try { 349 ImmutableBiMap.of("one", 1, "one", 1); 350 fail(); 351 } catch (IllegalArgumentException expected) { 352 assertTrue(expected.getMessage().contains("one")); 353 } 354 } 355 testCopyOfEmptyMap()356 public void testCopyOfEmptyMap() { 357 ImmutableBiMap<String, Integer> copy 358 = ImmutableBiMap.copyOf(Collections.<String, Integer>emptyMap()); 359 assertEquals(Collections.<String, Integer>emptyMap(), copy); 360 assertSame(copy, ImmutableBiMap.copyOf(copy)); 361 assertSame(ImmutableBiMap.of(), copy); 362 } 363 testCopyOfSingletonMap()364 public void testCopyOfSingletonMap() { 365 ImmutableBiMap<String, Integer> copy 366 = ImmutableBiMap.copyOf(Collections.singletonMap("one", 1)); 367 assertMapEquals(copy, "one", 1); 368 assertSame(copy, ImmutableBiMap.copyOf(copy)); 369 } 370 testCopyOf()371 public void testCopyOf() { 372 Map<String, Integer> original = new LinkedHashMap<String, Integer>(); 373 original.put("one", 1); 374 original.put("two", 2); 375 original.put("three", 3); 376 377 ImmutableBiMap<String, Integer> copy = ImmutableBiMap.copyOf(original); 378 assertMapEquals(copy, "one", 1, "two", 2, "three", 3); 379 assertSame(copy, ImmutableBiMap.copyOf(copy)); 380 } 381 testEmpty()382 public void testEmpty() { 383 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of(); 384 assertEquals(Collections.<String, Integer>emptyMap(), bimap); 385 assertEquals(Collections.<String, Integer>emptyMap(), bimap.inverse()); 386 } 387 testFromHashMap()388 public void testFromHashMap() { 389 Map<String, Integer> hashMap = Maps.newLinkedHashMap(); 390 hashMap.put("one", 1); 391 hashMap.put("two", 2); 392 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 393 ImmutableMap.of("one", 1, "two", 2)); 394 assertMapEquals(bimap, "one", 1, "two", 2); 395 assertMapEquals(bimap.inverse(), 1, "one", 2, "two"); 396 } 397 testFromImmutableMap()398 public void testFromImmutableMap() { 399 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 400 new ImmutableMap.Builder<String, Integer>() 401 .put("one", 1) 402 .put("two", 2) 403 .put("three", 3) 404 .put("four", 4) 405 .put("five", 5) 406 .build()); 407 assertMapEquals(bimap, 408 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); 409 assertMapEquals(bimap.inverse(), 410 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); 411 } 412 testDuplicateValues()413 public void testDuplicateValues() { 414 ImmutableMap<String, Integer> map 415 = new ImmutableMap.Builder<String, Integer>() 416 .put("one", 1) 417 .put("two", 2) 418 .put("uno", 1) 419 .put("dos", 2) 420 .build(); 421 422 try { 423 ImmutableBiMap.copyOf(map); 424 fail(); 425 } catch (IllegalArgumentException expected) { 426 assertTrue(expected.getMessage().contains("1")); 427 } 428 } 429 } 430 431 public static class BiMapSpecificTests extends TestCase { 432 433 @SuppressWarnings("deprecation") testForcePut()434 public void testForcePut() { 435 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 436 ImmutableMap.of("one", 1, "two", 2)); 437 try { 438 bimap.forcePut("three", 3); 439 fail(); 440 } catch (UnsupportedOperationException expected) {} 441 } 442 testKeySet()443 public void testKeySet() { 444 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 445 ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4)); 446 Set<String> keys = bimap.keySet(); 447 assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys); 448 assertThat(keys).has().exactly("one", "two", "three", "four").inOrder(); 449 } 450 testValues()451 public void testValues() { 452 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 453 ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4)); 454 Set<Integer> values = bimap.values(); 455 assertEquals(Sets.newHashSet(1, 2, 3, 4), values); 456 assertThat(values).has().exactly(1, 2, 3, 4).inOrder(); 457 } 458 testDoubleInverse()459 public void testDoubleInverse() { 460 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 461 ImmutableMap.of("one", 1, "two", 2)); 462 assertSame(bimap, bimap.inverse().inverse()); 463 } 464 465 @GwtIncompatible("SerializableTester") testEmptySerialization()466 public void testEmptySerialization() { 467 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of(); 468 assertSame(bimap, SerializableTester.reserializeAndAssert(bimap)); 469 } 470 471 @GwtIncompatible("SerializableTester") testSerialization()472 public void testSerialization() { 473 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 474 ImmutableMap.of("one", 1, "two", 2)); 475 ImmutableBiMap<String, Integer> copy = 476 SerializableTester.reserializeAndAssert(bimap); 477 assertEquals(Integer.valueOf(1), copy.get("one")); 478 assertEquals("one", copy.inverse().get(1)); 479 assertSame(copy, copy.inverse().inverse()); 480 } 481 482 @GwtIncompatible("SerializableTester") testInverseSerialization()483 public void testInverseSerialization() { 484 ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( 485 ImmutableMap.of(1, "one", 2, "two")).inverse(); 486 ImmutableBiMap<String, Integer> copy = 487 SerializableTester.reserializeAndAssert(bimap); 488 assertEquals(Integer.valueOf(1), copy.get("one")); 489 assertEquals("one", copy.inverse().get(1)); 490 assertSame(copy, copy.inverse().inverse()); 491 } 492 } 493 assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues)494 private static <K, V> void assertMapEquals(Map<K, V> map, 495 Object... alternatingKeysAndValues) { 496 int i = 0; 497 for (Entry<K, V> entry : map.entrySet()) { 498 assertEquals(alternatingKeysAndValues[i++], entry.getKey()); 499 assertEquals(alternatingKeysAndValues[i++], entry.getValue()); 500 } 501 } 502 } 503