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  import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
24  
25  import com.google.common.annotations.GwtCompatible;
26  import com.google.common.collect.testing.AbstractMapTester;
27  import com.google.common.collect.testing.features.CollectionSize;
28  import com.google.common.collect.testing.features.MapFeature;
29  import java.util.Map;
30  
31  /**
32   * A generic JUnit test which tests {@link Map#compute}. Can't be
33   * invoked directly; please see
34   * {@link com.google.common.collect.testing.MapTestSuiteBuilder}.
35   *
36   * @author Louis Wasserman
37   */
38  @GwtCompatible
39  public class MapComputeTester<K, V> extends AbstractMapTester<K, V> {
40    @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
41    public void testCompute_absentToPresent() {
42      assertEquals(
43          "Map.compute(absent, functionReturningValue) should return value",
44          v3(),
45          getMap()
46              .compute(
47                  k3(),
48                  (k, v)
49                      -> {
50                        assertEquals(k3(), k);
51                        assertNull(v);
52                        return v3();
53                      }));
54      expectAdded(e3());
55      assertEquals(getNumElements() + 1, getMap().size());
56    }
57  
58    @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
59    public void testCompute_absentToAbsent() {
60      assertNull(
61          "Map.compute(absent, functionReturningNull) should return null",
62          getMap()
63              .compute(
64                  k3(),
65                  (k, v)
66                      -> {
67                        assertEquals(k3(), k);
68                        assertNull(v);
69                        return null;
70                      }));
71      expectUnchanged();
72      assertEquals(getNumElements(), getMap().size());
73    }
74  
75    @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
76    @CollectionSize.Require(absent = ZERO)
77    public void testCompute_presentToPresent() {
78      assertEquals(
79          "Map.compute(present, functionReturningValue) should return new value",
80          v3(),
81          getMap()
82              .compute(
83                  k0(),
84                  (k, v)
85                      -> {
86                        assertEquals(k0(), k);
87                        assertEquals(v0(), v);
88                        return v3();
89                      }));
90      expectReplacement(entry(k0(), v3()));
91      assertEquals(getNumElements(), getMap().size());
92    }
93  
94    @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
95    @CollectionSize.Require(absent = ZERO)
96    public void testCompute_presentToAbsent() {
97      assertNull(
98          "Map.compute(present, functionReturningNull) should return null",
99          getMap()
100             .compute(
101                 k0(),
102                 (k, v)
103                     -> {
104                       assertEquals(k0(), k);
105                       assertEquals(v0(), v);
106                       return null;
107                     }));
108     expectMissing(e0());
109     expectMissingKeys(k0());
110     assertEquals(getNumElements() - 1, getMap().size());
111   }
112 
113   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
114   @CollectionSize.Require(absent = ZERO)
115   public void testCompute_presentNullToPresentNonnull() {
116     initMapWithNullValue();
117     V value = getValueForNullKey();
118     assertEquals(
119         "Map.compute(presentMappedToNull, functionReturningValue) should return new value",
120         value,
121         getMap()
122             .compute(
123                 getKeyForNullValue(),
124                 (k, v)
125                     -> {
126                       assertEquals(getKeyForNullValue(), k);
127                       assertNull(v);
128                       return value;
129                     }));
130     expectReplacement(entry(getKeyForNullValue(), value));
131     assertEquals(getNumElements(), getMap().size());
132   }
133 
134   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
135   @CollectionSize.Require(absent = ZERO)
136   public void testCompute_presentNullToNull() {
137     // The spec is somewhat ambiguous about this case, but the actual default implementation
138     // in Map will remove a present null.
139     initMapWithNullValue();
140     assertNull(
141         "Map.compute(presentMappedToNull, functionReturningNull) should return null",
142         getMap()
143             .compute(
144                 getKeyForNullValue(),
145                 (k, v)
146                     -> {
147                       assertEquals(getKeyForNullValue(), k);
148                       assertNull(v);
149                       return null;
150                     }));
151     expectMissingKeys(getKeyForNullValue());
152     assertEquals(getNumElements() - 1, getMap().size());
153   }
154 
155   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_KEYS})
156   @CollectionSize.Require(absent = ZERO)
157   public void testCompute_nullKeyPresentToPresent() {
158     initMapWithNullKey();
159     assertEquals(
160         "Map.compute(present, functionReturningValue) should return new value",
161         v3(),
162         getMap()
163             .compute(
164                 null,
165                 (k, v)
166                     -> {
167                       assertNull(k);
168                       assertEquals(getValueForNullKey(), v);
169                       return v3();
170                     }));
171     assertEquals(getNumElements(), getMap().size());
172   }
173 
174   static class ExpectedException extends RuntimeException {}
175 
176   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
177   @CollectionSize.Require(absent = ZERO)
178   public void testCompute_presentFunctionThrows() {
179     try {
180       getMap()
181           .compute(
182               k0(),
183               (k, v) -> {
184                 assertEquals(k0(), k);
185                 assertEquals(v0(), v);
186                 throw new ExpectedException();
187               });
188       fail("Expected ExpectedException");
189     } catch (ExpectedException expected) {
190     }
191     expectUnchanged();
192   }
193 
194   @MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
195   public void testCompute_absentFunctionThrows() {
196     try {
197       getMap()
198           .compute(
199               k3(),
200               (k, v) -> {
201                 assertEquals(k3(), k);
202                 assertNull(v);
203                 throw new ExpectedException();
204               });
205       fail("Expected ExpectedException");
206     } catch (ExpectedException expected) {
207     }
208     expectUnchanged();
209   }
210 }