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; 023 024import com.google.common.annotations.GwtCompatible; 025import com.google.common.collect.testing.AbstractMapTester; 026import com.google.common.collect.testing.features.CollectionSize; 027import com.google.common.collect.testing.features.MapFeature; 028import java.util.Map; 029import junit.framework.AssertionFailedError; 030import org.junit.Ignore; 031 032/** 033 * A generic JUnit test which tests {@link Map#computeIfAbsent}. Can't be invoked directly; please 034 * see {@link com.google.common.collect.testing.MapTestSuiteBuilder}. 035 * 036 * @author Louis Wasserman 037 */ 038@GwtCompatible 039@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 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 static class ExpectedException extends RuntimeException {} 116 117 @MapFeature.Require(SUPPORTS_PUT) 118 public void testComputeIfAbsent_functionThrows() { 119 try { 120 getMap() 121 .computeIfAbsent( 122 k3(), 123 k -> { 124 assertEquals(k3(), k); 125 throw new ExpectedException(); 126 }); 127 fail("Expected ExpectedException"); 128 } catch (ExpectedException expected) { 129 } 130 expectUnchanged(); 131 } 132 133 @MapFeature.Require(absent = SUPPORTS_PUT) 134 public void testComputeIfAbsent_unsupportedAbsent() { 135 try { 136 getMap() 137 .computeIfAbsent( 138 k3(), 139 k -> { 140 // allowed to be called 141 assertEquals(k3(), k); 142 return v3(); 143 }); 144 fail("computeIfAbsent(notPresent, function) should throw"); 145 } catch (UnsupportedOperationException expected) { 146 } 147 expectUnchanged(); 148 } 149 150 @MapFeature.Require(absent = SUPPORTS_PUT) 151 @CollectionSize.Require(absent = ZERO) 152 public void testComputeIfAbsent_unsupportedPresentExistingValue() { 153 try { 154 assertEquals( 155 "computeIfAbsent(present, returnsCurrentValue) should return present or throw", 156 v0(), 157 getMap() 158 .computeIfAbsent( 159 k0(), 160 k -> { 161 assertEquals(k0(), k); 162 return v0(); 163 })); 164 } catch (UnsupportedOperationException tolerated) { 165 } 166 expectUnchanged(); 167 } 168 169 @MapFeature.Require(absent = SUPPORTS_PUT) 170 @CollectionSize.Require(absent = ZERO) 171 public void testComputeIfAbsent_unsupportedPresentDifferentValue() { 172 try { 173 assertEquals( 174 "computeIfAbsent(present, returnsDifferentValue) should return present or throw", 175 v0(), 176 getMap() 177 .computeIfAbsent( 178 k0(), 179 k -> { 180 assertEquals(k0(), k); 181 return v3(); 182 })); 183 } catch (UnsupportedOperationException tolerated) { 184 } 185 expectUnchanged(); 186 } 187 188 @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS) 189 public void testComputeIfAbsent_nullKeyUnsupported() { 190 try { 191 getMap() 192 .computeIfAbsent( 193 null, 194 k -> { 195 assertNull(k); 196 return v3(); 197 }); 198 fail("computeIfAbsent(null, function) should throw"); 199 } catch (NullPointerException expected) { 200 } 201 expectUnchanged(); 202 expectNullKeyMissingWhenNullKeysUnsupported( 203 "Should not contain null key after unsupported computeIfAbsent(null, function)"); 204 } 205}