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