View Javadoc
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.truth.Truth.assertThat;
20  import static java.util.Arrays.asList;
21  
22  import com.google.common.annotations.GwtCompatible;
23  import com.google.common.testing.EqualsTester;
24  
25  import junit.framework.TestCase;
26  
27  import java.util.Arrays;
28  import java.util.Collection;
29  import java.util.Iterator;
30  import java.util.Map;
31  
32  /**
33   * Unit tests for {@code LinkedHashMultimap}.
34   *
35   * @author Jared Levy
36   */
37  @GwtCompatible(emulated = true)
38  public class LinkedHashMultimapTest extends TestCase {
39  
40    public void testValueSetHashTableExpansion() {
41      LinkedHashMultimap<String, Integer> multimap = LinkedHashMultimap.create();
42      for (int z = 1; z <= 100; z++) {
43        multimap.put("a", z);
44        // The Eclipse compiler (and hence GWT) rejects a parameterized cast.
45        @SuppressWarnings("unchecked")
46        LinkedHashMultimap<String, Integer>.ValueSet valueSet =
47            (LinkedHashMultimap.ValueSet) multimap.backingMap().get("a");
48        assertEquals(z, valueSet.size());
49        assertFalse(Hashing.needsResizing(valueSet.size(), valueSet.hashTable.length, 
50            LinkedHashMultimap.VALUE_SET_LOAD_FACTOR));
51      }
52    }
53  
54    private Multimap<String, Integer> initializeMultimap5() {
55      Multimap<String, Integer> multimap = LinkedHashMultimap.create();
56      multimap.put("foo", 5);
57      multimap.put("bar", 4);
58      multimap.put("foo", 3);
59      multimap.put("cow", 2);
60      multimap.put("bar", 1);
61      return multimap;
62    }
63  
64    public void testToString() {
65      Multimap<String, Integer> multimap = LinkedHashMultimap.create();
66      multimap.put("foo", 3);
67      multimap.put("bar", 1);
68      multimap.putAll("foo", Arrays.asList(-1, 2, 4));
69      multimap.putAll("bar", Arrays.asList(2, 3));
70      multimap.put("foo", 1);
71      assertEquals("{foo=[3, -1, 2, 4, 1], bar=[1, 2, 3]}",
72          multimap.toString());
73    }
74  
75    public void testOrderingReadOnly() {
76      Multimap<String, Integer> multimap = initializeMultimap5();
77      assertOrderingReadOnly(multimap);
78    }
79  
80    public void testOrderingUnmodifiable() {
81      Multimap<String, Integer> multimap = initializeMultimap5();
82      assertOrderingReadOnly(Multimaps.unmodifiableMultimap(multimap));
83    }
84  
85    public void testOrderingSynchronized() {
86      Multimap<String, Integer> multimap = initializeMultimap5();
87      assertOrderingReadOnly(Multimaps.synchronizedMultimap(multimap));
88    }
89  
90    private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
91      assertThat(multimap.get("foo")).has().exactly(5, 3).inOrder();
92      assertThat(multimap.get("bar")).has().exactly(4, 1).inOrder();
93      assertThat(multimap.get("cow")).has().item(2);
94  
95      assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
96      assertThat(multimap.values()).has().exactly(5, 4, 3, 2, 1).inOrder();
97  
98      Iterator<Map.Entry<String, Integer>> entryIterator =
99          multimap.entries().iterator();
100     assertEquals(Maps.immutableEntry("foo", 5), entryIterator.next());
101     assertEquals(Maps.immutableEntry("bar", 4), entryIterator.next());
102     assertEquals(Maps.immutableEntry("foo", 3), entryIterator.next());
103     assertEquals(Maps.immutableEntry("cow", 2), entryIterator.next());
104     assertEquals(Maps.immutableEntry("bar", 1), entryIterator.next());
105 
106     Iterator<Map.Entry<String, Collection<Integer>>> collectionIterator =
107         multimap.asMap().entrySet().iterator();
108     Map.Entry<String, Collection<Integer>> entry = collectionIterator.next();
109     assertEquals("foo", entry.getKey());
110     assertThat(entry.getValue()).has().exactly(5, 3).inOrder();
111     entry = collectionIterator.next();
112     assertEquals("bar", entry.getKey());
113     assertThat(entry.getValue()).has().exactly(4, 1).inOrder();
114     entry = collectionIterator.next();
115     assertEquals("cow", entry.getKey());
116     assertThat(entry.getValue()).has().item(2);
117   }
118 
119   public void testOrderingUpdates() {
120     Multimap<String, Integer> multimap = initializeMultimap5();
121 
122     assertThat(multimap.replaceValues("foo", asList(6, 7))).has().exactly(5, 3).inOrder();
123     assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
124     assertThat(multimap.removeAll("foo")).has().exactly(6, 7).inOrder();
125     assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
126     assertTrue(multimap.remove("bar", 4));
127     assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
128     assertTrue(multimap.remove("bar", 1));
129     assertThat(multimap.keySet()).has().item("cow");
130     multimap.put("bar", 9);
131     assertThat(multimap.keySet()).has().exactly("cow", "bar").inOrder();
132   }
133 
134   public void testToStringNullExact() {
135     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
136 
137     multimap.put("foo", 3);
138     multimap.put("foo", -1);
139     multimap.put(null, null);
140     multimap.put("bar", 1);
141     multimap.put("foo", 2);
142     multimap.put(null, 0);
143     multimap.put("bar", 2);
144     multimap.put("bar", null);
145     multimap.put("foo", null);
146     multimap.put("foo", 4);
147     multimap.put(null, -1);
148     multimap.put("bar", 3);
149     multimap.put("bar", 1);
150     multimap.put("foo", 1);
151 
152     assertEquals(
153         "{foo=[3, -1, 2, null, 4, 1], null=[null, 0, -1], bar=[1, 2, null, 3]}",
154         multimap.toString());
155   }
156 
157   public void testPutMultimapOrdered() {
158     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
159     multimap.putAll(initializeMultimap5());
160     assertOrderingReadOnly(multimap);
161   }
162 
163   public void testKeysToString_ordering() {
164     Multimap<String, Integer> multimap = initializeMultimap5();
165     assertEquals("[foo x 2, bar x 2, cow]", multimap.keys().toString());
166   }
167 
168   public void testCreate() {
169     LinkedHashMultimap<String, Integer> multimap = LinkedHashMultimap.create();
170     multimap.put("foo", 1);
171     multimap.put("bar", 2);
172     multimap.put("foo", 3);
173     assertEquals(ImmutableSet.of(1, 3), multimap.get("foo"));
174   }
175 
176   public void testCreateFromMultimap() {
177     Multimap<String, Integer> multimap = LinkedHashMultimap.create();
178     multimap.put("a", 1);
179     multimap.put("b", 2);
180     multimap.put("a", 3);
181     multimap.put("c", 4);
182     LinkedHashMultimap<String, Integer> copy =
183         LinkedHashMultimap.create(multimap);
184     new EqualsTester()
185         .addEqualityGroup(multimap, copy)
186         .testEquals();
187   }
188 
189   public void testCreateFromSizes() {
190     LinkedHashMultimap<String, Integer> multimap
191         = LinkedHashMultimap.create(20, 15);
192     multimap.put("foo", 1);
193     multimap.put("bar", 2);
194     multimap.put("foo", 3);
195     assertEquals(ImmutableSet.of(1, 3), multimap.get("foo"));
196   }
197 
198   public void testCreateFromIllegalSizes() {
199     try {
200       LinkedHashMultimap.create(-20, 15);
201       fail();
202     } catch (IllegalArgumentException expected) {}
203 
204     try {
205       LinkedHashMultimap.create(20, -15);
206       fail();
207     } catch (IllegalArgumentException expected) {}
208   }
209 }
210