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