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