001/* 002 * Copyright (C) 2015 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.testers.ReflectionFreeAssertThrows.assertThrows; 024 025import com.google.common.annotations.GwtCompatible; 026import com.google.common.collect.testing.AbstractMapTester; 027import com.google.common.collect.testing.features.CollectionSize; 028import com.google.common.collect.testing.features.MapFeature; 029import com.google.common.collect.testing.testers.TestExceptions.SomeUncheckedException; 030import java.util.Map; 031import junit.framework.AssertionFailedError; 032import org.junit.Ignore; 033 034/** 035 * A generic JUnit test which tests {@link Map#computeIfAbsent}. Can't be invoked directly; please 036 * see {@link com.google.common.collect.testing.MapTestSuiteBuilder}. 037 * 038 * @author Louis Wasserman 039 */ 040@GwtCompatible 041@Ignore("test runners must not instantiate and run this directly, only via suites we build") 042// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 043@SuppressWarnings("JUnit4ClassUsedInJUnit3") 044@IgnoreJRERequirement // We opt into library desugaring for our tests. 045public class MapComputeIfAbsentTester<K, V> extends AbstractMapTester<K, V> { 046 047 @MapFeature.Require(SUPPORTS_PUT) 048 public void testComputeIfAbsent_supportedAbsent() { 049 assertEquals( 050 "computeIfAbsent(notPresent, function) should return new value", 051 v3(), 052 getMap() 053 .computeIfAbsent( 054 k3(), 055 k -> { 056 assertEquals(k3(), k); 057 return v3(); 058 })); 059 expectAdded(e3()); 060 } 061 062 @MapFeature.Require(SUPPORTS_PUT) 063 @CollectionSize.Require(absent = ZERO) 064 public void testComputeIfAbsent_supportedPresent() { 065 assertEquals( 066 "computeIfAbsent(present, function) should return existing value", 067 v0(), 068 getMap() 069 .computeIfAbsent( 070 k0(), 071 k -> { 072 throw new AssertionFailedError(); 073 })); 074 expectUnchanged(); 075 } 076 077 @MapFeature.Require(SUPPORTS_PUT) 078 public void testComputeIfAbsent_functionReturnsNullNotInserted() { 079 assertNull( 080 "computeIfAbsent(absent, returnsNull) should return null", 081 getMap() 082 .computeIfAbsent( 083 k3(), 084 k -> { 085 assertEquals(k3(), k); 086 return null; 087 })); 088 expectUnchanged(); 089 } 090 091 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES}) 092 @CollectionSize.Require(absent = ZERO) 093 public void testComputeIfAbsent_nullTreatedAsAbsent() { 094 initMapWithNullValue(); 095 assertEquals( 096 "computeIfAbsent(presentAssignedToNull, function) should return newValue", 097 getValueForNullKey(), 098 getMap() 099 .computeIfAbsent( 100 getKeyForNullValue(), 101 k -> { 102 assertEquals(getKeyForNullValue(), k); 103 return getValueForNullKey(); 104 })); 105 expectReplacement(entry(getKeyForNullValue(), getValueForNullKey())); 106 } 107 108 @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS}) 109 public void testComputeIfAbsent_nullKeySupported() { 110 getMap() 111 .computeIfAbsent( 112 null, 113 k -> { 114 assertNull(k); 115 return v3(); 116 }); 117 expectAdded(entry(null, v3())); 118 } 119 120 @MapFeature.Require(SUPPORTS_PUT) 121 public void testComputeIfAbsent_functionThrows() { 122 assertThrows( 123 SomeUncheckedException.class, 124 () -> 125 getMap() 126 .computeIfAbsent( 127 k3(), 128 k -> { 129 assertEquals(k3(), k); 130 throw new SomeUncheckedException(); 131 })); 132 expectUnchanged(); 133 } 134 135 @MapFeature.Require(absent = SUPPORTS_PUT) 136 public void testComputeIfAbsent_unsupportedAbsent() { 137 assertThrows( 138 UnsupportedOperationException.class, 139 () -> 140 getMap() 141 .computeIfAbsent( 142 k3(), 143 k -> { 144 // allowed to be called 145 assertEquals(k3(), k); 146 return v3(); 147 })); 148 expectUnchanged(); 149 } 150 151 @MapFeature.Require(absent = SUPPORTS_PUT) 152 @CollectionSize.Require(absent = ZERO) 153 public void testComputeIfAbsent_unsupportedPresentExistingValue() { 154 try { 155 assertEquals( 156 "computeIfAbsent(present, returnsCurrentValue) should return present or throw", 157 v0(), 158 getMap() 159 .computeIfAbsent( 160 k0(), 161 k -> { 162 assertEquals(k0(), k); 163 return v0(); 164 })); 165 } catch (UnsupportedOperationException tolerated) { 166 } 167 expectUnchanged(); 168 } 169 170 @MapFeature.Require(absent = SUPPORTS_PUT) 171 @CollectionSize.Require(absent = ZERO) 172 public void testComputeIfAbsent_unsupportedPresentDifferentValue() { 173 try { 174 assertEquals( 175 "computeIfAbsent(present, returnsDifferentValue) should return present or throw", 176 v0(), 177 getMap() 178 .computeIfAbsent( 179 k0(), 180 k -> { 181 assertEquals(k0(), k); 182 return v3(); 183 })); 184 } catch (UnsupportedOperationException tolerated) { 185 } 186 expectUnchanged(); 187 } 188 189 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS) 190 public void testComputeIfAbsent_nullKeyUnsupported() { 191 assertThrows( 192 NullPointerException.class, 193 () -> 194 getMap() 195 .computeIfAbsent( 196 null, 197 k -> { 198 assertNull(k); 199 return v3(); 200 })); 201 expectUnchanged(); 202 expectNullKeyMissingWhenNullKeysUnsupported( 203 "Should not contain null key after unsupported computeIfAbsent(null, function)"); 204 } 205}