1 /* 2 * Copyright (C) 2016 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.SUPPORTS_PUT; 23 import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE; 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.Hashtable; 33 import java.util.Map; 34 import junit.framework.AssertionFailedError; 35 import org.junit.Ignore; 36 37 /** 38 * A generic JUnit test which tests {@link Map#merge}. Can't be invoked directly; please see {@link 39 * com.google.common.collect.testing.MapTestSuiteBuilder}. 40 * 41 * @author Louis Wasserman 42 */ 43 @GwtCompatible(emulated = true) 44 @Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 45 public class MapMergeTester<K, V> extends AbstractMapTester<K, V> { 46 @MapFeature.Require(SUPPORTS_PUT) testAbsent()47 public void testAbsent() { 48 assertEquals( 49 "Map.merge(absent, value, function) should return value", 50 v3(), 51 getMap() 52 .merge( 53 k3(), 54 v3(), 55 (oldV, newV) -> { 56 throw new AssertionFailedError( 57 "Should not call merge function if key was absent"); 58 })); 59 expectAdded(e3()); 60 } 61 62 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 63 @CollectionSize.Require(absent = ZERO) testMappedToNull()64 public void testMappedToNull() { 65 initMapWithNullValue(); 66 assertEquals( 67 "Map.merge(keyMappedToNull, value, function) should return value", 68 v3(), 69 getMap() 70 .merge( 71 getKeyForNullValue(), 72 v3(), 73 (oldV, newV) -> { 74 throw new AssertionFailedError( 75 "Should not call merge function if key was mapped to null"); 76 })); 77 expectReplacement(entry(getKeyForNullValue(), v3())); 78 } 79 80 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) testMergeAbsentNullKey()81 public void testMergeAbsentNullKey() { 82 assertEquals( 83 "Map.merge(null, value, function) should return value", 84 v3(), 85 getMap() 86 .merge( 87 null, 88 v3(), 89 (oldV, newV) -> { 90 throw new AssertionFailedError( 91 "Should not call merge function if key was absent"); 92 })); 93 expectAdded(entry(null, v3())); 94 } 95 96 @MapFeature.Require(SUPPORTS_PUT) 97 @CollectionSize.Require(absent = ZERO) testMergePresent()98 public void testMergePresent() { 99 assertEquals( 100 "Map.merge(present, value, function) should return function result", 101 v4(), 102 getMap() 103 .merge( 104 k0(), 105 v3(), 106 (oldV, newV) -> { 107 assertEquals(v0(), oldV); 108 assertEquals(v3(), newV); 109 return v4(); 110 })); 111 expectReplacement(entry(k0(), v4())); 112 } 113 114 private static class ExpectedException extends RuntimeException {} 115 116 @MapFeature.Require(SUPPORTS_PUT) 117 @CollectionSize.Require(absent = ZERO) testMergeFunctionThrows()118 public void testMergeFunctionThrows() { 119 try { 120 getMap() 121 .merge( 122 k0(), 123 v3(), 124 (oldV, newV) -> { 125 assertEquals(v0(), oldV); 126 assertEquals(v3(), newV); 127 throw new ExpectedException(); 128 }); 129 fail("Expected ExpectedException"); 130 } catch (ExpectedException expected) { 131 } 132 expectUnchanged(); 133 } 134 135 @MapFeature.Require(SUPPORTS_REMOVE) 136 @CollectionSize.Require(absent = ZERO) testMergePresentToNull()137 public void testMergePresentToNull() { 138 assertNull( 139 "Map.merge(present, value, functionReturningNull) should return null", 140 getMap() 141 .merge( 142 k0(), 143 v3(), 144 (oldV, newV) -> { 145 assertEquals(v0(), oldV); 146 assertEquals(v3(), newV); 147 return null; 148 })); 149 expectMissing(e0()); 150 } 151 testMergeNullValue()152 public void testMergeNullValue() { 153 try { 154 getMap() 155 .merge( 156 k0(), 157 null, 158 (oldV, newV) -> { 159 throw new AssertionFailedError("Should not call merge function if value was null"); 160 }); 161 fail("Expected NullPointerException or UnsupportedOperationException"); 162 } catch (NullPointerException | UnsupportedOperationException expected) { 163 } 164 } 165 testMergeNullFunction()166 public void testMergeNullFunction() { 167 try { 168 getMap().merge(k0(), v3(), null); 169 fail("Expected NullPointerException or UnsupportedOperationException"); 170 } catch (NullPointerException | UnsupportedOperationException expected) { 171 } 172 } 173 174 @MapFeature.Require(absent = SUPPORTS_PUT) testMergeUnsupported()175 public void testMergeUnsupported() { 176 try { 177 getMap() 178 .merge( 179 k3(), 180 v3(), 181 (oldV, newV) -> { 182 throw new AssertionFailedError(); 183 }); 184 fail("Expected UnsupportedOperationException"); 185 } catch (UnsupportedOperationException expected) { 186 } 187 } 188 189 /** 190 * Returns the {@link Method} instance for {@link #testMergeNullValue()} so that tests of {@link 191 * Hashtable} can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()}. 192 */ 193 @GwtIncompatible // reflection getMergeNullValueMethod()194 public static Method getMergeNullValueMethod() { 195 return Helpers.getMethod(MapMergeTester.class, "testMergeNullValue"); 196 } 197 } 198