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