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