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