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 package com.google.common.collect.testing.google; 17 18 import static com.google.common.base.Preconditions.checkState; 19 import static com.google.common.collect.testing.features.CollectionSize.ZERO; 20 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS; 21 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES; 22 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT; 23 import static org.truth0.Truth.ASSERT; 24 25 import com.google.common.annotations.GwtCompatible; 26 import com.google.common.collect.Iterators; 27 import com.google.common.collect.Lists; 28 import com.google.common.collect.Multimap; 29 import com.google.common.collect.testing.features.CollectionSize; 30 import com.google.common.collect.testing.features.MapFeature; 31 32 import java.util.Collection; 33 import java.util.Collections; 34 import java.util.Iterator; 35 36 /** 37 * Tests for {@link Multimap#putAll(Object, Iterable)}. 38 * 39 * @author Louis Wasserman 40 */ 41 @GwtCompatible 42 public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> { 43 @CollectionSize.Require(absent = ZERO) 44 @MapFeature.Require(SUPPORTS_PUT) testPutAllNonEmptyIterableOnPresentKey()45 public void testPutAllNonEmptyIterableOnPresentKey() { 46 assertTrue(multimap().putAll(sampleKeys().e0, new Iterable<V>() { 47 @Override 48 public Iterator<V> iterator() { 49 return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator(); 50 } 51 })); 52 assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4); 53 } 54 55 @CollectionSize.Require(absent = ZERO) 56 @MapFeature.Require(SUPPORTS_PUT) testPutAllNonEmptyCollectionOnPresentKey()57 public void testPutAllNonEmptyCollectionOnPresentKey() { 58 assertTrue(multimap().putAll( 59 sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4))); 60 assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4); 61 } 62 63 @MapFeature.Require(SUPPORTS_PUT) testPutAllNonEmptyIterableOnAbsentKey()64 public void testPutAllNonEmptyIterableOnAbsentKey() { 65 assertTrue(multimap().putAll(sampleKeys().e3, new Iterable<V>() { 66 @Override 67 public Iterator<V> iterator() { 68 return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator(); 69 } 70 })); 71 assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4); 72 } 73 74 @MapFeature.Require(SUPPORTS_PUT) testPutAllNonEmptyCollectionOnAbsentKey()75 public void testPutAllNonEmptyCollectionOnAbsentKey() { 76 assertTrue(multimap().putAll( 77 sampleKeys().e3, Lists.newArrayList(sampleValues().e3, sampleValues().e4))); 78 assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4); 79 } 80 81 @CollectionSize.Require(absent = ZERO) 82 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) testPutAllNullValueOnPresentKey_supported()83 public void testPutAllNullValueOnPresentKey_supported() { 84 assertTrue(multimap().putAll(sampleKeys().e0, Lists.newArrayList(sampleValues().e3, null))); 85 assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, null); 86 } 87 88 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) testPutAllNullValueOnAbsentKey_supported()89 public void testPutAllNullValueOnAbsentKey_supported() { 90 assertTrue(multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null))); 91 assertGet(sampleKeys().e3, sampleValues().e3, null); 92 } 93 94 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) testPutAllNullValueSingle_unsupported()95 public void testPutAllNullValueSingle_unsupported() { 96 multimap().putAll(sampleKeys().e1, Lists.newArrayList((V) null)); 97 expectUnchanged(); 98 } 99 100 // In principle, it would be nice to apply these two tests to keys with existing values, too. 101 102 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) testPutAllNullValueNullLast_unsupported()103 public void testPutAllNullValueNullLast_unsupported() { 104 int size = getNumElements(); 105 106 try { 107 multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null)); 108 fail(); 109 } catch (NullPointerException expected) { 110 } 111 112 Collection<V> values = multimap().get(sampleKeys().e3); 113 if (values.size() == 0) { 114 expectUnchanged(); 115 // Be extra thorough in case internal state was corrupted by the expected null. 116 assertEquals(Lists.newArrayList(), Lists.newArrayList(values)); 117 assertEquals(size, multimap().size()); 118 } else { 119 assertEquals(Lists.newArrayList(sampleValues().e3), Lists.newArrayList(values)); 120 assertEquals(size + 1, multimap().size()); 121 } 122 } 123 124 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) testPutAllNullValueNullFirst_unsupported()125 public void testPutAllNullValueNullFirst_unsupported() { 126 int size = getNumElements(); 127 128 try { 129 multimap().putAll(sampleKeys().e3, Lists.newArrayList(null, sampleValues().e3)); 130 fail(); 131 } catch (NullPointerException expected) { 132 } 133 134 /* 135 * In principle, a Multimap implementation could add e3 first before failing on the null. But 136 * that seems unlikely enough to be worth complicating the test over, especially if there's any 137 * chance that a permissive test could mask a bug. 138 */ 139 expectUnchanged(); 140 // Be extra thorough in case internal state was corrupted by the expected null. 141 assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(sampleKeys().e3))); 142 assertEquals(size, multimap().size()); 143 } 144 145 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) testPutAllOnPresentNullKey()146 public void testPutAllOnPresentNullKey() { 147 assertTrue(multimap().putAll(null, Lists.newArrayList(sampleValues().e3, sampleValues().e4))); 148 assertGet(null, sampleValues().e3, sampleValues().e4); 149 } 150 151 @MapFeature.Require(absent = ALLOWS_NULL_KEYS) testPutAllNullForbidden()152 public void testPutAllNullForbidden() { 153 try { 154 multimap().putAll(null, Collections.singletonList(sampleValues().e3)); 155 fail("Expected NullPointerException"); 156 } catch (NullPointerException expected) { 157 // success 158 } 159 } 160 161 private static final Object[] EMPTY = new Object[0]; 162 163 @MapFeature.Require(SUPPORTS_PUT) testPutAllEmptyCollectionOnAbsentKey()164 public void testPutAllEmptyCollectionOnAbsentKey() { 165 assertFalse(multimap().putAll(sampleKeys().e3, Collections.<V>emptyList())); 166 expectUnchanged(); 167 } 168 169 @MapFeature.Require(SUPPORTS_PUT) testPutAllEmptyIterableOnAbsentKey()170 public void testPutAllEmptyIterableOnAbsentKey() { 171 Iterable<V> iterable = new Iterable<V>() { 172 @Override 173 public Iterator<V> iterator() { 174 return Iterators.emptyIterator(); 175 } 176 }; 177 178 assertFalse(multimap().putAll(sampleKeys().e3, iterable)); 179 expectUnchanged(); 180 } 181 182 @CollectionSize.Require(absent = ZERO) 183 @MapFeature.Require(SUPPORTS_PUT) testPutAllEmptyIterableOnPresentKey()184 public void testPutAllEmptyIterableOnPresentKey() { 185 multimap().putAll(sampleKeys().e0, Collections.<V>emptyList()); 186 expectUnchanged(); 187 } 188 189 @MapFeature.Require(SUPPORTS_PUT) testPutAllOnlyCallsIteratorOnce()190 public void testPutAllOnlyCallsIteratorOnce() { 191 Iterable<V> iterable = new Iterable<V>() { 192 private boolean calledIteratorAlready = false; 193 194 @Override 195 public Iterator<V> iterator() { 196 checkState(!calledIteratorAlready); 197 calledIteratorAlready = true; 198 return Iterators.forArray(sampleValues().e3); 199 } 200 }; 201 202 multimap().putAll(sampleKeys().e3, iterable); 203 } 204 205 @MapFeature.Require(SUPPORTS_PUT) testPutAllPropagatesToGet()206 public void testPutAllPropagatesToGet() { 207 Collection<V> getCollection = multimap().get(sampleKeys().e0); 208 int getCollectionSize = getCollection.size(); 209 assertTrue(multimap().putAll( 210 sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4))); 211 assertEquals(getCollectionSize + 2, getCollection.size()); 212 ASSERT.that(getCollection).has().allOf(sampleValues().e3, sampleValues().e4); 213 } 214 } 215