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