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