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.collect.ImmutableListMultimap.Builder; 24 import com.google.common.collect.testing.features.CollectionFeature; 25 import com.google.common.collect.testing.features.CollectionSize; 26 import com.google.common.collect.testing.features.MapFeature; 27 import com.google.common.collect.testing.google.ListMultimapTestSuiteBuilder; 28 import com.google.common.collect.testing.google.TestStringListMultimapGenerator; 29 import com.google.common.collect.testing.google.UnmodifiableCollectionTests; 30 import com.google.common.testing.EqualsTester; 31 import com.google.common.testing.SerializableTester; 32 33 import junit.framework.Test; 34 import junit.framework.TestCase; 35 import junit.framework.TestSuite; 36 37 import java.util.Arrays; 38 import java.util.Collection; 39 import java.util.Collections; 40 import java.util.Map.Entry; 41 42 /** 43 * Tests for {@link ImmutableListMultimap}. 44 * 45 * @author Jared Levy 46 */ 47 @GwtCompatible(emulated = true) 48 public class ImmutableListMultimapTest extends TestCase { 49 public static class ImmutableListMultimapGenerator extends TestStringListMultimapGenerator { 50 @Override create(Entry<String, String>[] entries)51 protected ListMultimap<String, String> create(Entry<String, String>[] entries) { 52 ImmutableListMultimap.Builder<String, String> builder = ImmutableListMultimap.builder(); 53 for (Entry<String, String> entry : entries) { 54 builder.put(entry.getKey(), entry.getValue()); 55 } 56 return builder.build(); 57 } 58 } 59 60 @GwtIncompatible("suite") suite()61 public static Test suite() { 62 TestSuite suite = new TestSuite(); 63 suite.addTest(ListMultimapTestSuiteBuilder.using(new ImmutableListMultimapGenerator()) 64 .named("ImmutableListMultimap") 65 .withFeatures( 66 MapFeature.ALLOWS_ANY_NULL_QUERIES, 67 CollectionFeature.SERIALIZABLE, 68 CollectionFeature.KNOWN_ORDER, 69 CollectionSize.ANY) 70 .createTestSuite()); 71 suite.addTestSuite(ImmutableListMultimapTest.class); 72 return suite; 73 } 74 testBuilder_withImmutableEntry()75 public void testBuilder_withImmutableEntry() { 76 ImmutableListMultimap<String, Integer> multimap = new Builder<String, Integer>() 77 .put(Maps.immutableEntry("one", 1)) 78 .build(); 79 assertEquals(Arrays.asList(1), multimap.get("one")); 80 } 81 testBuilder_withImmutableEntryAndNullContents()82 public void testBuilder_withImmutableEntryAndNullContents() { 83 Builder<String, Integer> builder = new Builder<String, Integer>(); 84 try { 85 builder.put(Maps.immutableEntry("one", (Integer) null)); 86 fail(); 87 } catch (NullPointerException expected) { 88 } 89 try { 90 builder.put(Maps.immutableEntry((String) null, 1)); 91 fail(); 92 } catch (NullPointerException expected) { 93 } 94 } 95 96 private static class StringHolder { 97 String string; 98 } 99 testBuilder_withMutableEntry()100 public void testBuilder_withMutableEntry() { 101 ImmutableListMultimap.Builder<String, Integer> builder = 102 new Builder<String, Integer>(); 103 final StringHolder holder = new StringHolder(); 104 holder.string = "one"; 105 Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() { 106 @Override public String getKey() { 107 return holder.string; 108 } 109 @Override public Integer getValue() { 110 return 1; 111 } 112 }; 113 114 builder.put(entry); 115 holder.string = "two"; 116 assertEquals(Arrays.asList(1), builder.build().get("one")); 117 } 118 testBuilderPutAllIterable()119 public void testBuilderPutAllIterable() { 120 ImmutableListMultimap.Builder<String, Integer> builder 121 = ImmutableListMultimap.builder(); 122 builder.putAll("foo", Arrays.asList(1, 2, 3)); 123 builder.putAll("bar", Arrays.asList(4, 5)); 124 builder.putAll("foo", Arrays.asList(6, 7)); 125 Multimap<String, Integer> multimap = builder.build(); 126 assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo")); 127 assertEquals(Arrays.asList(4, 5), multimap.get("bar")); 128 assertEquals(7, multimap.size()); 129 } 130 testBuilderPutAllVarargs()131 public void testBuilderPutAllVarargs() { 132 ImmutableListMultimap.Builder<String, Integer> builder 133 = ImmutableListMultimap.builder(); 134 builder.putAll("foo", 1, 2, 3); 135 builder.putAll("bar", 4, 5); 136 builder.putAll("foo", 6, 7); 137 Multimap<String, Integer> multimap = builder.build(); 138 assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo")); 139 assertEquals(Arrays.asList(4, 5), multimap.get("bar")); 140 assertEquals(7, multimap.size()); 141 } 142 testBuilderPutAllMultimap()143 public void testBuilderPutAllMultimap() { 144 Multimap<String, Integer> toPut = LinkedListMultimap.create(); 145 toPut.put("foo", 1); 146 toPut.put("bar", 4); 147 toPut.put("foo", 2); 148 toPut.put("foo", 3); 149 Multimap<String, Integer> moreToPut = LinkedListMultimap.create(); 150 moreToPut.put("foo", 6); 151 moreToPut.put("bar", 5); 152 moreToPut.put("foo", 7); 153 ImmutableListMultimap.Builder<String, Integer> builder 154 = ImmutableListMultimap.builder(); 155 builder.putAll(toPut); 156 builder.putAll(moreToPut); 157 Multimap<String, Integer> multimap = builder.build(); 158 assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo")); 159 assertEquals(Arrays.asList(4, 5), multimap.get("bar")); 160 assertEquals(7, multimap.size()); 161 } 162 testBuilderPutAllWithDuplicates()163 public void testBuilderPutAllWithDuplicates() { 164 ImmutableListMultimap.Builder<String, Integer> builder 165 = ImmutableListMultimap.builder(); 166 builder.putAll("foo", 1, 2, 3); 167 builder.putAll("bar", 4, 5); 168 builder.putAll("foo", 1, 6, 7); 169 ImmutableListMultimap<String, Integer> multimap = builder.build(); 170 assertEquals(Arrays.asList(1, 2, 3, 1, 6, 7), multimap.get("foo")); 171 assertEquals(Arrays.asList(4, 5), multimap.get("bar")); 172 assertEquals(8, multimap.size()); 173 } 174 testBuilderPutWithDuplicates()175 public void testBuilderPutWithDuplicates() { 176 ImmutableListMultimap.Builder<String, Integer> builder 177 = ImmutableListMultimap.builder(); 178 builder.putAll("foo", 1, 2, 3); 179 builder.putAll("bar", 4, 5); 180 builder.put("foo", 1); 181 ImmutableListMultimap<String, Integer> multimap = builder.build(); 182 assertEquals(Arrays.asList(1, 2, 3, 1), multimap.get("foo")); 183 assertEquals(Arrays.asList(4, 5), multimap.get("bar")); 184 assertEquals(6, multimap.size()); 185 } 186 testBuilderPutAllMultimapWithDuplicates()187 public void testBuilderPutAllMultimapWithDuplicates() { 188 Multimap<String, Integer> toPut = LinkedListMultimap.create(); 189 toPut.put("foo", 1); 190 toPut.put("bar", 4); 191 toPut.put("foo", 2); 192 toPut.put("foo", 1); 193 toPut.put("bar", 5); 194 Multimap<String, Integer> moreToPut = LinkedListMultimap.create(); 195 moreToPut.put("foo", 6); 196 moreToPut.put("bar", 4); 197 moreToPut.put("foo", 7); 198 moreToPut.put("foo", 2); 199 ImmutableListMultimap.Builder<String, Integer> builder 200 = ImmutableListMultimap.builder(); 201 builder.putAll(toPut); 202 builder.putAll(moreToPut); 203 Multimap<String, Integer> multimap = builder.build(); 204 assertEquals(Arrays.asList(1, 2, 1, 6, 7, 2), multimap.get("foo")); 205 assertEquals(Arrays.asList(4, 5, 4), multimap.get("bar")); 206 assertEquals(9, multimap.size()); 207 } 208 testBuilderPutNullKey()209 public void testBuilderPutNullKey() { 210 Multimap<String, Integer> toPut = LinkedListMultimap.create(); 211 toPut.put("foo", null); 212 ImmutableListMultimap.Builder<String, Integer> builder 213 = ImmutableListMultimap.builder(); 214 try { 215 builder.put(null, 1); 216 fail(); 217 } catch (NullPointerException expected) {} 218 try { 219 builder.putAll(null, Arrays.asList(1, 2, 3)); 220 fail(); 221 } catch (NullPointerException expected) {} 222 try { 223 builder.putAll(null, 1, 2, 3); 224 fail(); 225 } catch (NullPointerException expected) {} 226 try { 227 builder.putAll(toPut); 228 fail(); 229 } catch (NullPointerException expected) {} 230 } 231 testBuilderPutNullValue()232 public void testBuilderPutNullValue() { 233 Multimap<String, Integer> toPut = LinkedListMultimap.create(); 234 toPut.put(null, 1); 235 ImmutableListMultimap.Builder<String, Integer> builder 236 = ImmutableListMultimap.builder(); 237 try { 238 builder.put("foo", null); 239 fail(); 240 } catch (NullPointerException expected) {} 241 try { 242 builder.putAll("foo", Arrays.asList(1, null, 3)); 243 fail(); 244 } catch (NullPointerException expected) {} 245 try { 246 builder.putAll("foo", 1, null, 3); 247 fail(); 248 } catch (NullPointerException expected) {} 249 try { 250 builder.putAll(toPut); 251 fail(); 252 } catch (NullPointerException expected) {} 253 } 254 testBuilderOrderKeysBy()255 public void testBuilderOrderKeysBy() { 256 ImmutableListMultimap.Builder<String, Integer> builder 257 = ImmutableListMultimap.builder(); 258 builder.put("b", 3); 259 builder.put("d", 2); 260 builder.put("a", 5); 261 builder.orderKeysBy(Collections.reverseOrder()); 262 builder.put("c", 4); 263 builder.put("a", 2); 264 builder.put("b", 6); 265 ImmutableListMultimap<String, Integer> multimap = builder.build(); 266 assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder(); 267 assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder(); 268 assertThat(multimap.get("a")).has().exactly(5, 2).inOrder(); 269 assertThat(multimap.get("b")).has().exactly(3, 6).inOrder(); 270 } 271 testBuilderOrderKeysByDuplicates()272 public void testBuilderOrderKeysByDuplicates() { 273 ImmutableListMultimap.Builder<String, Integer> builder 274 = ImmutableListMultimap.builder(); 275 builder.put("bb", 3); 276 builder.put("d", 2); 277 builder.put("a", 5); 278 builder.orderKeysBy(new Ordering<String>() { 279 @Override 280 public int compare(String left, String right) { 281 return left.length() - right.length(); 282 } 283 }); 284 builder.put("cc", 4); 285 builder.put("a", 2); 286 builder.put("bb", 6); 287 ImmutableListMultimap<String, Integer> multimap = builder.build(); 288 assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder(); 289 assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder(); 290 assertThat(multimap.get("a")).has().exactly(5, 2).inOrder(); 291 assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder(); 292 } 293 testBuilderOrderValuesBy()294 public void testBuilderOrderValuesBy() { 295 ImmutableListMultimap.Builder<String, Integer> builder 296 = ImmutableListMultimap.builder(); 297 builder.put("b", 3); 298 builder.put("d", 2); 299 builder.put("a", 5); 300 builder.orderValuesBy(Collections.reverseOrder()); 301 builder.put("c", 4); 302 builder.put("a", 2); 303 builder.put("b", 6); 304 ImmutableListMultimap<String, Integer> multimap = builder.build(); 305 assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder(); 306 assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder(); 307 assertThat(multimap.get("a")).has().exactly(5, 2).inOrder(); 308 assertThat(multimap.get("b")).has().exactly(6, 3).inOrder(); 309 } 310 testBuilderOrderKeysAndValuesBy()311 public void testBuilderOrderKeysAndValuesBy() { 312 ImmutableListMultimap.Builder<String, Integer> builder 313 = ImmutableListMultimap.builder(); 314 builder.put("b", 3); 315 builder.put("d", 2); 316 builder.put("a", 5); 317 builder.orderKeysBy(Collections.reverseOrder()); 318 builder.orderValuesBy(Collections.reverseOrder()); 319 builder.put("c", 4); 320 builder.put("a", 2); 321 builder.put("b", 6); 322 ImmutableListMultimap<String, Integer> multimap = builder.build(); 323 assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder(); 324 assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder(); 325 assertThat(multimap.get("a")).has().exactly(5, 2).inOrder(); 326 assertThat(multimap.get("b")).has().exactly(6, 3).inOrder(); 327 } 328 testCopyOf()329 public void testCopyOf() { 330 ArrayListMultimap<String, Integer> input = ArrayListMultimap.create(); 331 input.put("foo", 1); 332 input.put("bar", 2); 333 input.put("foo", 3); 334 Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input); 335 assertEquals(multimap, input); 336 assertEquals(input, multimap); 337 } 338 testCopyOfWithDuplicates()339 public void testCopyOfWithDuplicates() { 340 ArrayListMultimap<String, Integer> input = ArrayListMultimap.create(); 341 input.put("foo", 1); 342 input.put("bar", 2); 343 input.put("foo", 3); 344 input.put("foo", 1); 345 Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input); 346 assertEquals(multimap, input); 347 assertEquals(input, multimap); 348 } 349 testCopyOfEmpty()350 public void testCopyOfEmpty() { 351 ArrayListMultimap<String, Integer> input = ArrayListMultimap.create(); 352 Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input); 353 assertEquals(multimap, input); 354 assertEquals(input, multimap); 355 } 356 testCopyOfImmutableListMultimap()357 public void testCopyOfImmutableListMultimap() { 358 Multimap<String, Integer> multimap = createMultimap(); 359 assertSame(multimap, ImmutableListMultimap.copyOf(multimap)); 360 } 361 testCopyOfNullKey()362 public void testCopyOfNullKey() { 363 ArrayListMultimap<String, Integer> input = ArrayListMultimap.create(); 364 input.put(null, 1); 365 try { 366 ImmutableListMultimap.copyOf(input); 367 fail(); 368 } catch (NullPointerException expected) {} 369 } 370 testCopyOfNullValue()371 public void testCopyOfNullValue() { 372 ArrayListMultimap<String, Integer> input = ArrayListMultimap.create(); 373 input.putAll("foo", Arrays.asList(1, null, 3)); 374 try { 375 ImmutableListMultimap.copyOf(input); 376 fail(); 377 } catch (NullPointerException expected) {} 378 } 379 testEmptyMultimapReads()380 public void testEmptyMultimapReads() { 381 Multimap<String, Integer> multimap = ImmutableListMultimap.of(); 382 assertFalse(multimap.containsKey("foo")); 383 assertFalse(multimap.containsValue(1)); 384 assertFalse(multimap.containsEntry("foo", 1)); 385 assertTrue(multimap.entries().isEmpty()); 386 assertTrue(multimap.equals(ArrayListMultimap.create())); 387 assertEquals(Collections.emptyList(), multimap.get("foo")); 388 assertEquals(0, multimap.hashCode()); 389 assertTrue(multimap.isEmpty()); 390 assertEquals(HashMultiset.create(), multimap.keys()); 391 assertEquals(Collections.emptySet(), multimap.keySet()); 392 assertEquals(0, multimap.size()); 393 assertTrue(multimap.values().isEmpty()); 394 assertEquals("{}", multimap.toString()); 395 } 396 testEmptyMultimapWrites()397 public void testEmptyMultimapWrites() { 398 Multimap<String, Integer> multimap = ImmutableListMultimap.of(); 399 UnmodifiableCollectionTests.assertMultimapIsUnmodifiable( 400 multimap, "foo", 1); 401 } 402 createMultimap()403 private Multimap<String, Integer> createMultimap() { 404 return ImmutableListMultimap.<String, Integer>builder() 405 .put("foo", 1).put("bar", 2).put("foo", 3).build(); 406 } 407 testMultimapReads()408 public void testMultimapReads() { 409 Multimap<String, Integer> multimap = createMultimap(); 410 assertTrue(multimap.containsKey("foo")); 411 assertFalse(multimap.containsKey("cat")); 412 assertTrue(multimap.containsValue(1)); 413 assertFalse(multimap.containsValue(5)); 414 assertTrue(multimap.containsEntry("foo", 1)); 415 assertFalse(multimap.containsEntry("cat", 1)); 416 assertFalse(multimap.containsEntry("foo", 5)); 417 assertFalse(multimap.entries().isEmpty()); 418 assertEquals(3, multimap.size()); 419 assertFalse(multimap.isEmpty()); 420 assertEquals("{foo=[1, 3], bar=[2]}", multimap.toString()); 421 } 422 testMultimapWrites()423 public void testMultimapWrites() { 424 Multimap<String, Integer> multimap = createMultimap(); 425 UnmodifiableCollectionTests.assertMultimapIsUnmodifiable( 426 multimap, "bar", 2); 427 } 428 testMultimapEquals()429 public void testMultimapEquals() { 430 Multimap<String, Integer> multimap = createMultimap(); 431 Multimap<String, Integer> arrayListMultimap 432 = ArrayListMultimap.create(); 433 arrayListMultimap.putAll("foo", Arrays.asList(1, 3)); 434 arrayListMultimap.put("bar", 2); 435 436 new EqualsTester() 437 .addEqualityGroup(multimap, createMultimap(), arrayListMultimap, 438 ImmutableListMultimap.<String, Integer>builder() 439 .put("bar", 2).put("foo", 1).put("foo", 3).build()) 440 .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder() 441 .put("bar", 2).put("foo", 3).put("foo", 1).build()) 442 .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder() 443 .put("foo", 2).put("foo", 3).put("foo", 1).build()) 444 .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder() 445 .put("bar", 2).put("foo", 3).build()) 446 .testEquals(); 447 } 448 testOf()449 public void testOf() { 450 assertMultimapEquals( 451 ImmutableListMultimap.of("one", 1), 452 "one", 1); 453 assertMultimapEquals( 454 ImmutableListMultimap.of("one", 1, "two", 2), 455 "one", 1, "two", 2); 456 assertMultimapEquals( 457 ImmutableListMultimap.of("one", 1, "two", 2, "three", 3), 458 "one", 1, "two", 2, "three", 3); 459 assertMultimapEquals( 460 ImmutableListMultimap.of("one", 1, "two", 2, "three", 3, "four", 4), 461 "one", 1, "two", 2, "three", 3, "four", 4); 462 assertMultimapEquals( 463 ImmutableListMultimap.of( 464 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5), 465 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); 466 } 467 testInverse()468 public void testInverse() { 469 assertEquals( 470 ImmutableListMultimap.<Integer, String>of(), 471 ImmutableListMultimap.<String, Integer>of().inverse()); 472 assertEquals( 473 ImmutableListMultimap.of(1, "one"), 474 ImmutableListMultimap.of("one", 1).inverse()); 475 assertEquals( 476 ImmutableListMultimap.of(1, "one", 2, "two"), 477 ImmutableListMultimap.of("one", 1, "two", 2).inverse()); 478 assertEquals( 479 ImmutableListMultimap.of("of", 'o', "of", 'f', "to", 't', "to", 'o').inverse(), 480 ImmutableListMultimap.of('o', "of", 'f', "of", 't', "to", 'o', "to")); 481 assertEquals( 482 ImmutableListMultimap.of('f', "foo", 'o', "foo", 'o', "foo"), 483 ImmutableListMultimap.of("foo", 'f', "foo", 'o', "foo", 'o').inverse()); 484 } 485 testInverseMinimizesWork()486 public void testInverseMinimizesWork() { 487 ImmutableListMultimap<String, Character> multimap = 488 ImmutableListMultimap.<String, Character>builder() 489 .put("foo", 'f') 490 .put("foo", 'o') 491 .put("foo", 'o') 492 .put("poo", 'p') 493 .put("poo", 'o') 494 .put("poo", 'o') 495 .build(); 496 assertSame(multimap.inverse(), multimap.inverse()); 497 assertSame(multimap, multimap.inverse().inverse()); 498 } 499 assertMultimapEquals(Multimap<K, V> multimap, Object... alternatingKeysAndValues)500 private static <K, V> void assertMultimapEquals(Multimap<K, V> multimap, 501 Object... alternatingKeysAndValues) { 502 assertEquals(multimap.size(), alternatingKeysAndValues.length / 2); 503 int i = 0; 504 for (Entry<K, V> entry : multimap.entries()) { 505 assertEquals(alternatingKeysAndValues[i++], entry.getKey()); 506 assertEquals(alternatingKeysAndValues[i++], entry.getValue()); 507 } 508 } 509 510 @GwtIncompatible("SerializableTester") testSerialization()511 public void testSerialization() { 512 Multimap<String, Integer> multimap = createMultimap(); 513 SerializableTester.reserializeAndAssert(multimap); 514 assertEquals(multimap.size(), 515 SerializableTester.reserialize(multimap).size()); 516 SerializableTester.reserializeAndAssert(multimap.get("foo")); 517 LenientSerializableTester.reserializeAndAssertLenient(multimap.keySet()); 518 LenientSerializableTester.reserializeAndAssertLenient(multimap.keys()); 519 SerializableTester.reserializeAndAssert(multimap.asMap()); 520 Collection<Integer> valuesCopy 521 = SerializableTester.reserialize(multimap.values()); 522 assertEquals(HashMultiset.create(multimap.values()), 523 HashMultiset.create(valuesCopy)); 524 } 525 526 @GwtIncompatible("SerializableTester") testEmptySerialization()527 public void testEmptySerialization() { 528 Multimap<String, Integer> multimap = ImmutableListMultimap.of(); 529 assertSame(multimap, SerializableTester.reserialize(multimap)); 530 } 531 } 532