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