• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.annotations.GwtIncompatible;
27 import com.google.common.collect.testing.AbstractMapTester;
28 import com.google.common.collect.testing.Helpers;
29 import com.google.common.collect.testing.features.CollectionSize;
30 import com.google.common.collect.testing.features.MapFeature;
31 import java.lang.reflect.Method;
32 import java.util.Hashtable;
33 import java.util.Map;
34 import junit.framework.AssertionFailedError;
35 import org.junit.Ignore;
36 
37 /**
38  * A generic JUnit test which tests {@link Map#merge}. Can't be invoked directly; please see {@link
39  * com.google.common.collect.testing.MapTestSuiteBuilder}.
40  *
41  * @author Louis Wasserman
42  */
43 @GwtCompatible(emulated = true)
44 @Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
45 public class MapMergeTester<K, V> extends AbstractMapTester<K, V> {
46   @MapFeature.Require(SUPPORTS_PUT)
testAbsent()47   public void testAbsent() {
48     assertEquals(
49         "Map.merge(absent, value, function) should return value",
50         v3(),
51         getMap()
52             .merge(
53                 k3(),
54                 v3(),
55                 (oldV, newV) -> {
56                   throw new AssertionFailedError(
57                       "Should not call merge function if key was absent");
58                 }));
59     expectAdded(e3());
60   }
61 
62   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
63   @CollectionSize.Require(absent = ZERO)
testMappedToNull()64   public void testMappedToNull() {
65     initMapWithNullValue();
66     assertEquals(
67         "Map.merge(keyMappedToNull, value, function) should return value",
68         v3(),
69         getMap()
70             .merge(
71                 getKeyForNullValue(),
72                 v3(),
73                 (oldV, newV) -> {
74                   throw new AssertionFailedError(
75                       "Should not call merge function if key was mapped to null");
76                 }));
77     expectReplacement(entry(getKeyForNullValue(), v3()));
78   }
79 
80   @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
testMergeAbsentNullKey()81   public void testMergeAbsentNullKey() {
82     assertEquals(
83         "Map.merge(null, value, function) should return value",
84         v3(),
85         getMap()
86             .merge(
87                 null,
88                 v3(),
89                 (oldV, newV) -> {
90                   throw new AssertionFailedError(
91                       "Should not call merge function if key was absent");
92                 }));
93     expectAdded(entry(null, v3()));
94   }
95 
96   @MapFeature.Require(SUPPORTS_PUT)
97   @CollectionSize.Require(absent = ZERO)
testMergePresent()98   public void testMergePresent() {
99     assertEquals(
100         "Map.merge(present, value, function) should return function result",
101         v4(),
102         getMap()
103             .merge(
104                 k0(),
105                 v3(),
106                 (oldV, newV) -> {
107                   assertEquals(v0(), oldV);
108                   assertEquals(v3(), newV);
109                   return v4();
110                 }));
111     expectReplacement(entry(k0(), v4()));
112   }
113 
114   private static class ExpectedException extends RuntimeException {}
115 
116   @MapFeature.Require(SUPPORTS_PUT)
117   @CollectionSize.Require(absent = ZERO)
testMergeFunctionThrows()118   public void testMergeFunctionThrows() {
119     try {
120       getMap()
121           .merge(
122               k0(),
123               v3(),
124               (oldV, newV) -> {
125                 assertEquals(v0(), oldV);
126                 assertEquals(v3(), newV);
127                 throw new ExpectedException();
128               });
129       fail("Expected ExpectedException");
130     } catch (ExpectedException expected) {
131     }
132     expectUnchanged();
133   }
134 
135   @MapFeature.Require(SUPPORTS_REMOVE)
136   @CollectionSize.Require(absent = ZERO)
testMergePresentToNull()137   public void testMergePresentToNull() {
138     assertNull(
139         "Map.merge(present, value, functionReturningNull) should return null",
140         getMap()
141             .merge(
142                 k0(),
143                 v3(),
144                 (oldV, newV) -> {
145                   assertEquals(v0(), oldV);
146                   assertEquals(v3(), newV);
147                   return null;
148                 }));
149     expectMissing(e0());
150   }
151 
testMergeNullValue()152   public void testMergeNullValue() {
153     try {
154       getMap()
155           .merge(
156               k0(),
157               null,
158               (oldV, newV) -> {
159                 throw new AssertionFailedError("Should not call merge function if value was null");
160               });
161       fail("Expected NullPointerException or UnsupportedOperationException");
162     } catch (NullPointerException | UnsupportedOperationException expected) {
163     }
164   }
165 
testMergeNullFunction()166   public void testMergeNullFunction() {
167     try {
168       getMap().merge(k0(), v3(), null);
169       fail("Expected NullPointerException or UnsupportedOperationException");
170     } catch (NullPointerException | UnsupportedOperationException expected) {
171     }
172   }
173 
174   @MapFeature.Require(absent = SUPPORTS_PUT)
testMergeUnsupported()175   public void testMergeUnsupported() {
176     try {
177       getMap()
178           .merge(
179               k3(),
180               v3(),
181               (oldV, newV) -> {
182                 throw new AssertionFailedError();
183               });
184       fail("Expected UnsupportedOperationException");
185     } catch (UnsupportedOperationException expected) {
186     }
187   }
188 
189   /**
190    * Returns the {@link Method} instance for {@link #testMergeNullValue()} so that tests of {@link
191    * Hashtable} can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()}.
192    */
193   @GwtIncompatible // reflection
getMergeNullValueMethod()194   public static Method getMergeNullValueMethod() {
195     return Helpers.getMethod(MapMergeTester.class, "testMergeNullValue");
196   }
197 }
198