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