001/* 002 * Copyright (C) 2012 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.google.common.collect.testing.google; 017 018import static com.google.common.base.Preconditions.checkState; 019import static com.google.common.collect.testing.Helpers.assertContainsAllOf; 020import static com.google.common.collect.testing.features.CollectionSize.ZERO; 021import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS; 022import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES; 023import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT; 024 025import com.google.common.annotations.GwtCompatible; 026import com.google.common.collect.ImmutableSet; 027import com.google.common.collect.Iterators; 028import com.google.common.collect.Lists; 029import com.google.common.collect.Multimap; 030import com.google.common.collect.testing.features.CollectionSize; 031import com.google.common.collect.testing.features.MapFeature; 032import java.util.Collection; 033import java.util.Collections; 034import java.util.Iterator; 035import org.junit.Ignore; 036 037/** 038 * Tests for {@link Multimap#putAll(Object, Iterable)}. 039 * 040 * @author Louis Wasserman 041 */ 042@GwtCompatible 043@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 044public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> { 045 @CollectionSize.Require(absent = ZERO) 046 @MapFeature.Require(SUPPORTS_PUT) 047 public void testPutAllNonEmptyIterableOnPresentKey() { 048 assertTrue( 049 multimap() 050 .putAll( 051 k0(), 052 new Iterable<V>() { 053 @Override 054 public Iterator<V> iterator() { 055 return Lists.newArrayList(v3(), v4()).iterator(); 056 } 057 })); 058 assertGet(k0(), v0(), v3(), v4()); 059 } 060 061 @CollectionSize.Require(absent = ZERO) 062 @MapFeature.Require(SUPPORTS_PUT) 063 public void testPutAllNonEmptyCollectionOnPresentKey() { 064 assertTrue(multimap().putAll(k0(), Lists.newArrayList(v3(), v4()))); 065 assertGet(k0(), v0(), v3(), v4()); 066 } 067 068 @MapFeature.Require(SUPPORTS_PUT) 069 public void testPutAllNonEmptyIterableOnAbsentKey() { 070 assertTrue( 071 multimap() 072 .putAll( 073 k3(), 074 new Iterable<V>() { 075 @Override 076 public Iterator<V> iterator() { 077 return Lists.newArrayList(v3(), v4()).iterator(); 078 } 079 })); 080 assertGet(k3(), v3(), v4()); 081 } 082 083 @MapFeature.Require(SUPPORTS_PUT) 084 public void testPutAllNonEmptyCollectionOnAbsentKey() { 085 assertTrue(multimap().putAll(k3(), Lists.newArrayList(v3(), v4()))); 086 assertGet(k3(), v3(), v4()); 087 } 088 089 @CollectionSize.Require(absent = ZERO) 090 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 091 public void testPutAllNullValueOnPresentKey_supported() { 092 assertTrue(multimap().putAll(k0(), Lists.newArrayList(v3(), null))); 093 assertGet(k0(), v0(), v3(), null); 094 } 095 096 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 097 public void testPutAllNullValueOnAbsentKey_supported() { 098 assertTrue(multimap().putAll(k3(), Lists.newArrayList(v3(), null))); 099 assertGet(k3(), v3(), null); 100 } 101 102 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) 103 public void testPutAllNullValueSingle_unsupported() { 104 multimap().putAll(k1(), Lists.newArrayList((V) null)); 105 expectUnchanged(); 106 } 107 108 // In principle, it would be nice to apply these two tests to keys with existing values, too. 109 110 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) 111 public void testPutAllNullValueNullLast_unsupported() { 112 int size = getNumElements(); 113 114 try { 115 multimap().putAll(k3(), Lists.newArrayList(v3(), null)); 116 fail(); 117 } catch (NullPointerException expected) { 118 } 119 120 Collection<V> values = multimap().get(k3()); 121 if (values.size() == 0) { 122 expectUnchanged(); 123 // Be extra thorough in case internal state was corrupted by the expected null. 124 assertEquals(Lists.newArrayList(), Lists.newArrayList(values)); 125 assertEquals(size, multimap().size()); 126 } else { 127 assertEquals(Lists.newArrayList(v3()), Lists.newArrayList(values)); 128 assertEquals(size + 1, multimap().size()); 129 } 130 } 131 132 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES) 133 public void testPutAllNullValueNullFirst_unsupported() { 134 int size = getNumElements(); 135 136 try { 137 multimap().putAll(k3(), Lists.newArrayList(null, v3())); 138 fail(); 139 } catch (NullPointerException expected) { 140 } 141 142 /* 143 * In principle, a Multimap implementation could add e3 first before failing on the null. But 144 * that seems unlikely enough to be worth complicating the test over, especially if there's any 145 * chance that a permissive test could mask a bug. 146 */ 147 expectUnchanged(); 148 // Be extra thorough in case internal state was corrupted by the expected null. 149 assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(k3()))); 150 assertEquals(size, multimap().size()); 151 } 152 153 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) 154 public void testPutAllOnPresentNullKey() { 155 assertTrue(multimap().putAll(null, Lists.newArrayList(v3(), v4()))); 156 assertGet(null, v3(), v4()); 157 } 158 159 @MapFeature.Require(absent = ALLOWS_NULL_KEYS) 160 public void testPutAllNullForbidden() { 161 try { 162 multimap().putAll(null, Collections.singletonList(v3())); 163 fail("Expected NullPointerException"); 164 } catch (NullPointerException expected) { 165 // success 166 } 167 } 168 169 @MapFeature.Require(SUPPORTS_PUT) 170 public void testPutAllEmptyCollectionOnAbsentKey() { 171 assertFalse(multimap().putAll(k3(), Collections.<V>emptyList())); 172 expectUnchanged(); 173 } 174 175 @MapFeature.Require(SUPPORTS_PUT) 176 public void testPutAllEmptyIterableOnAbsentKey() { 177 Iterable<V> iterable = 178 new Iterable<V>() { 179 @Override 180 public Iterator<V> iterator() { 181 return ImmutableSet.<V>of().iterator(); 182 } 183 }; 184 185 assertFalse(multimap().putAll(k3(), iterable)); 186 expectUnchanged(); 187 } 188 189 @CollectionSize.Require(absent = ZERO) 190 @MapFeature.Require(SUPPORTS_PUT) 191 public void testPutAllEmptyIterableOnPresentKey() { 192 multimap().putAll(k0(), Collections.<V>emptyList()); 193 expectUnchanged(); 194 } 195 196 @MapFeature.Require(SUPPORTS_PUT) 197 public void testPutAllOnlyCallsIteratorOnce() { 198 Iterable<V> iterable = 199 new Iterable<V>() { 200 private boolean calledIteratorAlready = false; 201 202 @Override 203 public Iterator<V> iterator() { 204 checkState(!calledIteratorAlready); 205 calledIteratorAlready = true; 206 return Iterators.forArray(v3()); 207 } 208 }; 209 210 multimap().putAll(k3(), iterable); 211 } 212 213 @MapFeature.Require(SUPPORTS_PUT) 214 public void testPutAllPropagatesToGet() { 215 Collection<V> getCollection = multimap().get(k0()); 216 int getCollectionSize = getCollection.size(); 217 assertTrue(multimap().putAll(k0(), Lists.newArrayList(v3(), v4()))); 218 assertEquals(getCollectionSize + 2, getCollection.size()); 219 assertContainsAllOf(getCollection, v3(), v4()); 220 } 221}