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