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