1 /*
2  * Copyright (C) 2012 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.testing.google;
18 
19 import static org.truth0.Truth.ASSERT;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.collect.Multimap;
23 import com.google.common.collect.testing.AbstractContainerTester;
24 import com.google.common.collect.testing.Helpers;
25 import com.google.common.collect.testing.SampleElements;
26 
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.Map.Entry;
32 
33 /**
34  * Superclass for all {@code Multimap} testers.
35  *
36  * @author Louis Wasserman
37  */
38 @GwtCompatible
39 public abstract class AbstractMultimapTester<K, V, M extends Multimap<K, V>>
40     extends AbstractContainerTester<M, Map.Entry<K, V>> {
41 
42   private M multimap;
43 
multimap()44   protected M multimap() {
45     return multimap;
46   }
47 
48   /**
49    * @return an array of the proper size with {@code null} as the key of the
50    * middle element.
51    */
createArrayWithNullKey()52   protected Map.Entry<K, V>[] createArrayWithNullKey() {
53     Map.Entry<K, V>[] array = createSamplesArray();
54     final int nullKeyLocation = getNullLocation();
55     final Map.Entry<K, V> oldEntry = array[nullKeyLocation];
56     array[nullKeyLocation] = Helpers.mapEntry(null, oldEntry.getValue());
57     return array;
58   }
59 
60   /**
61    * @return an array of the proper size with {@code null} as the value of the
62    * middle element.
63    */
createArrayWithNullValue()64   protected Map.Entry<K, V>[] createArrayWithNullValue() {
65     Map.Entry<K, V>[] array = createSamplesArray();
66     final int nullValueLocation = getNullLocation();
67     final Map.Entry<K, V> oldEntry = array[nullValueLocation];
68     array[nullValueLocation] = Helpers.mapEntry(oldEntry.getKey(), null);
69     return array;
70   }
71 
72   /**
73    * @return an array of the proper size with {@code null} as the key and value of the
74    * middle element.
75    */
createArrayWithNullKeyAndValue()76   protected Map.Entry<K, V>[] createArrayWithNullKeyAndValue() {
77     Map.Entry<K, V>[] array = createSamplesArray();
78     final int nullValueLocation = getNullLocation();
79     array[nullValueLocation] = Helpers.mapEntry(null, null);
80     return array;
81   }
82 
getValueForNullKey()83   protected V getValueForNullKey() {
84     return getEntryNullReplaces().getValue();
85   }
86 
getKeyForNullValue()87   protected K getKeyForNullValue() {
88     return getEntryNullReplaces().getKey();
89   }
90 
getEntryNullReplaces()91   private Entry<K, V> getEntryNullReplaces() {
92     Iterator<Entry<K, V>> entries = getSampleElements().iterator();
93     for (int i = 0; i < getNullLocation(); i++) {
94       entries.next();
95     }
96     return entries.next();
97   }
98 
initMultimapWithNullKey()99   protected void initMultimapWithNullKey() {
100     resetContainer(getSubjectGenerator().create(createArrayWithNullKey()));
101   }
102 
initMultimapWithNullValue()103   protected void initMultimapWithNullValue() {
104     resetContainer(getSubjectGenerator().create(createArrayWithNullValue()));
105   }
106 
initMultimapWithNullKeyAndValue()107   protected void initMultimapWithNullKeyAndValue() {
108     resetContainer(getSubjectGenerator().create(createArrayWithNullKeyAndValue()));
109   }
110 
sampleKeys()111   protected SampleElements<K> sampleKeys() {
112     return ((TestMultimapGenerator<K, V, ? extends Multimap<K, V>>) getSubjectGenerator()
113         .getInnerGenerator()).sampleKeys();
114   }
115 
sampleValues()116   protected SampleElements<V> sampleValues() {
117     return ((TestMultimapGenerator<K, V, ? extends Multimap<K, V>>) getSubjectGenerator()
118         .getInnerGenerator()).sampleValues();
119   }
120 
121   @Override
actualContents()122   protected Collection<Entry<K, V>> actualContents() {
123     return multimap.entries();
124   }
125 
126   // TODO: dispose of this once collection is encapsulated.
127   @Override
resetContainer(M newContents)128   protected M resetContainer(M newContents) {
129     multimap = super.resetContainer(newContents);
130     return multimap;
131   }
132 
resetContainer(Entry<K, V>.... newContents)133   protected Multimap<K, V> resetContainer(Entry<K, V>... newContents) {
134     multimap = super.resetContainer(getSubjectGenerator().create(newContents));
135     return multimap;
136   }
137 
138   /** @see AbstractContainerTester#resetContainer() */
resetCollection()139   protected void resetCollection() {
140     resetContainer();
141   }
142 
assertGet(K key, V... values)143   protected void assertGet(K key, V... values) {
144     assertGet(key, Arrays.asList(values));
145   }
146 
assertGet(K key, Collection<V> values)147   protected void assertGet(K key, Collection<V> values) {
148     ASSERT.that(multimap().get(key)).has().exactlyAs(values);
149 
150     if (!values.isEmpty()) {
151       ASSERT.that(multimap().asMap().get(key)).has().exactlyAs(values);
152       assertFalse(multimap().isEmpty());
153     } else {
154       ASSERT.that(multimap().asMap().get(key)).isNull();
155     }
156 
157     // TODO(user): Add proper overrides to prevent autoboxing.
158     // Truth+autoboxing == compile error. Cast int to long to fix:
159     ASSERT.that(multimap().get(key).size()).is((long) values.size());
160 
161     assertEquals(values.size() > 0, multimap().containsKey(key));
162     assertEquals(values.size() > 0, multimap().keySet().contains(key));
163     assertEquals(values.size() > 0, multimap().keys().contains(key));
164   }
165 }
166