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 17package com.google.common.collect; 18 19import static java.util.Arrays.asList; 20 21import com.google.common.annotations.GwtCompatible; 22import com.google.common.annotations.GwtIncompatible; 23import com.google.common.testing.SerializableTester; 24 25import junit.framework.TestCase; 26 27import java.io.Serializable; 28import java.util.Collections; 29import java.util.Iterator; 30import java.util.Map; 31import java.util.Map.Entry; 32import java.util.Set; 33 34/** 35 * Common tests for any {@code BiMap}. 36 * 37 * @author Kevin Bourrillion 38 */ 39@GwtCompatible(emulated = true) 40public 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