Java
627 строк · 15.7 Кб
1/*
2* Copyright (C) 2012 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.testing.anotherpackage;
18
19import static com.google.common.truth.Truth.assertThat;
20import static org.junit.Assert.assertThrows;
21
22import com.google.common.base.Equivalence;
23import com.google.common.base.Function;
24import com.google.common.base.Functions;
25import com.google.common.base.Joiner;
26import com.google.common.base.Predicate;
27import com.google.common.collect.Ordering;
28import com.google.common.primitives.UnsignedInteger;
29import com.google.common.primitives.UnsignedLong;
30import com.google.common.testing.ForwardingWrapperTester;
31import com.google.common.testing.NullPointerTester;
32import com.google.errorprone.annotations.CanIgnoreReturnValue;
33import java.io.InputStream;
34import java.nio.charset.Charset;
35import java.util.concurrent.TimeUnit;
36import java.util.regex.Pattern;
37import junit.framework.AssertionFailedError;
38import junit.framework.TestCase;
39import org.checkerframework.checker.nullness.qual.Nullable;
40
41/**
42* Tests for {@link ForwardingWrapperTester}. Live in a different package to detect reflection
43* access issues, if any.
44*
45* @author Ben Yu
46*/
47public class ForwardingWrapperTesterTest extends TestCase {
48
49private final ForwardingWrapperTester tester = new ForwardingWrapperTester();
50
51public void testGoodForwarder() {
52tester.testForwarding(
53Arithmetic.class,
54new Function<Arithmetic, Arithmetic>() {
55@Override
56public Arithmetic apply(Arithmetic arithmetic) {
57return new ForwardingArithmetic(arithmetic);
58}
59});
60tester.testForwarding(
61ParameterTypesDifferent.class,
62new Function<ParameterTypesDifferent, ParameterTypesDifferent>() {
63@Override
64public ParameterTypesDifferent apply(ParameterTypesDifferent delegate) {
65return new ParameterTypesDifferentForwarder(delegate);
66}
67});
68}
69
70public void testVoidMethodForwarding() {
71tester.testForwarding(
72Runnable.class,
73new Function<Runnable, Runnable>() {
74@Override
75public Runnable apply(final Runnable runnable) {
76return new ForwardingRunnable(runnable);
77}
78});
79}
80
81public void testToStringForwarding() {
82tester.testForwarding(
83Runnable.class,
84new Function<Runnable, Runnable>() {
85@Override
86public Runnable apply(final Runnable runnable) {
87return new ForwardingRunnable(runnable) {
88@Override
89public String toString() {
90return runnable.toString();
91}
92};
93}
94});
95}
96
97public void testFailsToForwardToString() {
98assertFailure(
99Runnable.class,
100new Function<Runnable, Runnable>() {
101@Override
102public Runnable apply(final Runnable runnable) {
103return new ForwardingRunnable(runnable) {
104@Override
105public String toString() {
106return "";
107}
108};
109}
110},
111"toString()");
112}
113
114public void testFailsToForwardHashCode() {
115tester.includingEquals();
116assertFailure(
117Runnable.class,
118new Function<Runnable, Runnable>() {
119@Override
120public Runnable apply(final Runnable runnable) {
121return new ForwardingRunnable(runnable) {
122
123@SuppressWarnings("EqualsHashCode")
124@Override
125public boolean equals(@Nullable Object o) {
126if (o instanceof ForwardingRunnable) {
127ForwardingRunnable that = (ForwardingRunnable) o;
128return runnable.equals(that.runnable);
129}
130return false;
131}
132};
133}
134},
135"Runnable");
136}
137
138public void testEqualsAndHashCodeForwarded() {
139tester.includingEquals();
140tester.testForwarding(
141Runnable.class,
142new Function<Runnable, Runnable>() {
143@Override
144public Runnable apply(final Runnable runnable) {
145return new ForwardingRunnable(runnable) {
146@Override
147public boolean equals(@Nullable Object o) {
148if (o instanceof ForwardingRunnable) {
149ForwardingRunnable that = (ForwardingRunnable) o;
150return runnable.equals(that.runnable);
151}
152return false;
153}
154
155@Override
156public int hashCode() {
157return runnable.hashCode();
158}
159};
160}
161});
162}
163
164public void testFailsToForwardEquals() {
165tester.includingEquals();
166assertFailure(
167Runnable.class,
168new Function<Runnable, Runnable>() {
169@Override
170public Runnable apply(final Runnable runnable) {
171return new ForwardingRunnable(runnable) {
172@Override
173public int hashCode() {
174return runnable.hashCode();
175}
176};
177}
178},
179"Runnable");
180}
181
182public void testFailsToForward() {
183assertFailure(
184Runnable.class,
185new Function<Runnable, Runnable>() {
186@Override
187public Runnable apply(Runnable runnable) {
188return new ForwardingRunnable(runnable) {
189@Override
190public void run() {}
191};
192}
193},
194"run()",
195"Failed to forward");
196}
197
198public void testRedundantForwarding() {
199assertFailure(
200Runnable.class,
201new Function<Runnable, Runnable>() {
202@Override
203public Runnable apply(final Runnable runnable) {
204return new Runnable() {
205@Override
206public void run() {
207runnable.run();
208runnable.run();
209}
210};
211}
212},
213"run()",
214"invoked more than once");
215}
216
217public void testFailsToForwardParameters() {
218assertFailure(
219Adder.class,
220new Function<Adder, Adder>() {
221@Override
222public Adder apply(Adder adder) {
223return new FailsToForwardParameters(adder);
224}
225},
226"add(",
227"Parameter #0");
228}
229
230public void testForwardsToTheWrongMethod() {
231assertFailure(
232Arithmetic.class,
233new Function<Arithmetic, Arithmetic>() {
234@Override
235public Arithmetic apply(Arithmetic adder) {
236return new ForwardsToTheWrongMethod(adder);
237}
238},
239"minus");
240}
241
242public void testFailsToForwardReturnValue() {
243assertFailure(
244Adder.class,
245new Function<Adder, Adder>() {
246@Override
247public Adder apply(Adder adder) {
248return new FailsToForwardReturnValue(adder);
249}
250},
251"add(",
252"Return value");
253}
254
255public void testFailsToPropagateException() {
256assertFailure(
257Adder.class,
258new Function<Adder, Adder>() {
259@Override
260public Adder apply(Adder adder) {
261return new FailsToPropagateException(adder);
262}
263},
264"add(",
265"exception");
266}
267
268public void testNotInterfaceType() {
269assertThrows(
270IllegalArgumentException.class,
271() ->
272new ForwardingWrapperTester()
273.testForwarding(String.class, Functions.<String>identity()));
274}
275
276public void testNulls() {
277new NullPointerTester()
278.setDefault(Class.class, Runnable.class)
279.testAllPublicInstanceMethods(new ForwardingWrapperTester());
280}
281
282private <T> void assertFailure(
283Class<T> interfaceType,
284Function<T, ? extends T> wrapperFunction,
285String... expectedMessages) {
286try {
287tester.testForwarding(interfaceType, wrapperFunction);
288} catch (AssertionFailedError expected) {
289for (String message : expectedMessages) {
290assertThat(expected.getMessage()).contains(message);
291}
292return;
293}
294fail("expected failure not reported");
295}
296
297private class ForwardingRunnable implements Runnable {
298
299private final Runnable runnable;
300
301ForwardingRunnable(Runnable runnable) {
302this.runnable = runnable;
303}
304
305@Override
306public void run() {
307runnable.run();
308}
309
310@Override
311public String toString() {
312return runnable.toString();
313}
314}
315
316private interface Adder {
317int add(int a, int b);
318}
319
320private static class ForwardingArithmetic implements Arithmetic {
321private final Arithmetic arithmetic;
322
323public ForwardingArithmetic(Arithmetic arithmetic) {
324this.arithmetic = arithmetic;
325}
326
327@Override
328public int add(int a, int b) {
329return arithmetic.add(a, b);
330}
331
332@Override
333public int minus(int a, int b) {
334return arithmetic.minus(a, b);
335}
336
337@Override
338public String toString() {
339return arithmetic.toString();
340}
341}
342
343private static class FailsToForwardParameters implements Adder {
344private final Adder adder;
345
346FailsToForwardParameters(Adder adder) {
347this.adder = adder;
348}
349
350@Override
351public int add(int a, int b) {
352return adder.add(b, a);
353}
354
355@Override
356public String toString() {
357return adder.toString();
358}
359}
360
361private static class FailsToForwardReturnValue implements Adder {
362private final Adder adder;
363
364FailsToForwardReturnValue(Adder adder) {
365this.adder = adder;
366}
367
368@Override
369public int add(int a, int b) {
370return adder.add(a, b) + 1;
371}
372
373@Override
374public String toString() {
375return adder.toString();
376}
377}
378
379private static class FailsToPropagateException implements Adder {
380private final Adder adder;
381
382FailsToPropagateException(Adder adder) {
383this.adder = adder;
384}
385
386@Override
387public int add(int a, int b) {
388try {
389return adder.add(a, b);
390} catch (Exception e) {
391// swallow!
392return 0;
393}
394}
395
396@Override
397public String toString() {
398return adder.toString();
399}
400}
401
402public interface Arithmetic extends Adder {
403int minus(int a, int b);
404}
405
406private static class ForwardsToTheWrongMethod implements Arithmetic {
407private final Arithmetic arithmetic;
408
409ForwardsToTheWrongMethod(Arithmetic arithmetic) {
410this.arithmetic = arithmetic;
411}
412
413@Override
414public int minus(int a, int b) { // bad!
415return arithmetic.add(a, b);
416}
417
418@Override
419public int add(int a, int b) {
420return arithmetic.add(a, b);
421}
422
423@Override
424public String toString() {
425return arithmetic.toString();
426}
427}
428
429private interface ParameterTypesDifferent {
430void foo(
431String s,
432Runnable r,
433Number n,
434Iterable<?> it,
435boolean b,
436Equivalence<String> eq,
437Exception e,
438InputStream in,
439Comparable<?> c,
440Ordering<Integer> ord,
441Charset charset,
442TimeUnit unit,
443Class<?> cls,
444Joiner joiner,
445Pattern pattern,
446UnsignedInteger ui,
447UnsignedLong ul,
448StringBuilder sb,
449Predicate<?> pred,
450Function<?, ?> func,
451Object obj);
452}
453
454private static class ParameterTypesDifferentForwarder implements ParameterTypesDifferent {
455private final ParameterTypesDifferent delegate;
456
457public ParameterTypesDifferentForwarder(ParameterTypesDifferent delegate) {
458this.delegate = delegate;
459}
460
461@Override
462public void foo(
463String s,
464Runnable r,
465Number n,
466Iterable<?> it,
467boolean b,
468Equivalence<String> eq,
469Exception e,
470InputStream in,
471Comparable<?> c,
472Ordering<Integer> ord,
473Charset charset,
474TimeUnit unit,
475Class<?> cls,
476Joiner joiner,
477Pattern pattern,
478UnsignedInteger ui,
479UnsignedLong ul,
480StringBuilder sb,
481Predicate<?> pred,
482Function<?, ?> func,
483Object obj) {
484delegate.foo(
485s, r, n, it, b, eq, e, in, c, ord, charset, unit, cls, joiner, pattern, ui, ul, sb, pred,
486func, obj);
487}
488
489@Override
490public String toString() {
491return delegate.toString();
492}
493}
494
495public void testCovariantReturn() {
496new ForwardingWrapperTester()
497.testForwarding(
498Sub.class,
499new Function<Sub, Sub>() {
500@Override
501public Sub apply(Sub sub) {
502return new ForwardingSub(sub);
503}
504});
505}
506
507interface Base {
508CharSequence getId();
509}
510
511interface Sub extends Base {
512@Override
513String getId();
514}
515
516private static class ForwardingSub implements Sub {
517private final Sub delegate;
518
519ForwardingSub(Sub delegate) {
520this.delegate = delegate;
521}
522
523@Override
524public String getId() {
525return delegate.getId();
526}
527
528@Override
529public String toString() {
530return delegate.toString();
531}
532}
533
534private interface Equals {
535@Override
536boolean equals(@Nullable Object obj);
537
538@Override
539int hashCode();
540
541@Override
542String toString();
543}
544
545private static class NoDelegateToEquals implements Equals {
546
547private static Function<Equals, Equals> WRAPPER =
548new Function<Equals, Equals>() {
549@Override
550public NoDelegateToEquals apply(Equals delegate) {
551return new NoDelegateToEquals(delegate);
552}
553};
554
555private final Equals delegate;
556
557NoDelegateToEquals(Equals delegate) {
558this.delegate = delegate;
559}
560
561@Override
562public String toString() {
563return delegate.toString();
564}
565}
566
567public void testExplicitEqualsAndHashCodeNotDelegatedByDefault() {
568new ForwardingWrapperTester().testForwarding(Equals.class, NoDelegateToEquals.WRAPPER);
569}
570
571public void testExplicitEqualsAndHashCodeDelegatedWhenExplicitlyAsked() {
572try {
573new ForwardingWrapperTester()
574.includingEquals()
575.testForwarding(Equals.class, NoDelegateToEquals.WRAPPER);
576} catch (AssertionFailedError expected) {
577return;
578}
579fail("Should have failed");
580}
581
582/** An interface for the 2 ways that a chaining call might be defined. */
583private interface ChainingCalls {
584// A method that is defined to 'return this'
585@CanIgnoreReturnValue
586ChainingCalls chainingCall();
587
588// A method that just happens to return a ChainingCalls object
589ChainingCalls nonChainingCall();
590}
591
592private static class ForwardingChainingCalls implements ChainingCalls {
593final ChainingCalls delegate;
594
595ForwardingChainingCalls(ChainingCalls delegate) {
596this.delegate = delegate;
597}
598
599@CanIgnoreReturnValue
600@Override
601public ForwardingChainingCalls chainingCall() {
602delegate.chainingCall();
603return this;
604}
605
606@Override
607public ChainingCalls nonChainingCall() {
608return delegate.nonChainingCall();
609}
610
611@Override
612public String toString() {
613return delegate.toString();
614}
615}
616
617public void testChainingCalls() {
618tester.testForwarding(
619ChainingCalls.class,
620new Function<ChainingCalls, ChainingCalls>() {
621@Override
622public ChainingCalls apply(ChainingCalls delegate) {
623return new ForwardingChainingCalls(delegate);
624}
625});
626}
627}
628