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