/*
* Copyright (C) 2005 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
import java.io.Serializable;
import java.util.Map;
/**
* Tests for {@link Functions}.
*
* @author Mike Bostock
* @author Vlad Patryshev
*/
@GwtCompatible(emulated = true)
public class FunctionsTest extends TestCase {
public void testIdentity_same() {
Function<String, String> identity = Functions.identity();
assertNull(identity.apply(null));
assertSame("foo", identity.apply("foo"));
}
public void testIdentity_notSame() {
Function<Long, Long> identity = Functions.identity();
assertNotSame(new Long(135135L), identity.apply(new Long(135135L)));
}
@GwtIncompatible("SerializableTester")
public void testIdentitySerializable() {
checkCanReserializeSingleton(Functions.identity());
}
public void testToStringFunction_apply() {
assertEquals("3", Functions.toStringFunction().apply(3));
assertEquals("hiya", Functions.toStringFunction().apply("hiya"));
assertEquals("I'm a string",
Functions.toStringFunction().apply(
new Object() {
@Override public String toString() {
return "I'm a string";
}
}));
try {
Functions.toStringFunction().apply(null);
fail("expected NullPointerException");
} catch (NullPointerException e) {
// expected
}
}
@GwtIncompatible("SerializableTester")
public void testToStringFunctionSerializable() {
checkCanReserializeSingleton(Functions.toStringFunction());
}
@GwtIncompatible("NullPointerTester")
public void testNullPointerExceptions() throws Exception {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(Functions.class);
}
public void testForMapWithoutDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
map.put("Null", null);
Function<String, Integer> function = Functions.forMap(map);
assertEquals(1, function.apply("One").intValue());
assertEquals(3, function.apply("Three").intValue());
assertNull(function.apply("Null"));
try {
function.apply("Two");
fail();
} catch (IllegalArgumentException expected) {
}
new EqualsTester()
.addEqualityGroup(function, Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, 42))
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForMapWithoutDefaultSerializable() {
checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2)));
}
public void testForMapWithDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
map.put("Null", null);
Function<String, Integer> function = Functions.forMap(map, 42);
assertEquals(1, function.apply("One").intValue());
assertEquals(42, function.apply("Two").intValue());
assertEquals(3, function.apply("Three").intValue());
assertNull(function.apply("Null"));
new EqualsTester()
.addEqualityGroup(function, Functions.forMap(map, 42))
.addEqualityGroup(Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, null))
.addEqualityGroup(Functions.forMap(map, 43))
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForMapWithDefault_includeSerializable() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
Function<String, Integer> function = Functions.forMap(map, 42);
assertEquals(1, function.apply("One").intValue());
assertEquals(42, function.apply("Two").intValue());
assertEquals(3, function.apply("Three").intValue());
new EqualsTester()
.addEqualityGroup(
function,
Functions.forMap(map, 42),
SerializableTester.reserialize(function))
.addEqualityGroup(Functions.forMap(map))
.addEqualityGroup(Functions.forMap(map, null))
.addEqualityGroup(Functions.forMap(map, 43))
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForMapWithDefaultSerializable() {
checkCanReserialize(Functions.forMap(ImmutableMap.of(1, 2), 3));
}
public void testForMapWithDefault_null() {
ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
Function<String, Integer> function = Functions.forMap(map, null);
assertEquals((Integer) 1, function.apply("One"));
assertNull(function.apply("Two"));
// check basic sanity of equals and hashCode
new EqualsTester()
.addEqualityGroup(function)
.addEqualityGroup(Functions.forMap(map, 1))
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForMapWithDefault_null_compareWithSerializable() {
ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1);
Function<String, Integer> function = Functions.forMap(map, null);
assertEquals((Integer) 1, function.apply("One"));
assertNull(function.apply("Two"));
// check basic sanity of equals and hashCode
new EqualsTester()
.addEqualityGroup(function, SerializableTester.reserialize(function))
.addEqualityGroup(Functions.forMap(map, 1))
.testEquals();
}
public void testForMapWildCardWithDefault() {
Map<String, Integer> map = Maps.newHashMap();
map.put("One", 1);
map.put("Three", 3);
Number number = Double.valueOf(42);
Function<String, Number> function = Functions.forMap(map, number);
assertEquals(1, function.apply("One").intValue());
assertEquals(number, function.apply("Two"));
assertEquals(3L, function.apply("Three").longValue());
}
public void testComposition() {
Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
mJapaneseToInteger.put("Ichi", 1);
mJapaneseToInteger.put("Ni", 2);
mJapaneseToInteger.put("San", 3);
Function<String, Integer> japaneseToInteger =
Functions.forMap(mJapaneseToInteger);
Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
mIntegerToSpanish.put(1, "Uno");
mIntegerToSpanish.put(3, "Tres");
mIntegerToSpanish.put(4, "Cuatro");
Function<Integer, String> integerToSpanish =
Functions.forMap(mIntegerToSpanish);
Function<String, String> japaneseToSpanish =
Functions.compose(integerToSpanish, japaneseToInteger);
assertEquals("Uno", japaneseToSpanish.apply("Ichi"));
try {
japaneseToSpanish.apply("Ni");
fail();
} catch (IllegalArgumentException e) {
}
assertEquals("Tres", japaneseToSpanish.apply("San"));
try {
japaneseToSpanish.apply("Shi");
fail();
} catch (IllegalArgumentException e) {
}
new EqualsTester()
.addEqualityGroup(
japaneseToSpanish,
Functions.compose(integerToSpanish, japaneseToInteger))
.addEqualityGroup(japaneseToInteger)
.addEqualityGroup(integerToSpanish)
.addEqualityGroup(
Functions.compose(japaneseToInteger, integerToSpanish))
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testComposition_includeReserializabled() {
Map<String, Integer> mJapaneseToInteger = Maps.newHashMap();
mJapaneseToInteger.put("Ichi", 1);
mJapaneseToInteger.put("Ni", 2);
mJapaneseToInteger.put("San", 3);
Function<String, Integer> japaneseToInteger =
Functions.forMap(mJapaneseToInteger);
Map<Integer, String> mIntegerToSpanish = Maps.newHashMap();
mIntegerToSpanish.put(1, "Uno");
mIntegerToSpanish.put(3, "Tres");
mIntegerToSpanish.put(4, "Cuatro");
Function<Integer, String> integerToSpanish =
Functions.forMap(mIntegerToSpanish);
Function<String, String> japaneseToSpanish =
Functions.compose(integerToSpanish, japaneseToInteger);
new EqualsTester()
.addEqualityGroup(
japaneseToSpanish,
Functions.compose(integerToSpanish, japaneseToInteger),
SerializableTester.reserialize(japaneseToSpanish))
.addEqualityGroup(japaneseToInteger)
.addEqualityGroup(integerToSpanish)
.addEqualityGroup(
Functions.compose(japaneseToInteger, integerToSpanish))
.testEquals();
}
public void testCompositionWildcard() {
Map<String, Integer> mapJapaneseToInteger = Maps.newHashMap();
Function<String, Integer> japaneseToInteger =
Functions.forMap(mapJapaneseToInteger);
Function<Object, String> numberToSpanish = Functions.constant("Yo no se");
Function<String, String> japaneseToSpanish =
Functions.compose(numberToSpanish, japaneseToInteger);
}
private static class HashCodeFunction implements Function<Object, Integer> {
@Override
public Integer apply(Object o) {
return (o == null) ? 0 : o.hashCode();
}
}
public void testComposeOfFunctionsIsAssociative() {
Map<Float, String> m = ImmutableMap.of(
4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
Function<? super Integer, Boolean> h = Functions.constant(Boolean.TRUE);
Function<? super String, Integer> g = new HashCodeFunction();
Function<Float, String> f = Functions.forMap(m, "F");
Function<Float, Boolean> c1 = Functions.compose(Functions.compose(h, g), f);
Function<Float, Boolean> c2 = Functions.compose(h, Functions.compose(g, f));
// Might be nice (eventually) to have:
// assertEquals(c1, c2);
// But for now, settle for this:
assertEquals(c1.hashCode(), c2.hashCode());
assertEquals(c1.apply(1.0f), c2.apply(1.0f));
assertEquals(c1.apply(5.0f), c2.apply(5.0f));
}
public void testComposeOfPredicateAndFunctionIsAssociative() {
Map<Float, String> m = ImmutableMap.of(
4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D");
Predicate<? super Integer> h = Predicates.equalTo(42);
Function<? super String, Integer> g = new HashCodeFunction();
Function<Float, String> f = Functions.forMap(m, "F");
Predicate<Float> p1 = Predicates.compose(Predicates.compose(h, g), f);
Predicate<Float> p2 = Predicates.compose(h, Functions.compose(g, f));
// Might be nice (eventually) to have:
// assertEquals(p1, p2);
// But for now, settle for this:
assertEquals(p1.hashCode(), p2.hashCode());
assertEquals(p1.apply(1.0f), p2.apply(1.0f));
assertEquals(p1.apply(5.0f), p2.apply(5.0f));
}
public void testForPredicate() {
Function<Object, Boolean> alwaysTrue =
Functions.forPredicate(Predicates.alwaysTrue());
Function<Object, Boolean> alwaysFalse =
Functions.forPredicate(Predicates.alwaysFalse());
assertTrue(alwaysTrue.apply(0));
assertFalse(alwaysFalse.apply(0));
new EqualsTester()
.addEqualityGroup(
alwaysTrue, Functions.forPredicate(Predicates.alwaysTrue()))
.addEqualityGroup(alwaysFalse)
.addEqualityGroup(Functions.identity())
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForPredicateSerializable() {
checkCanReserialize(Functions.forPredicate(Predicates.equalTo(5)));
}
public void testConstant() {
Function<Object, Object> f = Functions.<Object>constant("correct");
assertEquals("correct", f.apply(new Object()));
assertEquals("correct", f.apply(null));
Function<Object, String> g = Functions.constant(null);
assertEquals(null, g.apply(2));
assertEquals(null, g.apply(null));
new EqualsTester()
.addEqualityGroup(f, Functions.constant("correct"))
.addEqualityGroup(Functions.constant("incorrect"))
.addEqualityGroup(Functions.toStringFunction())
.addEqualityGroup(g)
.testEquals();
new EqualsTester()
.addEqualityGroup(g, Functions.constant(null))
.addEqualityGroup(Functions.constant("incorrect"))
.addEqualityGroup(Functions.toStringFunction())
.addEqualityGroup(f)
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testConstantSerializable() {
checkCanReserialize(Functions.constant(5));
}
private static class CountingSupplier
implements Supplier<Integer>, Serializable {
private static final long serialVersionUID = 0;
private int value;
@Override
public Integer get() {
return ++value;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CountingSupplier) {
return this.value == ((CountingSupplier) obj).value;
}
return false;
}
@Override
public int hashCode() {
return value;
}
}
public void testForSupplier() {
Supplier<Integer> supplier = new CountingSupplier();
Function<Object, Integer> function = Functions.forSupplier(supplier);
assertEquals(1, (int) function.apply(null));
assertEquals(2, (int) function.apply("foo"));
new EqualsTester()
.addEqualityGroup(function, Functions.forSupplier(supplier))
.addEqualityGroup(Functions.forSupplier(new CountingSupplier()))
.addEqualityGroup(Functions.forSupplier(Suppliers.ofInstance(12)))
.addEqualityGroup(Functions.toStringFunction())
.testEquals();
}
@GwtIncompatible("SerializableTester")
public void testForSupplierSerializable() {
checkCanReserialize(Functions.forSupplier(new CountingSupplier()));
}
@GwtIncompatible("SerializableTester")
private <Y> void checkCanReserialize(Function<? super Integer, Y> f) {
Function<? super Integer, Y> g = SerializableTester.reserializeAndAssert(f);
for (int i = 1; i < 5; i++) {
// convoluted way to check that the same result happens from each
Y expected = null;
try {
expected = f.apply(i);
} catch (IllegalArgumentException e) {
try {
g.apply(i);
fail();
} catch (IllegalArgumentException ok) {
continue;
}
}
assertEquals(expected, g.apply(i));
}
}
@GwtIncompatible("SerializableTester")
private <Y> void checkCanReserializeSingleton(Function<? super String, Y> f) {
Function<? super String, Y> g = SerializableTester.reserializeAndAssert(f);
assertSame(f, g);
for (Integer i = 1; i < 5; i++) {
assertEquals(f.apply(i.toString()), g.apply(i.toString()));
}
}
}