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 17package com.google.common.base; 18 19import com.google.common.annotations.GwtCompatible; 20import com.google.common.collect.ImmutableMap; 21import com.google.common.collect.Maps; 22import com.google.common.testing.EqualsTester; 23 24import junit.framework.TestCase; 25 26import java.io.Serializable; 27import java.util.Map; 28 29/** 30 * Tests for {@link Functions}. 31 * 32 * @author Mike Bostock 33 * @author Vlad Patryshev 34 */ 35@GwtCompatible(emulated = true) 36public class FunctionsTest extends TestCase { 37 38 public void testIdentity_same() { 39 Function<String, String> identity = Functions.identity(); 40 assertNull(identity.apply(null)); 41 assertSame("foo", identity.apply("foo")); 42 } 43 44 public void testIdentity_notSame() { 45 Function<Long, Long> identity = Functions.identity(); 46 assertNotSame(new Long(135135L), identity.apply(new Long(135135L))); 47 } 48 49 public void testToStringFunction_apply() { 50 assertEquals("3", Functions.toStringFunction().apply(3)); 51 assertEquals("hiya", Functions.toStringFunction().apply("hiya")); 52 assertEquals("I'm a string", 53 Functions.toStringFunction().apply( 54 new Object() { 55 @Override public String toString() { 56 return "I'm a string"; 57 } 58 })); 59 try { 60 Functions.toStringFunction().apply(null); 61 fail("expected NullPointerException"); 62 } catch (NullPointerException e) { 63 // expected 64 } 65 } 66 67 public void testForMapWithoutDefault() { 68 Map<String, Integer> map = Maps.newHashMap(); 69 map.put("One", 1); 70 map.put("Three", 3); 71 map.put("Null", null); 72 Function<String, Integer> function = Functions.forMap(map); 73 74 assertEquals(1, function.apply("One").intValue()); 75 assertEquals(3, function.apply("Three").intValue()); 76 assertNull(function.apply("Null")); 77 78 try { 79 function.apply("Two"); 80 fail(); 81 } catch (IllegalArgumentException expected) { 82 } 83 84 new EqualsTester() 85 .addEqualityGroup(function, Functions.forMap(map)) 86 .addEqualityGroup(Functions.forMap(map, 42)) 87 .testEquals(); 88 } 89 90 public void testForMapWithDefault() { 91 Map<String, Integer> map = Maps.newHashMap(); 92 map.put("One", 1); 93 map.put("Three", 3); 94 map.put("Null", null); 95 Function<String, Integer> function = Functions.forMap(map, 42); 96 97 assertEquals(1, function.apply("One").intValue()); 98 assertEquals(42, function.apply("Two").intValue()); 99 assertEquals(3, function.apply("Three").intValue()); 100 assertNull(function.apply("Null")); 101 102 new EqualsTester() 103 .addEqualityGroup(function, Functions.forMap(map, 42)) 104 .addEqualityGroup(Functions.forMap(map)) 105 .addEqualityGroup(Functions.forMap(map, null)) 106 .addEqualityGroup(Functions.forMap(map, 43)) 107 .testEquals(); 108 } 109 110 public void testForMapWithDefault_null() { 111 ImmutableMap<String, Integer> map = ImmutableMap.of("One", 1); 112 Function<String, Integer> function = Functions.forMap(map, null); 113 114 assertEquals((Integer) 1, function.apply("One")); 115 assertNull(function.apply("Two")); 116 117 // check basic sanity of equals and hashCode 118 new EqualsTester() 119 .addEqualityGroup(function) 120 .addEqualityGroup(Functions.forMap(map, 1)) 121 .testEquals(); 122 } 123 124 public void testForMapWildCardWithDefault() { 125 Map<String, Integer> map = Maps.newHashMap(); 126 map.put("One", 1); 127 map.put("Three", 3); 128 Number number = Double.valueOf(42); 129 Function<String, Number> function = Functions.forMap(map, number); 130 131 assertEquals(1, function.apply("One").intValue()); 132 assertEquals(number, function.apply("Two")); 133 assertEquals(3L, function.apply("Three").longValue()); 134 } 135 136 public void testComposition() { 137 Map<String, Integer> mJapaneseToInteger = Maps.newHashMap(); 138 mJapaneseToInteger.put("Ichi", 1); 139 mJapaneseToInteger.put("Ni", 2); 140 mJapaneseToInteger.put("San", 3); 141 Function<String, Integer> japaneseToInteger = 142 Functions.forMap(mJapaneseToInteger); 143 144 Map<Integer, String> mIntegerToSpanish = Maps.newHashMap(); 145 mIntegerToSpanish.put(1, "Uno"); 146 mIntegerToSpanish.put(3, "Tres"); 147 mIntegerToSpanish.put(4, "Cuatro"); 148 Function<Integer, String> integerToSpanish = 149 Functions.forMap(mIntegerToSpanish); 150 151 Function<String, String> japaneseToSpanish = 152 Functions.compose(integerToSpanish, japaneseToInteger); 153 154 assertEquals("Uno", japaneseToSpanish.apply("Ichi")); 155 try { 156 japaneseToSpanish.apply("Ni"); 157 fail(); 158 } catch (IllegalArgumentException e) { 159 } 160 assertEquals("Tres", japaneseToSpanish.apply("San")); 161 try { 162 japaneseToSpanish.apply("Shi"); 163 fail(); 164 } catch (IllegalArgumentException e) { 165 } 166 167 new EqualsTester() 168 .addEqualityGroup( 169 japaneseToSpanish, 170 Functions.compose(integerToSpanish, japaneseToInteger)) 171 .addEqualityGroup(japaneseToInteger) 172 .addEqualityGroup(integerToSpanish) 173 .addEqualityGroup( 174 Functions.compose(japaneseToInteger, integerToSpanish)) 175 .testEquals(); 176 } 177 178 public void testCompositionWildcard() { 179 Map<String, Integer> mapJapaneseToInteger = Maps.newHashMap(); 180 Function<String, Integer> japaneseToInteger = 181 Functions.forMap(mapJapaneseToInteger); 182 183 Function<Object, String> numberToSpanish = Functions.constant("Yo no se"); 184 185 Function<String, String> japaneseToSpanish = 186 Functions.compose(numberToSpanish, japaneseToInteger); 187 } 188 189 private static class HashCodeFunction implements Function<Object, Integer> { 190 @Override 191 public Integer apply(Object o) { 192 return (o == null) ? 0 : o.hashCode(); 193 } 194 } 195 196 public void testComposeOfFunctionsIsAssociative() { 197 Map<Float, String> m = ImmutableMap.of( 198 4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D"); 199 Function<? super Integer, Boolean> h = Functions.constant(Boolean.TRUE); 200 Function<? super String, Integer> g = new HashCodeFunction(); 201 Function<Float, String> f = Functions.forMap(m, "F"); 202 203 Function<Float, Boolean> c1 = Functions.compose(Functions.compose(h, g), f); 204 Function<Float, Boolean> c2 = Functions.compose(h, Functions.compose(g, f)); 205 206 // Might be nice (eventually) to have: 207 // assertEquals(c1, c2); 208 209 // But for now, settle for this: 210 assertEquals(c1.hashCode(), c2.hashCode()); 211 212 assertEquals(c1.apply(1.0f), c2.apply(1.0f)); 213 assertEquals(c1.apply(5.0f), c2.apply(5.0f)); 214 } 215 216 public void testComposeOfPredicateAndFunctionIsAssociative() { 217 Map<Float, String> m = ImmutableMap.of( 218 4.0f, "A", 3.0f, "B", 2.0f, "C", 1.0f, "D"); 219 Predicate<? super Integer> h = Predicates.equalTo(42); 220 Function<? super String, Integer> g = new HashCodeFunction(); 221 Function<Float, String> f = Functions.forMap(m, "F"); 222 223 Predicate<Float> p1 = Predicates.compose(Predicates.compose(h, g), f); 224 Predicate<Float> p2 = Predicates.compose(h, Functions.compose(g, f)); 225 226 // Might be nice (eventually) to have: 227 // assertEquals(p1, p2); 228 229 // But for now, settle for this: 230 assertEquals(p1.hashCode(), p2.hashCode()); 231 232 assertEquals(p1.apply(1.0f), p2.apply(1.0f)); 233 assertEquals(p1.apply(5.0f), p2.apply(5.0f)); 234 } 235 236 public void testForPredicate() { 237 Function<Object, Boolean> alwaysTrue = 238 Functions.forPredicate(Predicates.alwaysTrue()); 239 Function<Object, Boolean> alwaysFalse = 240 Functions.forPredicate(Predicates.alwaysFalse()); 241 242 assertTrue(alwaysTrue.apply(0)); 243 assertFalse(alwaysFalse.apply(0)); 244 245 new EqualsTester() 246 .addEqualityGroup( 247 alwaysTrue, Functions.forPredicate(Predicates.alwaysTrue())) 248 .addEqualityGroup(alwaysFalse) 249 .addEqualityGroup(Functions.identity()) 250 .testEquals(); 251 } 252 253 public void testConstant() { 254 Function<Object, Object> f = Functions.<Object>constant("correct"); 255 assertEquals("correct", f.apply(new Object())); 256 assertEquals("correct", f.apply(null)); 257 258 Function<Object, String> g = Functions.constant(null); 259 assertEquals(null, g.apply(2)); 260 assertEquals(null, g.apply(null)); 261 262 new EqualsTester() 263 .addEqualityGroup(f, Functions.constant("correct")) 264 .addEqualityGroup(Functions.constant("incorrect")) 265 .addEqualityGroup(Functions.toStringFunction()) 266 .addEqualityGroup(g) 267 .testEquals(); 268 269 new EqualsTester() 270 .addEqualityGroup(g, Functions.constant(null)) 271 .addEqualityGroup(Functions.constant("incorrect")) 272 .addEqualityGroup(Functions.toStringFunction()) 273 .addEqualityGroup(f) 274 .testEquals(); 275 } 276 277 private static class CountingSupplier 278 implements Supplier<Integer>, Serializable { 279 280 private static final long serialVersionUID = 0; 281 282 private int value; 283 284 @Override 285 public Integer get() { 286 return ++value; 287 } 288 289 @Override 290 public boolean equals(Object obj) { 291 if (obj instanceof CountingSupplier) { 292 return this.value == ((CountingSupplier) obj).value; 293 } 294 return false; 295 } 296 297 @Override 298 public int hashCode() { 299 return value; 300 } 301 } 302 303 public void testForSupplier() { 304 Supplier<Integer> supplier = new CountingSupplier(); 305 Function<Object, Integer> function = Functions.forSupplier(supplier); 306 307 assertEquals(1, (int) function.apply(null)); 308 assertEquals(2, (int) function.apply("foo")); 309 310 new EqualsTester() 311 .addEqualityGroup(function, Functions.forSupplier(supplier)) 312 .addEqualityGroup(Functions.forSupplier(new CountingSupplier())) 313 .addEqualityGroup(Functions.forSupplier(Suppliers.ofInstance(12))) 314 .addEqualityGroup(Functions.toStringFunction()) 315 .testEquals(); 316 } 317 318} 319 320