• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.common.collect;
18 
19 import static com.google.common.collect.Lists.newArrayList;
20 import static com.google.common.collect.Sets.newHashSet;
21 import static com.google.common.collect.Sets.newLinkedHashSet;
22 import static com.google.common.collect.testing.Helpers.mapEntry;
23 import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
24 import static com.google.common.truth.Truth.assertThat;
25 import static java.util.Arrays.asList;
26 
27 import com.google.common.annotations.GwtCompatible;
28 import com.google.common.annotations.GwtIncompatible;
29 import com.google.common.collect.testing.IteratorTester;
30 import com.google.common.collect.testing.features.CollectionFeature;
31 import com.google.common.collect.testing.features.CollectionSize;
32 import com.google.common.collect.testing.features.MapFeature;
33 import com.google.common.collect.testing.google.SetMultimapTestSuiteBuilder;
34 import com.google.common.collect.testing.google.TestStringSetMultimapGenerator;
35 import com.google.common.testing.EqualsTester;
36 import com.google.common.testing.SerializableTester;
37 import java.util.Arrays;
38 import java.util.Collection;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Map.Entry;
42 import java.util.Set;
43 import junit.framework.Test;
44 import junit.framework.TestCase;
45 import junit.framework.TestSuite;
46 
47 /**
48  * Unit tests for {@code LinkedHashMultimap}.
49  *
50  * @author Jared Levy
51  */
52 @GwtCompatible(emulated = true)
53 public class LinkedHashMultimapTest extends TestCase {
54 
55   @GwtIncompatible // suite
suite()56   public static Test suite() {
57     TestSuite suite = new TestSuite();
58     suite.addTest(
59         SetMultimapTestSuiteBuilder.using(
60                 new TestStringSetMultimapGenerator() {
61                   @Override
62                   protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
63                     SetMultimap<String, String> multimap = LinkedHashMultimap.create();
64                     for (Entry<String, String> entry : entries) {
65                       multimap.put(entry.getKey(), entry.getValue());
66                     }
67                     return multimap;
68                   }
69                 })
70             .named("LinkedHashMultimap")
71             .withFeatures(
72                 MapFeature.ALLOWS_NULL_KEYS,
73                 MapFeature.ALLOWS_NULL_VALUES,
74                 MapFeature.ALLOWS_ANY_NULL_QUERIES,
75                 MapFeature.GENERAL_PURPOSE,
76                 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
77                 CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
78                 CollectionFeature.KNOWN_ORDER,
79                 CollectionFeature.SERIALIZABLE,
80                 CollectionSize.ANY)
81             .createTestSuite());
82     suite.addTestSuite(LinkedHashMultimapTest.class);
83     return suite;
84   }
85 
testValueSetHashTableExpansion()86   public void testValueSetHashTableExpansion() {
87     LinkedHashMultimap<String, Integer> multimap = LinkedHashMultimap.create();
88     for (int z = 1; z <= 100; z++) {
89       multimap.put("a", z);
90       // The Eclipse compiler (and hence GWT) rejects a parameterized cast.
91       @SuppressWarnings("unchecked")
92       LinkedHashMultimap<String, Integer>.ValueSet valueSet =
93           (LinkedHashMultimap.ValueSet) multimap.backingMap().get("a");
94       assertEquals(z, valueSet.size());
95       assertFalse(
96           Hashing.needsResizing(
97               valueSet.size(),
98               valueSet.hashTable.length,
99               LinkedHashMultimap.VALUE_SET_LOAD_FACTOR));
100     }
101   }
102 
initializeMultimap5()103   private Multimap<String, Integer> initializeMultimap5() {
104     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
105     multimap.put("foo", 5);
106     multimap.put("bar", 4);
107     multimap.put("foo", 3);
108     multimap.put("cow", 2);
109     multimap.put("bar", 1);
110     return multimap;
111   }
112 
testToString()113   public void testToString() {
114     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
115     multimap.put("foo", 3);
116     multimap.put("bar", 1);
117     multimap.putAll("foo", Arrays.asList(-1, 2, 4));
118     multimap.putAll("bar", Arrays.asList(2, 3));
119     multimap.put("foo", 1);
120     assertEquals("{foo=[3, -1, 2, 4, 1], bar=[1, 2, 3]}", multimap.toString());
121   }
122 
testOrderingReadOnly()123   public void testOrderingReadOnly() {
124     Multimap<String, Integer> multimap = initializeMultimap5();
125     assertOrderingReadOnly(multimap);
126   }
127 
testOrderingUnmodifiable()128   public void testOrderingUnmodifiable() {
129     Multimap<String, Integer> multimap = initializeMultimap5();
130     assertOrderingReadOnly(Multimaps.unmodifiableMultimap(multimap));
131   }
132 
testOrderingSynchronized()133   public void testOrderingSynchronized() {
134     Multimap<String, Integer> multimap = initializeMultimap5();
135     assertOrderingReadOnly(Multimaps.synchronizedMultimap(multimap));
136   }
137 
138   @GwtIncompatible // SeriazableTester
testSerializationOrdering()139   public void testSerializationOrdering() {
140     Multimap<String, Integer> multimap = initializeMultimap5();
141     Multimap<String, Integer> copy = SerializableTester.reserializeAndAssert(multimap);
142     assertOrderingReadOnly(copy);
143   }
144 
145   @GwtIncompatible // SeriazableTester
testSerializationOrderingKeysAndEntries()146   public void testSerializationOrderingKeysAndEntries() {
147     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
148     multimap.put("a", 1);
149     multimap.put("b", 2);
150     multimap.put("a", 3);
151     multimap.put("c", 4);
152     multimap.remove("a", 1);
153     multimap = SerializableTester.reserializeAndAssert(multimap);
154     assertThat(multimap.keySet()).containsExactly("a", "b", "c").inOrder();
155     assertThat(multimap.entries())
156         .containsExactly(mapEntry("b", 2), mapEntry("a", 3), mapEntry("c", 4))
157         .inOrder();
158     // note that the keys and entries are in different orders
159   }
160 
assertOrderingReadOnly(Multimap<String, Integer> multimap)161   private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
162     assertThat(multimap.get("foo")).containsExactly(5, 3).inOrder();
163     assertThat(multimap.get("bar")).containsExactly(4, 1).inOrder();
164     assertThat(multimap.get("cow")).contains(2);
165 
166     assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
167     assertThat(multimap.values()).containsExactly(5, 4, 3, 2, 1).inOrder();
168 
169     Iterator<Entry<String, Integer>> entryIterator = multimap.entries().iterator();
170     assertEquals(Maps.immutableEntry("foo", 5), entryIterator.next());
171     assertEquals(Maps.immutableEntry("bar", 4), entryIterator.next());
172     assertEquals(Maps.immutableEntry("foo", 3), entryIterator.next());
173     assertEquals(Maps.immutableEntry("cow", 2), entryIterator.next());
174     assertEquals(Maps.immutableEntry("bar", 1), entryIterator.next());
175 
176     Iterator<Entry<String, Collection<Integer>>> collectionIterator =
177         multimap.asMap().entrySet().iterator();
178     Entry<String, Collection<Integer>> entry = collectionIterator.next();
179     assertEquals("foo", entry.getKey());
180     assertThat(entry.getValue()).containsExactly(5, 3).inOrder();
181     entry = collectionIterator.next();
182     assertEquals("bar", entry.getKey());
183     assertThat(entry.getValue()).containsExactly(4, 1).inOrder();
184     entry = collectionIterator.next();
185     assertEquals("cow", entry.getKey());
186     assertThat(entry.getValue()).contains(2);
187   }
188 
testOrderingUpdates()189   public void testOrderingUpdates() {
190     Multimap<String, Integer> multimap = initializeMultimap5();
191 
192     assertThat(multimap.replaceValues("foo", asList(6, 7))).containsExactly(5, 3).inOrder();
193     assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
194     assertThat(multimap.removeAll("foo")).containsExactly(6, 7).inOrder();
195     assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
196     assertTrue(multimap.remove("bar", 4));
197     assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
198     assertTrue(multimap.remove("bar", 1));
199     assertThat(multimap.keySet()).contains("cow");
200     multimap.put("bar", 9);
201     assertThat(multimap.keySet()).containsExactly("cow", "bar").inOrder();
202   }
203 
testToStringNullExact()204   public void testToStringNullExact() {
205     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
206 
207     multimap.put("foo", 3);
208     multimap.put("foo", -1);
209     multimap.put(null, null);
210     multimap.put("bar", 1);
211     multimap.put("foo", 2);
212     multimap.put(null, 0);
213     multimap.put("bar", 2);
214     multimap.put("bar", null);
215     multimap.put("foo", null);
216     multimap.put("foo", 4);
217     multimap.put(null, -1);
218     multimap.put("bar", 3);
219     multimap.put("bar", 1);
220     multimap.put("foo", 1);
221 
222     assertEquals(
223         "{foo=[3, -1, 2, null, 4, 1], null=[null, 0, -1], bar=[1, 2, null, 3]}",
224         multimap.toString());
225   }
226 
testPutMultimapOrdered()227   public void testPutMultimapOrdered() {
228     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
229     multimap.putAll(initializeMultimap5());
230     assertOrderingReadOnly(multimap);
231   }
232 
testKeysToString_ordering()233   public void testKeysToString_ordering() {
234     Multimap<String, Integer> multimap = initializeMultimap5();
235     assertEquals("[foo x 2, bar x 2, cow]", multimap.keys().toString());
236   }
237 
testCreate()238   public void testCreate() {
239     LinkedHashMultimap<String, Integer> multimap = LinkedHashMultimap.create();
240     multimap.put("foo", 1);
241     multimap.put("bar", 2);
242     multimap.put("foo", 3);
243     assertEquals(ImmutableSet.of(1, 3), multimap.get("foo"));
244   }
245 
testCreateFromMultimap()246   public void testCreateFromMultimap() {
247     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
248     multimap.put("a", 1);
249     multimap.put("b", 2);
250     multimap.put("a", 3);
251     multimap.put("c", 4);
252     LinkedHashMultimap<String, Integer> copy = LinkedHashMultimap.create(multimap);
253     new EqualsTester().addEqualityGroup(multimap, copy).testEquals();
254   }
255 
testCreateFromSizes()256   public void testCreateFromSizes() {
257     LinkedHashMultimap<String, Integer> multimap = LinkedHashMultimap.create(20, 15);
258     multimap.put("foo", 1);
259     multimap.put("bar", 2);
260     multimap.put("foo", 3);
261     assertEquals(ImmutableSet.of(1, 3), multimap.get("foo"));
262   }
263 
testCreateFromIllegalSizes()264   public void testCreateFromIllegalSizes() {
265     try {
266       LinkedHashMultimap.create(-20, 15);
267       fail();
268     } catch (IllegalArgumentException expected) {
269     }
270 
271     try {
272       LinkedHashMultimap.create(20, -15);
273       fail();
274     } catch (IllegalArgumentException expected) {
275     }
276   }
277 
278   @GwtIncompatible // unreasonably slow
testGetIteration()279   public void testGetIteration() {
280     new IteratorTester<Integer>(
281         6,
282         MODIFIABLE,
283         newLinkedHashSet(asList(2, 3, 4, 7, 8)),
284         IteratorTester.KnownOrder.KNOWN_ORDER) {
285       private Multimap<String, Integer> multimap;
286 
287       @Override
288       protected Iterator<Integer> newTargetIterator() {
289         multimap = LinkedHashMultimap.create();
290         multimap.putAll("foo", asList(2, 3, 4));
291         multimap.putAll("bar", asList(5, 6));
292         multimap.putAll("foo", asList(7, 8));
293         return multimap.get("foo").iterator();
294       }
295 
296       @Override
297       protected void verify(List<Integer> elements) {
298         assertEquals(newHashSet(elements), multimap.get("foo"));
299       }
300     }.test();
301   }
302 
303   @GwtIncompatible // unreasonably slow
testEntriesIteration()304   public void testEntriesIteration() {
305     @SuppressWarnings("unchecked")
306     Set<Entry<String, Integer>> set =
307         Sets.newLinkedHashSet(
308             asList(
309                 Maps.immutableEntry("foo", 2),
310                 Maps.immutableEntry("foo", 3),
311                 Maps.immutableEntry("bar", 4),
312                 Maps.immutableEntry("bar", 5),
313                 Maps.immutableEntry("foo", 6)));
314 
315     new IteratorTester<Entry<String, Integer>>(
316         6, MODIFIABLE, set, IteratorTester.KnownOrder.KNOWN_ORDER) {
317       private Multimap<String, Integer> multimap;
318 
319       @Override
320       protected Iterator<Entry<String, Integer>> newTargetIterator() {
321         multimap = LinkedHashMultimap.create();
322         multimap.putAll("foo", asList(2, 3));
323         multimap.putAll("bar", asList(4, 5));
324         multimap.putAll("foo", asList(6));
325         return multimap.entries().iterator();
326       }
327 
328       @Override
329       protected void verify(List<Entry<String, Integer>> elements) {
330         assertEquals(newHashSet(elements), multimap.entries());
331       }
332     }.test();
333   }
334 
335   @GwtIncompatible // unreasonably slow
testKeysIteration()336   public void testKeysIteration() {
337     new IteratorTester<String>(
338         6,
339         MODIFIABLE,
340         newArrayList("foo", "foo", "bar", "bar", "foo"),
341         IteratorTester.KnownOrder.KNOWN_ORDER) {
342       private Multimap<String, Integer> multimap;
343 
344       @Override
345       protected Iterator<String> newTargetIterator() {
346         multimap = LinkedHashMultimap.create();
347         multimap.putAll("foo", asList(2, 3));
348         multimap.putAll("bar", asList(4, 5));
349         multimap.putAll("foo", asList(6));
350         return multimap.keys().iterator();
351       }
352 
353       @Override
354       protected void verify(List<String> elements) {
355         assertEquals(elements, Lists.newArrayList(multimap.keys()));
356       }
357     }.test();
358   }
359 
360   @GwtIncompatible // unreasonably slow
testValuesIteration()361   public void testValuesIteration() {
362     new IteratorTester<Integer>(
363         6, MODIFIABLE, newArrayList(2, 3, 4, 5, 6), IteratorTester.KnownOrder.KNOWN_ORDER) {
364       private Multimap<String, Integer> multimap;
365 
366       @Override
367       protected Iterator<Integer> newTargetIterator() {
368         multimap = LinkedHashMultimap.create();
369         multimap.putAll("foo", asList(2, 3));
370         multimap.putAll("bar", asList(4, 5));
371         multimap.putAll("foo", asList(6));
372         return multimap.values().iterator();
373       }
374 
375       @Override
376       protected void verify(List<Integer> elements) {
377         assertEquals(elements, Lists.newArrayList(multimap.values()));
378       }
379     }.test();
380   }
381 
382   @GwtIncompatible // unreasonably slow
testKeySetIteration()383   public void testKeySetIteration() {
384     new IteratorTester<String>(
385         6,
386         MODIFIABLE,
387         newLinkedHashSet(asList("foo", "bar", "baz", "dog", "cat")),
388         IteratorTester.KnownOrder.KNOWN_ORDER) {
389       private Multimap<String, Integer> multimap;
390 
391       @Override
392       protected Iterator<String> newTargetIterator() {
393         multimap = LinkedHashMultimap.create();
394         multimap.putAll("foo", asList(2, 3));
395         multimap.putAll("bar", asList(4, 5));
396         multimap.putAll("foo", asList(6));
397         multimap.putAll("baz", asList(7, 8));
398         multimap.putAll("dog", asList(9));
399         multimap.putAll("bar", asList(10, 11));
400         multimap.putAll("cat", asList(12, 13, 14));
401         return multimap.keySet().iterator();
402       }
403 
404       @Override
405       protected void verify(List<String> elements) {
406         assertEquals(newHashSet(elements), multimap.keySet());
407       }
408     }.test();
409   }
410 
411   @GwtIncompatible // unreasonably slow
testAsSetIteration()412   public void testAsSetIteration() {
413     @SuppressWarnings("unchecked")
414     Set<Entry<String, Collection<Integer>>> set =
415         newLinkedHashSet(
416             asList(
417                 Maps.immutableEntry("foo", (Collection<Integer>) Sets.newHashSet(2, 3, 6)),
418                 Maps.immutableEntry("bar", (Collection<Integer>) Sets.newHashSet(4, 5, 10, 11)),
419                 Maps.immutableEntry("baz", (Collection<Integer>) Sets.newHashSet(7, 8)),
420                 Maps.immutableEntry("dog", (Collection<Integer>) Sets.newHashSet(9)),
421                 Maps.immutableEntry("cat", (Collection<Integer>) Sets.newHashSet(12, 13, 14))));
422     new IteratorTester<Entry<String, Collection<Integer>>>(
423         6, MODIFIABLE, set, IteratorTester.KnownOrder.KNOWN_ORDER) {
424       private Multimap<String, Integer> multimap;
425 
426       @Override
427       protected Iterator<Entry<String, Collection<Integer>>> newTargetIterator() {
428         multimap = LinkedHashMultimap.create();
429         multimap.putAll("foo", asList(2, 3));
430         multimap.putAll("bar", asList(4, 5));
431         multimap.putAll("foo", asList(6));
432         multimap.putAll("baz", asList(7, 8));
433         multimap.putAll("dog", asList(9));
434         multimap.putAll("bar", asList(10, 11));
435         multimap.putAll("cat", asList(12, 13, 14));
436         return multimap.asMap().entrySet().iterator();
437       }
438 
439       @Override
440       protected void verify(List<Entry<String, Collection<Integer>>> elements) {
441         assertEquals(newHashSet(elements), multimap.asMap().entrySet());
442       }
443     }.test();
444   }
445 }
446