001/* 002 * Copyright (C) 2016 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect.testing.testers; 018 019import static com.google.common.collect.testing.features.CollectionSize.ZERO; 020import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS; 021import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES; 022import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT; 023import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE; 024import static com.google.common.collect.testing.testers.ReflectionFreeAssertThrows.assertThrows; 025 026import com.google.common.annotations.GwtCompatible; 027import com.google.common.annotations.GwtIncompatible; 028import com.google.common.annotations.J2ktIncompatible; 029import com.google.common.collect.testing.AbstractMapTester; 030import com.google.common.collect.testing.Helpers; 031import com.google.common.collect.testing.features.CollectionSize; 032import com.google.common.collect.testing.features.MapFeature; 033import com.google.common.collect.testing.testers.TestExceptions.SomeUncheckedException; 034import java.lang.reflect.Method; 035import java.util.Hashtable; 036import java.util.Map; 037import junit.framework.AssertionFailedError; 038import org.junit.Ignore; 039 040/** 041 * A generic JUnit test which tests {@link Map#merge}. Can't be invoked directly; please see {@link 042 * com.google.common.collect.testing.MapTestSuiteBuilder}. 043 * 044 * @author Louis Wasserman 045 */ 046@GwtCompatible(emulated = true) 047@Ignore("test runners must not instantiate and run this directly, only via suites we build") 048// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 049@SuppressWarnings("JUnit4ClassUsedInJUnit3") 050@IgnoreJRERequirement // We opt into library desugaring for our tests. 051public class MapMergeTester<K, V> extends AbstractMapTester<K, V> { 052 @MapFeature.Require(SUPPORTS_PUT) 053 public void testAbsent() { 054 assertEquals( 055 "Map.merge(absent, value, function) should return value", 056 v3(), 057 getMap() 058 .merge( 059 k3(), 060 v3(), 061 (oldV, newV) -> { 062 throw new AssertionFailedError( 063 "Should not call merge function if key was absent"); 064 })); 065 expectAdded(e3()); 066 } 067 068 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 069 @CollectionSize.Require(absent = ZERO) 070 public void testMappedToNull() { 071 initMapWithNullValue(); 072 assertEquals( 073 "Map.merge(keyMappedToNull, value, function) should return value", 074 v3(), 075 getMap() 076 .merge( 077 getKeyForNullValue(), 078 v3(), 079 (oldV, newV) -> { 080 throw new AssertionFailedError( 081 "Should not call merge function if key was mapped to null"); 082 })); 083 expectReplacement(entry(getKeyForNullValue(), v3())); 084 } 085 086 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) 087 public void testMergeAbsentNullKey() { 088 assertEquals( 089 "Map.merge(null, value, function) should return value", 090 v3(), 091 getMap() 092 .merge( 093 null, 094 v3(), 095 (oldV, newV) -> { 096 throw new AssertionFailedError( 097 "Should not call merge function if key was absent"); 098 })); 099 expectAdded(entry(null, v3())); 100 } 101 102 @MapFeature.Require(SUPPORTS_PUT) 103 @CollectionSize.Require(absent = ZERO) 104 public void testMergePresent() { 105 assertEquals( 106 "Map.merge(present, value, function) should return function result", 107 v4(), 108 getMap() 109 .merge( 110 k0(), 111 v3(), 112 (oldV, newV) -> { 113 assertEquals(v0(), oldV); 114 assertEquals(v3(), newV); 115 return v4(); 116 })); 117 expectReplacement(entry(k0(), v4())); 118 } 119 120 @MapFeature.Require(SUPPORTS_PUT) 121 @CollectionSize.Require(absent = ZERO) 122 public void testMergeFunctionThrows() { 123 assertThrows( 124 SomeUncheckedException.class, 125 () -> 126 getMap() 127 .merge( 128 k0(), 129 v3(), 130 (oldV, newV) -> { 131 assertEquals(v0(), oldV); 132 assertEquals(v3(), newV); 133 throw new SomeUncheckedException(); 134 })); 135 expectUnchanged(); 136 } 137 138 @MapFeature.Require(SUPPORTS_REMOVE) 139 @CollectionSize.Require(absent = ZERO) 140 public void testMergePresentToNull() { 141 assertNull( 142 "Map.merge(present, value, functionReturningNull) should return null", 143 getMap() 144 .merge( 145 k0(), 146 v3(), 147 (oldV, newV) -> { 148 assertEquals(v0(), oldV); 149 assertEquals(v3(), newV); 150 return null; 151 })); 152 expectMissing(e0()); 153 } 154 155 public void testMergeNullValue() { 156 try { 157 getMap() 158 .merge( 159 k0(), 160 null, 161 (oldV, newV) -> { 162 throw new AssertionFailedError("Should not call merge function if value was null"); 163 }); 164 fail("Expected NullPointerException or UnsupportedOperationException"); 165 } catch (NullPointerException | UnsupportedOperationException expected) { 166 } 167 } 168 169 public void testMergeNullFunction() { 170 try { 171 getMap().merge(k0(), v3(), null); 172 fail("Expected NullPointerException or UnsupportedOperationException"); 173 } catch (NullPointerException | UnsupportedOperationException expected) { 174 } 175 } 176 177 @MapFeature.Require(absent = SUPPORTS_PUT) 178 public void testMergeUnsupported() { 179 assertThrows( 180 UnsupportedOperationException.class, 181 () -> 182 getMap() 183 .merge( 184 k3(), 185 v3(), 186 (oldV, newV) -> { 187 throw new AssertionFailedError(); 188 })); 189 } 190 191 /** 192 * Returns the {@link Method} instance for {@link #testMergeNullValue()} so that tests of {@link 193 * Hashtable} can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()}. 194 */ 195 @J2ktIncompatible 196 @GwtIncompatible // reflection 197 public static Method getMergeNullValueMethod() { 198 return Helpers.getMethod(MapMergeTester.class, "testMergeNullValue"); 199 } 200}