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 java.util.Map;
030import java.util.Map.Entry;
031import org.junit.Ignore;
032
033/**
034 * A generic JUnit test which tests {@link Map#putIfAbsent}. Can't be invoked directly; please see
035 * {@link com.google.common.collect.testing.MapTestSuiteBuilder}.
036 *
037 * @author Louis Wasserman
038 */
039@GwtCompatible
040@Ignore("test runners must not instantiate and run this directly, only via suites we build")
041// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
042@SuppressWarnings("JUnit4ClassUsedInJUnit3")
043public class MapPutIfAbsentTester<K, V> extends AbstractMapTester<K, V> {
044
045  @MapFeature.Require(SUPPORTS_PUT)
046  public void testPutIfAbsent_supportedAbsent() {
047    assertNull(
048        "putIfAbsent(notPresent, value) should return null", getMap().putIfAbsent(k3(), v3()));
049    expectAdded(e3());
050  }
051
052  @MapFeature.Require(SUPPORTS_PUT)
053  @CollectionSize.Require(absent = ZERO)
054  public void testPutIfAbsent_supportedPresent() {
055    assertEquals(
056        "putIfAbsent(present, value) should return existing value",
057        v0(),
058        getMap().putIfAbsent(k0(), v3()));
059    expectUnchanged();
060  }
061
062  @MapFeature.Require(absent = SUPPORTS_PUT)
063  public void testPutIfAbsent_unsupportedAbsent() {
064    assertThrows(UnsupportedOperationException.class, () -> getMap().putIfAbsent(k3(), v3()));
065    expectUnchanged();
066    expectMissing(e3());
067  }
068
069  @MapFeature.Require(absent = SUPPORTS_PUT)
070  @CollectionSize.Require(absent = ZERO)
071  public void testPutIfAbsent_unsupportedPresentExistingValue() {
072    try {
073      assertEquals(
074          "putIfAbsent(present, existingValue) should return present or throw",
075          v0(),
076          getMap().putIfAbsent(k0(), v0()));
077    } catch (UnsupportedOperationException tolerated) {
078    }
079    expectUnchanged();
080  }
081
082  @MapFeature.Require(absent = SUPPORTS_PUT)
083  @CollectionSize.Require(absent = ZERO)
084  public void testPutIfAbsent_unsupportedPresentDifferentValue() {
085    try {
086      getMap().putIfAbsent(k0(), v3());
087    } catch (UnsupportedOperationException tolerated) {
088    }
089    expectUnchanged();
090  }
091
092  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
093  public void testPutIfAbsent_nullKeyUnsupported() {
094    assertThrows(NullPointerException.class, () -> getMap().putIfAbsent(null, v3()));
095    expectUnchanged();
096    expectNullKeyMissingWhenNullKeysUnsupported(
097        "Should not contain null key after unsupported putIfAbsent(null, value)");
098  }
099
100  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
101  public void testPutIfAbsent_nullValueUnsupportedAndKeyAbsent() {
102    assertThrows(NullPointerException.class, () -> getMap().putIfAbsent(k3(), null));
103    expectUnchanged();
104    expectNullValueMissingWhenNullValuesUnsupported(
105        "Should not contain null value after unsupported putIfAbsent(key, null)");
106  }
107
108  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
109  @CollectionSize.Require(absent = ZERO)
110  public void testPutIfAbsent_nullValueUnsupportedAndKeyPresent() {
111    try {
112      getMap().putIfAbsent(k0(), null);
113    } catch (NullPointerException tolerated) {
114    }
115    expectUnchanged();
116    expectNullValueMissingWhenNullValuesUnsupported(
117        "Should not contain null after unsupported putIfAbsent(present, null)");
118  }
119
120  @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
121  public void testPut_nullValueSupported() {
122    Entry<K, V> nullValueEntry = entry(k3(), null);
123    assertNull(
124        "putIfAbsent(key, null) should return null",
125        getMap().putIfAbsent(nullValueEntry.getKey(), nullValueEntry.getValue()));
126    expectAdded(nullValueEntry);
127  }
128}