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