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