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; 024 025import com.google.common.annotations.GwtCompatible; 026import com.google.common.annotations.GwtIncompatible; 027import com.google.common.annotations.J2ktIncompatible; 028import com.google.common.collect.testing.AbstractMapTester; 029import com.google.common.collect.testing.Helpers; 030import com.google.common.collect.testing.features.CollectionSize; 031import com.google.common.collect.testing.features.MapFeature; 032import java.lang.reflect.Method; 033import java.util.Hashtable; 034import java.util.Map; 035import junit.framework.AssertionFailedError; 036import org.junit.Ignore; 037 038/** 039 * A generic JUnit test which tests {@link Map#merge}. Can't be invoked directly; please see {@link 040 * com.google.common.collect.testing.MapTestSuiteBuilder}. 041 * 042 * @author Louis Wasserman 043 */ 044@GwtCompatible(emulated = true) 045@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 046public class MapMergeTester<K, V> extends AbstractMapTester<K, V> { 047 @MapFeature.Require(SUPPORTS_PUT) 048 public void testAbsent() { 049 assertEquals( 050 "Map.merge(absent, value, function) should return value", 051 v3(), 052 getMap() 053 .merge( 054 k3(), 055 v3(), 056 (oldV, newV) -> { 057 throw new AssertionFailedError( 058 "Should not call merge function if key was absent"); 059 })); 060 expectAdded(e3()); 061 } 062 063 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 064 @CollectionSize.Require(absent = ZERO) 065 public void testMappedToNull() { 066 initMapWithNullValue(); 067 assertEquals( 068 "Map.merge(keyMappedToNull, value, function) should return value", 069 v3(), 070 getMap() 071 .merge( 072 getKeyForNullValue(), 073 v3(), 074 (oldV, newV) -> { 075 throw new AssertionFailedError( 076 "Should not call merge function if key was mapped to null"); 077 })); 078 expectReplacement(entry(getKeyForNullValue(), v3())); 079 } 080 081 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) 082 public void testMergeAbsentNullKey() { 083 assertEquals( 084 "Map.merge(null, value, function) should return value", 085 v3(), 086 getMap() 087 .merge( 088 null, 089 v3(), 090 (oldV, newV) -> { 091 throw new AssertionFailedError( 092 "Should not call merge function if key was absent"); 093 })); 094 expectAdded(entry(null, v3())); 095 } 096 097 @MapFeature.Require(SUPPORTS_PUT) 098 @CollectionSize.Require(absent = ZERO) 099 public void testMergePresent() { 100 assertEquals( 101 "Map.merge(present, value, function) should return function result", 102 v4(), 103 getMap() 104 .merge( 105 k0(), 106 v3(), 107 (oldV, newV) -> { 108 assertEquals(v0(), oldV); 109 assertEquals(v3(), newV); 110 return v4(); 111 })); 112 expectReplacement(entry(k0(), v4())); 113 } 114 115 private static class ExpectedException extends RuntimeException {} 116 117 @MapFeature.Require(SUPPORTS_PUT) 118 @CollectionSize.Require(absent = ZERO) 119 public void testMergeFunctionThrows() { 120 try { 121 getMap() 122 .merge( 123 k0(), 124 v3(), 125 (oldV, newV) -> { 126 assertEquals(v0(), oldV); 127 assertEquals(v3(), newV); 128 throw new ExpectedException(); 129 }); 130 fail("Expected ExpectedException"); 131 } catch (ExpectedException expected) { 132 } 133 expectUnchanged(); 134 } 135 136 @MapFeature.Require(SUPPORTS_REMOVE) 137 @CollectionSize.Require(absent = ZERO) 138 public void testMergePresentToNull() { 139 assertNull( 140 "Map.merge(present, value, functionReturningNull) should return null", 141 getMap() 142 .merge( 143 k0(), 144 v3(), 145 (oldV, newV) -> { 146 assertEquals(v0(), oldV); 147 assertEquals(v3(), newV); 148 return null; 149 })); 150 expectMissing(e0()); 151 } 152 153 public void testMergeNullValue() { 154 try { 155 getMap() 156 .merge( 157 k0(), 158 null, 159 (oldV, newV) -> { 160 throw new AssertionFailedError("Should not call merge function if value was null"); 161 }); 162 fail("Expected NullPointerException or UnsupportedOperationException"); 163 } catch (NullPointerException | UnsupportedOperationException expected) { 164 } 165 } 166 167 public void testMergeNullFunction() { 168 try { 169 getMap().merge(k0(), v3(), null); 170 fail("Expected NullPointerException or UnsupportedOperationException"); 171 } catch (NullPointerException | UnsupportedOperationException expected) { 172 } 173 } 174 175 @MapFeature.Require(absent = SUPPORTS_PUT) 176 public void testMergeUnsupported() { 177 try { 178 getMap() 179 .merge( 180 k3(), 181 v3(), 182 (oldV, newV) -> { 183 throw new AssertionFailedError(); 184 }); 185 fail("Expected UnsupportedOperationException"); 186 } catch (UnsupportedOperationException expected) { 187 } 188 } 189 190 /** 191 * Returns the {@link Method} instance for {@link #testMergeNullValue()} so that tests of {@link 192 * Hashtable} can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()}. 193 */ 194 @J2ktIncompatible 195 @GwtIncompatible // reflection 196 public static Method getMergeNullValueMethod() { 197 return Helpers.getMethod(MapMergeTester.class, "testMergeNullValue"); 198 } 199}