• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 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.base;
18 
19 import static com.google.common.base.ReflectionFreeAssertThrows.assertThrows;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.annotations.J2ktIncompatible;
24 import com.google.common.collect.ImmutableMap;
25 import com.google.common.collect.Maps;
26 import com.google.common.testing.ClassSanityTester;
27 import com.google.common.testing.EqualsTester;
28 import com.google.common.testing.NullPointerTester;
29 import com.google.common.testing.SerializableTester;
30 import java.io.Serializable;
31 import java.util.Map;
32 import junit.framework.TestCase;
33 import org.checkerframework.checker.nullness.qual.Nullable;
34 
35 /**
36  * Tests for {@link Functions}.
37  *
38  * @author Mike Bostock
39  * @author Vlad Patryshev
40  */
41 @GwtCompatible(emulated = true)
42 @ElementTypesAreNonnullByDefault
43 public class FunctionsTest extends TestCase {
44 
testIdentity_same()45   public void testIdentity_same() {
46     Function<@Nullable String, @Nullable String> identity = Functions.identity();
47     assertNull(identity.apply(null));
48     assertSame("foo", identity.apply("foo"));
49   }
50 
testIdentity_notSame()51   public void testIdentity_notSame() {
52     Function<Long, Long> identity = Functions.identity();
53     assertNotSame(new Long(135135L), identity.apply(new Long(135135L)));
54   }
55 
56   @J2ktIncompatible
57   @GwtIncompatible // SerializableTester
testIdentitySerializable()58   public void testIdentitySerializable() {
59     checkCanReserializeSingleton(Functions.identity());
60   }
61 
testToStringFunction_apply()62   public void testToStringFunction_apply() {
63     assertEquals("3", Functions.toStringFunction().apply(3));
64     assertEquals("hiya", Functions.toStringFunction().apply("hiya"));
65     assertEquals(
66         "I'm a string",
67         Functions.toStringFunction()
68             .apply(
69                 new Object() {
70                   @Override
71                   public String toString() {
72                     return "I'm a string";
73                   }
74                 }));
75     assertThrows(NullPointerException.class, () -> Functions.toStringFunction().apply(null));
76   }
77 
78   @J2ktIncompatible
79   @GwtIncompatible // SerializableTester
testToStringFunctionSerializable()80   public void testToStringFunctionSerializable() {
81     checkCanReserializeSingleton(Functions.toStringFunction());
82   }
83 
84   @J2ktIncompatible
85   @GwtIncompatible // NullPointerTester
testNullPointerExceptions()86   public void testNullPointerExceptions() {
87     NullPointerTester tester = new NullPointerTester();
88     tester.testAllPublicStaticMethods(Functions.class);
89   }
90 
testForMapWithoutDefault()91   public void testForMapWithoutDefault() {
92     Map<String, @Nullable Integer> map = Maps.newHashMap();
93     map.put("One", 1);
94     map.put("Three", 3);
95     map.put("Null", null);
96     Function<String, @Nullable Integer> function = Functions.forMap(map);
97 
98     assertEquals(1, function.apply("One").intValue());
99     assertEquals(3, function.apply("Three").intValue());
100     assertNull(function.apply("Null"));
101 
102     assertThrows(IllegalArgumentException.class, () -> function.apply("Two"));
103 
104     new EqualsTester()
105         .addEqualityGroup(function, Functions.forMap(map))
106         .addEqualityGroup(Functions.forMap(map, 42))
107         .testEquals();
108   }
109 
110   @J2ktIncompatible
111   @GwtIncompatible // SerializableTester
testForMapWithoutDefaultSerializable()112   public void testForMapWithoutDefaultSerializable() {
113     checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2)));
114   }
115 
testForMapWithDefault()116   public void testForMapWithDefault() {
117     Map<String, @Nullable Integer> map = Maps.newHashMap();
118     map.put("One", 1);
119     map.put("Three", 3);
120     map.put("Null", null);
121     Function<String, @Nullable Integer> function = Functions.forMap(map, 42);
122 
123     assertEquals(1, function.apply("One").intValue());
124     assertEquals(42, function.apply("Two").intValue());
125     assertEquals(3, function.apply("Three").intValue());
126     assertNull(function.apply("Null"));
127 
128     new EqualsTester()
129         .addEqualityGroup(function, Functions.forMap(map, 42))
130         .addEqualityGroup(Functions.forMap(map))
131         .addEqualityGroup(Functions.forMap(map, null))
132         .addEqualityGroup(Functions.forMap(map, 43))
133         .testEquals();
134   }
135 
136   @J2ktIncompatible
137   @GwtIncompatible // SerializableTester
testForMapWithDefault_includeSerializable()138   public void testForMapWithDefault_includeSerializable() {
139     Map<String, Integer> map = Maps.newHashMap();
140     map.put("One", 1);
141     map.put("Three", 3);
142     Function<String, Integer> function = Functions.forMap(map, 42);
143 
144     assertEquals(1, function.apply("One").intValue());
145     assertEquals(42, function.apply("Two").intValue());
146     assertEquals(3, function.apply("Three").intValue());
147 
148     new EqualsTester()
149         .addEqualityGroup(
150             function, Functions.forMap(map, 42), SerializableTester.reserialize(function))
151         .addEqualityGroup(Functions.forMap(map))
152         .addEqualityGroup(Functions.forMap(map, null))
153         .addEqualityGroup(Functions.forMap(map, 43))
154         .testEquals();
155   }
156 
157   @J2ktIncompatible
158   @GwtIncompatible // SerializableTester
testForMapWithDefaultSerializable()159   public void testForMapWithDefaultSerializable() {
160     checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2), 3));
161   }
162 
testForMapWithDefault_null()163   public void testForMapWithDefault_null() {
164     ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
165     Function<String, @Nullable Integer> function = Functions.forMap(map, null);
166 
167     assertEquals((Integer) 1, function.apply("One"));
168     assertNull(function.apply("Two"));
169 
170     // check basic sanity of equals and hashCode
171     new EqualsTester()
172         .addEqualityGroup(function)
173         .addEqualityGroup(Functions.forMap(map, 1))
174         .testEquals();
175   }
176 
177   @J2ktIncompatible
178   @GwtIncompatible // SerializableTester
testForMapWithDefault_null_compareWithSerializable()179   public void testForMapWithDefault_null_compareWithSerializable() {
180     ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
181     Function<String, Integer> function = Functions.forMap(map, null);
182 
183     assertEquals((Integer) 1, function.apply("One"));
184     assertNull(function.apply("Two"));
185 
186     // check basic sanity of equals and hashCode
187     new EqualsTester()
188         .addEqualityGroup(function, SerializableTester.reserialize(function))
189         .addEqualityGroup(Functions.forMap(map, 1))
190         .testEquals();
191   }
192 
testForMapWildCardWithDefault()193   public void testForMapWildCardWithDefault() {
194     Map<String, Integer> map = Maps.newHashMap();
195     map.put("One", 1);
196     map.put("Three", 3);
197     Number number = Double.valueOf(42);
198     Function<String, Number> function = Functions.forMap(map, number);
199 
200     assertEquals(1, function.apply("One").intValue());
201     assertEquals(number, function.apply("Two"));
202     assertEquals(3L, function.apply("Three").longValue());
203   }
204 
testComposition()205   public void testComposition() {
206     Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
207     mJapaneseToInteger.put("Ichi", 1);
208     mJapaneseToInteger.put("Ni", 2);
209     mJapaneseToInteger.put("San", 3);
210     Function<String, Integer> japaneseToInteger = Functions.forMap(mJapaneseToInteger);
211 
212     Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
213     mIntegerToSpanish.put(1, "Uno");
214     mIntegerToSpanish.put(3, "Tres");
215     mIntegerToSpanish.put(4, "Cuatro");
216     Function<Integer, String> integerToSpanish = Functions.forMap(mIntegerToSpanish);
217 
218     Function<String, String> japaneseToSpanish =
219         Functions.compose(integerToSpanish, japaneseToInteger);
220 
221     assertEquals("Uno", japaneseToSpanish.apply("Ichi"));
222     assertThrows(IllegalArgumentException.class, () -> japaneseToSpanish.apply("Ni"));
223     assertEquals("Tres", japaneseToSpanish.apply("San"));
224     assertThrows(IllegalArgumentException.class, () -> japaneseToSpanish.apply("Shi"));
225 
226     new EqualsTester()
227         .addEqualityGroup(japaneseToSpanish, Functions.compose(integerToSpanish, japaneseToInteger))
228         .addEqualityGroup(japaneseToInteger)
229         .addEqualityGroup(integerToSpanish)
230         .addEqualityGroup(Functions.compose(japaneseToInteger, integerToSpanish))
231         .testEquals();
232   }
233 
234   @J2ktIncompatible
235   @GwtIncompatible // SerializableTester
testComposition_includeReserializabled()236   public void testComposition_includeReserializabled() {
237     Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
238     mJapaneseToInteger.put("Ichi", 1);
239     mJapaneseToInteger.put("Ni", 2);
240     mJapaneseToInteger.put("San", 3);
241     Function<String, Integer> japaneseToInteger = Functions.forMap(mJapaneseToInteger);
242 
243     Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
244     mIntegerToSpanish.put(1, "Uno");
245     mIntegerToSpanish.put(3, "Tres");
246     mIntegerToSpanish.put(4, "Cuatro");
247     Function<Integer, String> integerToSpanish = Functions.forMap(mIntegerToSpanish);
248 
249     Function<String, String> japaneseToSpanish =
250         Functions.compose(integerToSpanish, japaneseToInteger);
251 
252     new EqualsTester()
253         .addEqualityGroup(
254             japaneseToSpanish,
255             Functions.compose(integerToSpanish, japaneseToInteger),
256             SerializableTester.reserialize(japaneseToSpanish))
257         .addEqualityGroup(japaneseToInteger)
258         .addEqualityGroup(integerToSpanish)
259         .addEqualityGroup(Functions.compose(japaneseToInteger, integerToSpanish))
260         .testEquals();
261   }
262 
testCompositionWildcard()263   public void testCompositionWildcard() {
264     Map<String, Integer> mapJapaneseToInteger = Maps.newHashMap();
265     Function<String, Integer> japaneseToInteger = Functions.forMap(mapJapaneseToInteger);
266 
267     Function<Object, String> numberToSpanish = Functions.constant("Yo no se");
268 
269     Function<String, String> unusedJapaneseToSpanish =
270         Functions.compose(numberToSpanish, japaneseToInteger);
271   }
272 
273   private static class HashCodeFunction implements Function<@Nullable Object, Integer> {
274     @Override
apply(@ullable Object o)275     public Integer apply(@Nullable Object o) {
276       return (o == null) ? 0 : o.hashCode();
277     }
278   }
279 
testComposeOfFunctionsIsAssociative()280   public void testComposeOfFunctionsIsAssociative() {
281     Map<Float, String> m = ImmutableMap.of(4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
282     Function<? super Integer, Boolean> h = Functions.constant(Boolean.TRUE);
283     Function<? super String, Integer> g = new HashCodeFunction();
284     Function<Float, String> f = Functions.forMap(m, "F");
285 
286     Function<Float, Boolean> c1 = Functions.compose(Functions.compose(h, g), f);
287     Function<Float, Boolean> c2 = Functions.compose(h, Functions.compose(g, f));
288 
289     // Might be nice (eventually) to have:
290     //     assertEquals(c1, c2);
291 
292     // But for now, settle for this:
293     assertEquals(c1.hashCode(), c2.hashCode());
294 
295     assertEquals(c1.apply(1.0f), c2.apply(1.0f));
296     assertEquals(c1.apply(5.0f), c2.apply(5.0f));
297   }
298 
testComposeOfPredicateAndFunctionIsAssociative()299   public void testComposeOfPredicateAndFunctionIsAssociative() {
300     Map<Float, String> m = ImmutableMap.of(4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
301     Predicate<? super Integer> h = Predicates.equalTo(42);
302     Function<? super String, Integer> g = new HashCodeFunction();
303     Function<Float, String> f = Functions.forMap(m, "F");
304 
305     Predicate<Float> p1 = Predicates.compose(Predicates.compose(h, g), f);
306     Predicate<Float> p2 = Predicates.compose(h, Functions.compose(g, f));
307 
308     // Might be nice (eventually) to have:
309     //     assertEquals(p1, p2);
310 
311     // But for now, settle for this:
312     assertEquals(p1.hashCode(), p2.hashCode());
313 
314     assertEquals(p1.apply(1.0f), p2.apply(1.0f));
315     assertEquals(p1.apply(5.0f), p2.apply(5.0f));
316   }
317 
testForPredicate()318   public void testForPredicate() {
319     Function<Object, Boolean> alwaysTrue = Functions.forPredicate(Predicates.alwaysTrue());
320     Function<Object, Boolean> alwaysFalse = Functions.forPredicate(Predicates.alwaysFalse());
321 
322     assertTrue(alwaysTrue.apply(0));
323     assertFalse(alwaysFalse.apply(0));
324 
325     new EqualsTester()
326         .addEqualityGroup(alwaysTrue, Functions.forPredicate(Predicates.alwaysTrue()))
327         .addEqualityGroup(alwaysFalse)
328         .addEqualityGroup(Functions.identity())
329         .testEquals();
330   }
331 
332   @J2ktIncompatible
333   @GwtIncompatible // SerializableTester
testForPredicateSerializable()334   public void testForPredicateSerializable() {
335     checkCanReserialize(Functions.forPredicate(Predicates.equalTo(5)));
336   }
337 
testConstant()338   public void testConstant() {
339     Function<@Nullable Object, Object> f = Functions.<Object>constant("correct");
340     assertEquals("correct", f.apply(new Object()));
341     assertEquals("correct", f.apply(null));
342 
343     Function<@Nullable Object, @Nullable String> g = Functions.constant(null);
344     assertEquals(null, g.apply(2));
345     assertEquals(null, g.apply(null));
346 
347     new EqualsTester()
348         .addEqualityGroup(f, Functions.constant("correct"))
349         .addEqualityGroup(Functions.constant("incorrect"))
350         .addEqualityGroup(Functions.toStringFunction())
351         .addEqualityGroup(g)
352         .testEquals();
353 
354     new EqualsTester()
355         .addEqualityGroup(g, Functions.<@Nullable Object>constant(null))
356         .addEqualityGroup(Functions.constant("incorrect"))
357         .addEqualityGroup(Functions.toStringFunction())
358         .addEqualityGroup(f)
359         .testEquals();
360   }
361 
362   @J2ktIncompatible
363   @GwtIncompatible // SerializableTester
testConstantSerializable()364   public void testConstantSerializable() {
365     checkCanReserialize(Functions.constant(5));
366   }
367 
368   private static class CountingSupplier implements Supplier<Integer>, Serializable {
369 
370     private static final long serialVersionUID = 0;
371 
372     private int value;
373 
374     @Override
get()375     public Integer get() {
376       return ++value;
377     }
378 
379     @Override
equals(@ullable Object obj)380     public boolean equals(@Nullable Object obj) {
381       if (obj instanceof CountingSupplier) {
382         return this.value == ((CountingSupplier) obj).value;
383       }
384       return false;
385     }
386 
387     @Override
hashCode()388     public int hashCode() {
389       return value;
390     }
391   }
392 
testForSupplier()393   public void testForSupplier() {
394     Supplier<Integer> supplier = new CountingSupplier();
395     Function<@Nullable Object, Integer> function = Functions.forSupplier(supplier);
396 
397     assertEquals(1, (int) function.apply(null));
398     assertEquals(2, (int) function.apply("foo"));
399 
400     new EqualsTester()
401         .addEqualityGroup(function, Functions.forSupplier(supplier))
402         .addEqualityGroup(Functions.forSupplier(new CountingSupplier()))
403         .addEqualityGroup(Functions.forSupplier(Suppliers.ofInstance(12)))
404         .addEqualityGroup(Functions.toStringFunction())
405         .testEquals();
406   }
407 
408   @J2ktIncompatible
409   @GwtIncompatible // SerializableTester
testForSupplierSerializable()410   public void testForSupplierSerializable() {
411     checkCanReserialize(Functions.forSupplier(new CountingSupplier()));
412   }
413 
414   @J2ktIncompatible
415   @GwtIncompatible // reflection
testNulls()416   public void testNulls() throws Exception {
417     new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testNulls();
418   }
419 
420   @J2ktIncompatible
421   @GwtIncompatible // reflection
422   @AndroidIncompatible // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
423   // (I suspect that this and the other similar failures happen with ArbitraryInstances proxies.)
testEqualsAndSerializable()424   public void testEqualsAndSerializable() throws Exception {
425     new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testEqualsAndSerializable();
426   }
427 
428   @J2ktIncompatible
429   @GwtIncompatible // SerializableTester
checkCanReserialize(Function<? super Integer, Y> f)430   private static <Y> void checkCanReserialize(Function<? super Integer, Y> f) {
431     Function<? super Integer, Y> g = SerializableTester.reserializeAndAssert(f);
432     for (int i = 1; i < 5; i++) {
433       // convoluted way to check that the same result happens from each
434       Y expected = null;
435       try {
436         expected = f.apply(i);
437       } catch (IllegalArgumentException e) {
438         try {
439           g.apply(i);
440           fail();
441         } catch (IllegalArgumentException ok) {
442           continue;
443         }
444       }
445       assertEquals(expected, g.apply(i));
446     }
447   }
448 
449   @J2ktIncompatible
450   @GwtIncompatible // SerializableTester
checkCanReserializeSingleton(Function<? super String, Y> f)451   private static <Y> void checkCanReserializeSingleton(Function<? super String, Y> f) {
452     Function<? super String, Y> g = SerializableTester.reserializeAndAssert(f);
453     assertSame(f, g);
454     for (Integer i = 1; i < 5; i++) {
455       assertEquals(f.apply(i.toString()), g.apply(i.toString()));
456     }
457   }
458 }
459