1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.testing.anotherpackage;
18
19 import static com.google.common.truth.Truth.assertThat;
20
21 import com.google.common.base.Equivalence;
22 import com.google.common.base.Function;
23 import com.google.common.base.Functions;
24 import com.google.common.base.Joiner;
25 import com.google.common.base.Predicate;
26 import com.google.common.collect.Ordering;
27 import com.google.common.primitives.UnsignedInteger;
28 import com.google.common.primitives.UnsignedLong;
29 import com.google.common.testing.ForwardingWrapperTester;
30 import com.google.common.testing.NullPointerTester;
31
32 import junit.framework.TestCase;
33
34 import java.io.InputStream;
35 import java.nio.charset.Charset;
36 import java.util.concurrent.TimeUnit;
37 import java.util.regex.Pattern;
38
39
40
41
42
43
44
45 public class ForwardingWrapperTesterTest extends TestCase {
46
47 private final ForwardingWrapperTester tester = new ForwardingWrapperTester();
48
49 public void testGoodForwarder() {
50 tester.testForwarding(Arithmetic.class,
51 new Function<Arithmetic, Arithmetic>() {
52 @Override public Arithmetic apply(Arithmetic arithmetic) {
53 return new ForwardingArithmetic(arithmetic);
54 }
55 });
56 tester.testForwarding(ParameterTypesDifferent.class,
57 new Function<ParameterTypesDifferent, ParameterTypesDifferent>() {
58 @Override public ParameterTypesDifferent apply(ParameterTypesDifferent delegate) {
59 return new ParameterTypesDifferentForwarder(delegate);
60 }
61 });
62 }
63
64 public void testVoidMethodForwarding() {
65 tester.testForwarding(Runnable.class,
66 new Function<Runnable, Runnable>() {
67 @Override public Runnable apply(final Runnable runnable) {
68 return new ForwardingRunnable(runnable);
69 }
70 });
71 }
72
73 public void testToStringForwarding() {
74 tester.testForwarding(Runnable.class,
75 new Function<Runnable, Runnable>() {
76 @Override public Runnable apply(final Runnable runnable) {
77 return new ForwardingRunnable(runnable) {
78 @Override public String toString() {
79 return runnable.toString();
80 }
81 };
82 }
83 });
84 }
85
86 public void testFailsToForwardToString() {
87 assertFailure(Runnable.class, new Function<Runnable, Runnable>() {
88 @Override public Runnable apply(final Runnable runnable) {
89 return new ForwardingRunnable(runnable) {
90 @Override public String toString() {
91 return "";
92 }
93 };
94 }
95 }, "toString()");
96 }
97
98 public void testFailsToForwardHashCode() {
99 tester.includingEquals();
100 assertFailure(Runnable.class, new Function<Runnable, Runnable>() {
101 @Override public Runnable apply(final Runnable runnable) {
102 return new ForwardingRunnable(runnable) {
103 @Override public boolean equals(Object o) {
104 if (o instanceof ForwardingRunnable) {
105 ForwardingRunnable that = (ForwardingRunnable) o;
106 return runnable.equals(that.runnable);
107 }
108 return false;
109 }
110 };
111 }
112 }, "Runnable");
113 }
114
115 public void testEqualsAndHashCodeForwarded() {
116 tester.includingEquals();
117 tester.testForwarding(Runnable.class, new Function<Runnable, Runnable>() {
118 @Override public Runnable apply(final Runnable runnable) {
119 return new ForwardingRunnable(runnable) {
120 @Override public boolean equals(Object o) {
121 if (o instanceof ForwardingRunnable) {
122 ForwardingRunnable that = (ForwardingRunnable) o;
123 return runnable.equals(that.runnable);
124 }
125 return false;
126 }
127 @Override public int hashCode() {
128 return runnable.hashCode();
129 }
130 };
131 }
132 });
133 }
134
135 public void testFailsToForwardEquals() {
136 tester.includingEquals();
137 assertFailure(Runnable.class, new Function<Runnable, Runnable>() {
138 @Override public Runnable apply(final Runnable runnable) {
139 return new ForwardingRunnable(runnable) {
140 @Override public int hashCode() {
141 return runnable.hashCode();
142 }
143 };
144 }
145 }, "Runnable");
146 }
147
148 public void testFailsToForward() {
149 assertFailure(Runnable.class,
150 new Function<Runnable, Runnable>() {
151 @Override public Runnable apply(Runnable runnable) {
152 return new ForwardingRunnable(runnable) {
153 @Override public void run() {}
154 };
155 }
156 }, "run()", "Failed to forward");
157 }
158
159 public void testRedundantForwarding() {
160 assertFailure(Runnable.class,
161 new Function<Runnable, Runnable>() {
162 @Override public Runnable apply(final Runnable runnable) {
163 return new Runnable() {
164 @Override public void run() {
165 runnable.run();
166 runnable.run();
167 }
168 };
169 }
170 }, "run()", "invoked more than once");
171 }
172
173 public void testFailsToForwardParameters() {
174 assertFailure(Adder.class, new Function<Adder, Adder>() {
175 @Override public Adder apply(Adder adder) {
176 return new FailsToForwardParameters(adder);
177 }
178 }, "add(", "Parameter #0");
179 }
180
181 public void testForwardsToTheWrongMethod() {
182 assertFailure(Arithmetic.class, new Function<Arithmetic, Arithmetic>() {
183 @Override public Arithmetic apply(Arithmetic adder) {
184 return new ForwardsToTheWrongMethod(adder);
185 }
186 }, "minus");
187 }
188
189 public void testFailsToForwardReturnValue() {
190 assertFailure(Adder.class, new Function<Adder, Adder>() {
191 @Override public Adder apply(Adder adder) {
192 return new FailsToForwardReturnValue(adder);
193 }
194 }, "add(", "Return value");
195 }
196
197 public void testFailsToPropagateException() {
198 assertFailure(Adder.class, new Function<Adder, Adder>() {
199 @Override public Adder apply(Adder adder) {
200 return new FailsToPropagageException(adder);
201 }
202 }, "add(", "exception");
203 }
204
205 public void testNotInterfaceType() {
206 try {
207 new ForwardingWrapperTester().testForwarding(String.class, Functions.<String>identity());
208 fail();
209 } catch (IllegalArgumentException expected) {}
210 }
211
212 public void testNulls() {
213 new NullPointerTester()
214 .setDefault(Class.class, Runnable.class)
215 .testAllPublicInstanceMethods(new ForwardingWrapperTester());
216 }
217
218 private <T> void assertFailure(
219 Class<T> interfaceType, Function<T, ? extends T> wrapperFunction,
220 String... expectedMessages) {
221 try {
222 tester.testForwarding(interfaceType, wrapperFunction);
223 } catch (AssertionError expected) {
224 for (String message : expectedMessages) {
225 assertThat(expected.getMessage()).contains(message);
226 }
227 return;
228 }
229 fail("expected failure not reported");
230 }
231
232 private class ForwardingRunnable implements Runnable {
233
234 private final Runnable runnable;
235
236 ForwardingRunnable(Runnable runnable) {
237 this.runnable = runnable;
238 }
239
240 @Override public void run() {
241 runnable.run();
242 }
243
244 @Override public String toString() {
245 return runnable.toString();
246 }
247 }
248
249 private interface Adder {
250 int add(int a, int b);
251 }
252
253 private static class ForwardingArithmetic implements Arithmetic {
254 private final Arithmetic arithmetic;
255
256 public ForwardingArithmetic(Arithmetic arithmetic) {
257 this.arithmetic = arithmetic;
258 }
259
260 @Override public int add(int a, int b) {
261 return arithmetic.add(a, b);
262 }
263
264 @Override public int minus(int a, int b) {
265 return arithmetic.minus(a, b);
266 }
267
268 @Override public String toString() {
269 return arithmetic.toString();
270 }
271 }
272
273 private static class FailsToForwardParameters implements Adder {
274 private final Adder adder;
275
276 FailsToForwardParameters(Adder adder) {
277 this.adder = adder;
278 }
279
280 @Override public int add(int a, int b) {
281 return adder.add(b, a);
282 }
283
284 @Override public String toString() {
285 return adder.toString();
286 }
287 }
288
289 private static class FailsToForwardReturnValue implements Adder {
290 private final Adder adder;
291
292 FailsToForwardReturnValue(Adder adder) {
293 this.adder = adder;
294 }
295
296 @Override public int add(int a, int b) {
297 return adder.add(a, b) + 1;
298 }
299
300 @Override public String toString() {
301 return adder.toString();
302 }
303 }
304
305 private static class FailsToPropagageException implements Adder {
306 private final Adder adder;
307
308 FailsToPropagageException(Adder adder) {
309 this.adder = adder;
310 }
311
312 @Override public int add(int a, int b) {
313 try {
314 return adder.add(a, b);
315 } catch (Exception e) {
316
317 return 0;
318 }
319 }
320
321 @Override public String toString() {
322 return adder.toString();
323 }
324 }
325
326 public interface Arithmetic extends Adder {
327 int minus(int a, int b);
328 }
329
330 private static class ForwardsToTheWrongMethod implements Arithmetic {
331 private final Arithmetic arithmetic;
332
333 ForwardsToTheWrongMethod(Arithmetic arithmetic) {
334 this.arithmetic = arithmetic;
335 }
336
337 @Override public int minus(int a, int b) {
338 return arithmetic.add(b, a);
339 }
340
341 @Override public int add(int a, int b) {
342 return arithmetic.add(b, a);
343 }
344
345 @Override public String toString() {
346 return arithmetic.toString();
347 }
348 }
349
350 private interface ParameterTypesDifferent {
351 void foo(String s, Runnable r, Number n, Iterable<?> it, boolean b, Equivalence<String> eq,
352 Exception e, InputStream in, Comparable<?> c, Ordering<Integer> ord,
353 Charset charset, TimeUnit unit, Class<?> cls, Joiner joiner,
354 Pattern pattern, UnsignedInteger ui, UnsignedLong ul, StringBuilder sb,
355 Predicate<?> pred, Function<?, ?> func, Object obj);
356 }
357
358 private static class ParameterTypesDifferentForwarder implements ParameterTypesDifferent {
359 private final ParameterTypesDifferent delegate;
360
361 public ParameterTypesDifferentForwarder(ParameterTypesDifferent delegate) {
362 this.delegate = delegate;
363 }
364
365 @Override public void foo(
366 String s, Runnable r, Number n, Iterable<?> it, boolean b, Equivalence<String> eq,
367 Exception e, InputStream in, Comparable<?> c, Ordering<Integer> ord,
368 Charset charset, TimeUnit unit, Class<?> cls, Joiner joiner,
369 Pattern pattern, UnsignedInteger ui, UnsignedLong ul, StringBuilder sb,
370 Predicate<?> pred, Function<?, ?> func, Object obj) {
371 delegate.foo(s,
372 r, n, it, b, eq, e, in, c, ord, charset, unit, cls, joiner, pattern,
373 ui, ul, sb, pred, func, obj);
374 }
375
376 @Override public String toString() {
377 return delegate.toString();
378 }
379 }
380
381 public void testCovariantReturn() {
382 new ForwardingWrapperTester().testForwarding(Sub.class, new Function<Sub, Sub>() {
383 @Override public Sub apply(Sub sub) {
384 return new ForwardingSub(sub);
385 }
386 });
387 }
388
389 interface Base {
390 CharSequence getId();
391 }
392
393 interface Sub extends Base {
394 @Override String getId();
395 }
396
397 private static class ForwardingSub implements Sub {
398 private final Sub delegate;
399
400 ForwardingSub(Sub delegate) {
401 this.delegate = delegate;
402 }
403
404 @Override public String getId() {
405 return delegate.getId();
406 }
407
408 @Override public String toString() {
409 return delegate.toString();
410 }
411 }
412
413 private interface Equals {
414 @Override boolean equals(Object obj);
415 @Override int hashCode();
416 @Override String toString();
417 }
418
419 private static class NoDelegateToEquals implements Equals {
420
421 private static Function<Equals, Equals> WRAPPER = new Function<Equals, Equals>() {
422 @Override public NoDelegateToEquals apply(Equals delegate) {
423 return new NoDelegateToEquals(delegate);
424 }
425 };
426
427 private final Equals delegate;
428
429 NoDelegateToEquals(Equals delegate) {
430 this.delegate = delegate;
431 }
432
433 @Override public String toString() {
434 return delegate.toString();
435 }
436 }
437
438 public void testExplicitEqualsAndHashCodeNotDelegatedByDefault() {
439 new ForwardingWrapperTester()
440 .testForwarding(Equals.class, NoDelegateToEquals.WRAPPER);
441 }
442
443 public void testExplicitEqualsAndHashCodeDelegatedWhenExplicitlyAsked() {
444 try {
445 new ForwardingWrapperTester()
446 .includingEquals()
447 .testForwarding(Equals.class, NoDelegateToEquals.WRAPPER);
448 } catch (AssertionError expected) {
449 return;
450 }
451 fail("Should have failed");
452 }
453
454
455
456
457 private interface ChainingCalls {
458
459 ChainingCalls chainingCall();
460
461 ChainingCalls nonChainingCall();
462 }
463
464 private static class ForwardingChainingCalls implements ChainingCalls {
465 final ChainingCalls delegate;
466
467 ForwardingChainingCalls(ChainingCalls delegate) {
468 this.delegate = delegate;
469 }
470
471 @Override public ForwardingChainingCalls chainingCall() {
472 delegate.chainingCall();
473 return this;
474 }
475
476 @Override public ChainingCalls nonChainingCall() {
477 return delegate.nonChainingCall();
478 }
479
480 @Override public String toString() {
481 return delegate.toString();
482 }
483 }
484
485 public void testChainingCalls() {
486 tester.testForwarding(ChainingCalls.class,
487 new Function<ChainingCalls, ChainingCalls>() {
488 @Override public ChainingCalls apply(ChainingCalls delegate) {
489 return new ForwardingChainingCalls(delegate);
490 }
491 });
492 }
493 }