• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.testers;
18 
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.FAILS_FAST_ON_CONCURRENT_MODIFICATION;
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.annotations.GwtIncompatible;
27 import com.google.common.collect.testing.AbstractMapTester;
28 import com.google.common.collect.testing.Helpers;
29 import com.google.common.collect.testing.features.CollectionSize;
30 import com.google.common.collect.testing.features.MapFeature;
31 
32 import java.lang.reflect.Method;
33 import java.util.ConcurrentModificationException;
34 import java.util.Iterator;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 
38 /**
39  * A generic JUnit test which tests {@code put} operations on a map. Can't be
40  * invoked directly; please see
41  * {@link com.google.common.collect.testing.MapTestSuiteBuilder}.
42  *
43  * @author Chris Povirk
44  * @author Kevin Bourrillion
45  */
46 @SuppressWarnings("unchecked") // too many "unchecked generic array creations"
47 @GwtCompatible(emulated = true)
48 public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
49   private Entry<K, V> nullKeyEntry;
50   private Entry<K, V> nullValueEntry;
51   private Entry<K, V> nullKeyValueEntry;
52   private Entry<K, V> presentKeyNullValueEntry;
53 
setUp()54   @Override public void setUp() throws Exception {
55     super.setUp();
56     nullKeyEntry = entry(null, samples.e3.getValue());
57     nullValueEntry = entry(samples.e3.getKey(), null);
58     nullKeyValueEntry = entry(null, null);
59     presentKeyNullValueEntry = entry(samples.e0.getKey(), null);
60   }
61 
62   @MapFeature.Require(SUPPORTS_PUT)
testPut_supportedNotPresent()63   public void testPut_supportedNotPresent() {
64     assertNull("put(notPresent, value) should return null", put(samples.e3));
65     expectAdded(samples.e3);
66   }
67 
68   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
69   @CollectionSize.Require(absent = ZERO)
testPutAbsentConcurrentWithEntrySetIteration()70   public void testPutAbsentConcurrentWithEntrySetIteration() {
71     try {
72       Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
73       put(samples.e3);
74       iterator.next();
75       fail("Expected ConcurrentModificationException");
76     } catch (ConcurrentModificationException expected) {
77       // success
78     }
79   }
80 
81   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
82   @CollectionSize.Require(absent = ZERO)
testPutAbsentConcurrentWithKeySetIteration()83   public void testPutAbsentConcurrentWithKeySetIteration() {
84     try {
85       Iterator<K> iterator = getMap().keySet().iterator();
86       put(samples.e3);
87       iterator.next();
88       fail("Expected ConcurrentModificationException");
89     } catch (ConcurrentModificationException expected) {
90       // success
91     }
92   }
93 
94   @MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
95   @CollectionSize.Require(absent = ZERO)
testPutAbsentConcurrentWithValueIteration()96   public void testPutAbsentConcurrentWithValueIteration() {
97     try {
98       Iterator<V> iterator = getMap().values().iterator();
99       put(samples.e3);
100       iterator.next();
101       fail("Expected ConcurrentModificationException");
102     } catch (ConcurrentModificationException expected) {
103       // success
104     }
105   }
106 
107   @MapFeature.Require(absent = SUPPORTS_PUT)
testPut_unsupportedNotPresent()108   public void testPut_unsupportedNotPresent() {
109     try {
110       put(samples.e3);
111       fail("put(notPresent, value) should throw");
112     } catch (UnsupportedOperationException expected) {
113     }
114     expectUnchanged();
115     expectMissing(samples.e3);
116   }
117 
118   @MapFeature.Require(absent = SUPPORTS_PUT)
119   @CollectionSize.Require(absent = ZERO)
testPut_unsupportedPresentExistingValue()120   public void testPut_unsupportedPresentExistingValue() {
121     try {
122       assertEquals("put(present, existingValue) should return present or throw",
123           samples.e0.getValue(), put(samples.e0));
124     } catch (UnsupportedOperationException tolerated) {
125     }
126     expectUnchanged();
127   }
128 
129   @MapFeature.Require(absent = SUPPORTS_PUT)
130   @CollectionSize.Require(absent = ZERO)
testPut_unsupportedPresentDifferentValue()131   public void testPut_unsupportedPresentDifferentValue() {
132     try {
133       getMap().put(samples.e0.getKey(), samples.e3.getValue());
134       fail("put(present, differentValue) should throw");
135     } catch (UnsupportedOperationException expected) {
136     }
137     expectUnchanged();
138   }
139 
140   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
testPut_nullKeySupportedNotPresent()141   public void testPut_nullKeySupportedNotPresent() {
142     assertNull("put(null, value) should return null", put(nullKeyEntry));
143     expectAdded(nullKeyEntry);
144   }
145 
146   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
147   @CollectionSize.Require(absent = ZERO)
testPut_nullKeySupportedPresent()148   public void testPut_nullKeySupportedPresent() {
149     Entry<K, V> newEntry = entry(null, samples.e3.getValue());
150     initMapWithNullKey();
151     assertEquals("put(present, value) should return the associated value",
152         getValueForNullKey(), put(newEntry));
153 
154     Entry<K, V>[] expected = createArrayWithNullKey();
155     expected[getNullLocation()] = newEntry;
156     expectContents(expected);
157   }
158 
159   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
testPut_nullKeyUnsupported()160   public void testPut_nullKeyUnsupported() {
161     try {
162       put(nullKeyEntry);
163       fail("put(null, value) should throw");
164     } catch (NullPointerException expected) {
165     }
166     expectUnchanged();
167     expectNullKeyMissingWhenNullKeysUnsupported(
168         "Should not contain null key after unsupported put(null, value)");
169   }
170 
171   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
testPut_nullValueSupported()172   public void testPut_nullValueSupported() {
173     assertNull("put(key, null) should return null", put(nullValueEntry));
174     expectAdded(nullValueEntry);
175   }
176 
177   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
testPut_nullValueUnsupported()178   public void testPut_nullValueUnsupported() {
179     try {
180       put(nullValueEntry);
181       fail("put(key, null) should throw");
182     } catch (NullPointerException expected) {
183     }
184     expectUnchanged();
185     expectNullValueMissingWhenNullValuesUnsupported(
186         "Should not contain null value after unsupported put(key, null)");
187   }
188 
189   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
190   @CollectionSize.Require(absent = ZERO)
testPut_replaceWithNullValueSupported()191   public void testPut_replaceWithNullValueSupported() {
192     assertEquals("put(present, null) should return the associated value",
193         samples.e0.getValue(), put(presentKeyNullValueEntry));
194     expectReplacement(presentKeyNullValueEntry);
195   }
196 
197   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
198   @CollectionSize.Require(absent = ZERO)
testPut_replaceWithNullValueUnsupported()199   public void testPut_replaceWithNullValueUnsupported() {
200     try {
201       put(presentKeyNullValueEntry);
202       fail("put(present, null) should throw");
203     } catch (NullPointerException expected) {
204     }
205     expectUnchanged();
206     expectNullValueMissingWhenNullValuesUnsupported(
207         "Should not contain null after unsupported put(present, null)");
208   }
209 
210   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
211   @CollectionSize.Require(absent = ZERO)
testPut_replaceNullValueWithNullSupported()212   public void testPut_replaceNullValueWithNullSupported() {
213     initMapWithNullValue();
214     assertNull("put(present, null) should return the associated value (null)",
215         getMap().put(getKeyForNullValue(), null));
216     expectContents(createArrayWithNullValue());
217   }
218 
219   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
220   @CollectionSize.Require(absent = ZERO)
testPut_replaceNullValueWithNonNullSupported()221   public void testPut_replaceNullValueWithNonNullSupported() {
222     Entry<K, V> newEntry = entry(getKeyForNullValue(), samples.e3.getValue());
223     initMapWithNullValue();
224     assertNull("put(present, value) should return the associated value (null)",
225         put(newEntry));
226 
227     Entry<K, V>[] expected = createArrayWithNullValue();
228     expected[getNullLocation()] = newEntry;
229     expectContents(expected);
230   }
231 
232   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS, ALLOWS_NULL_VALUES})
testPut_nullKeyAndValueSupported()233   public void testPut_nullKeyAndValueSupported() {
234     assertNull("put(null, null) should return null", put(nullKeyValueEntry));
235     expectAdded(nullKeyValueEntry);
236   }
237 
put(Map.Entry<K, V> entry)238   private V put(Map.Entry<K, V> entry) {
239     return getMap().put(entry.getKey(), entry.getValue());
240   }
241 
242   /**
243    * Returns the {@link Method} instance for {@link
244    * #testPut_nullKeyUnsupported()} so that tests of {@link java.util.TreeMap}
245    * can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()}
246    * until <a
247    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045147">Sun bug
248    * 5045147</a> is fixed.
249    */
250   @GwtIncompatible("reflection")
getPutNullKeyUnsupportedMethod()251   public static Method getPutNullKeyUnsupportedMethod() {
252     return Helpers.getMethod(MapPutTester.class, "testPut_nullKeyUnsupported");
253   }
254 }
255