View Javadoc
1   /*
2    * Copyright (C) 2015 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect.testing.testers;
18  
19  import static com.google.common.collect.testing.features.CollectionSize.ZERO;
20  import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
21  import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
22  import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
23  
24  import com.google.common.annotations.GwtCompatible;
25  import com.google.common.collect.testing.AbstractMapTester;
26  import com.google.common.collect.testing.features.CollectionSize;
27  import com.google.common.collect.testing.features.MapFeature;
28  import java.util.Map;
29  import java.util.concurrent.ConcurrentMap;
30  
31  /**
32   * A generic JUnit test which tests {@code putIfAbsent} operations on a concurrent map. Can't be
33   * invoked directly; please see
34   * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
35   *
36   * @author Louis Wasserman
37   */
38  @GwtCompatible
39  public class ConcurrentMapPutIfAbsentTester<K, V> extends AbstractMapTester<K, V> {
40    @Override
41    protected ConcurrentMap<K, V> getMap() {
42      return (ConcurrentMap<K, V>) super.getMap();
43    }
44  
45    @MapFeature.Require(SUPPORTS_PUT)
46    public void testPutIfAbsent_supportedAbsent() {
47      assertNull("putIfAbsent(notPresent, value) should return null", putIfAbsent(e3()));
48      expectAdded(e3());
49    }
50  
51    @MapFeature.Require(SUPPORTS_PUT)
52    @CollectionSize.Require(absent = ZERO)
53    public void testPutIfAbsent_supportedPresent() {
54      assertEquals(
55          "putIfAbsent(present, value) should return existing value",
56          v0(),
57          getMap().putIfAbsent(k0(), v3()));
58      expectUnchanged();
59    }
60  
61    @MapFeature.Require(absent = SUPPORTS_PUT)
62    public void testPutIfAbsent_unsupportedAbsent() {
63      try {
64        putIfAbsent(e3());
65        fail("putIfAbsent(notPresent, value) should throw");
66      } catch (UnsupportedOperationException expected) {
67      }
68      expectUnchanged();
69      expectMissing(e3());
70    }
71  
72    @MapFeature.Require(absent = SUPPORTS_PUT)
73    @CollectionSize.Require(absent = ZERO)
74    public void testPutIfAbsent_unsupportedPresentExistingValue() {
75      try {
76        assertEquals(
77            "putIfAbsent(present, existingValue) should return present or throw",
78            v0(),
79            putIfAbsent(e0()));
80      } catch (UnsupportedOperationException tolerated) {
81      }
82      expectUnchanged();
83    }
84  
85    @MapFeature.Require(absent = SUPPORTS_PUT)
86    @CollectionSize.Require(absent = ZERO)
87    public void testPutIfAbsent_unsupportedPresentDifferentValue() {
88      try {
89        getMap().putIfAbsent(k0(), v3());
90      } catch (UnsupportedOperationException tolerated) {
91      }
92      expectUnchanged();
93    }
94  
95    @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
96    public void testPutIfAbsent_nullKeyUnsupported() {
97      try {
98        getMap().putIfAbsent(null, v3());
99        fail("putIfAbsent(null, value) should throw");
100     } catch (NullPointerException expected) {
101     }
102     expectUnchanged();
103     expectNullKeyMissingWhenNullKeysUnsupported(
104         "Should not contain null key after unsupported putIfAbsent(null, value)");
105   }
106 
107   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
108   public void testPutIfAbsent_nullValueUnsupported() {
109     try {
110       getMap().putIfAbsent(k3(), null);
111       fail("putIfAbsent(key, null) should throw");
112     } catch (NullPointerException expected) {
113     }
114     expectUnchanged();
115     expectNullValueMissingWhenNullValuesUnsupported(
116         "Should not contain null value after unsupported put(key, null)");
117   }
118 
119   @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
120   @CollectionSize.Require(absent = ZERO)
121   public void testPutIfAbsent_putWithNullValueUnsupported() {
122     try {
123       getMap().putIfAbsent(k0(), null);
124     } catch (NullPointerException tolerated) {
125     }
126     expectUnchanged();
127     expectNullValueMissingWhenNullValuesUnsupported(
128         "Should not contain null after unsupported putIfAbsent(present, null)");
129   }
130 
131   private V putIfAbsent(Map.Entry<K, V> entry) {
132     return getMap().putIfAbsent(entry.getKey(), entry.getValue());
133   }
134 }