• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.common.reflect;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.collect.ImmutableList;
22 import com.google.common.testing.EqualsTester;
23 import com.google.common.testing.SerializableTester;
24 import java.io.Serializable;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Proxy;
27 import java.util.List;
28 import junit.framework.TestCase;
29 import org.checkerframework.checker.nullness.qual.Nullable;
30 
31 /**
32  * Tests for {@link AbstractInvocationHandler}.
33  *
34  * @author Ben Yu
35  */
36 public class AbstractInvocationHandlerTest extends TestCase {
37 
38   private static final ImmutableList<String> LIST1 = ImmutableList.of("one", "two");
39   private static final ImmutableList<String> LIST2 = ImmutableList.of("three");
40 
testDelegate()41   public void testDelegate() {
42     assertEquals(LIST1, ImmutableList.copyOf(newDelegatingList(LIST1)));
43     assertEquals(LIST1, ImmutableList.copyOf(newDelegatingListWithEquals(LIST1)));
44   }
45 
testToString()46   public void testToString() {
47     List<String> proxy = newDelegatingList(LIST1);
48     assertEquals(Proxy.getInvocationHandler(proxy).toString(), proxy.toString());
49   }
50 
51   interface A {}
52 
53   interface B {}
54 
testEquals()55   public void testEquals() {
56     class AB implements A, B {}
57     class BA implements B, A {}
58     AB ab = new AB();
59     BA ba = new BA();
60     new EqualsTester()
61         .addEqualityGroup(newDelegatingList(LIST1))
62         // Actually, this violates List#equals contract.
63         // But whatever, no one is going to proxy List (hopefully).
64         .addEqualityGroup(newDelegatingList(LIST1))
65         .addEqualityGroup(newDelegatingList(LIST2))
66         .addEqualityGroup(
67             newProxyWithEqualsForInterfaces(List.class, Runnable.class),
68             newProxyWithEqualsForInterfaces(List.class, Runnable.class))
69         .addEqualityGroup(newProxyWithEqualsForInterfaces(Runnable.class, List.class))
70         .addEqualityGroup(
71             newDelegatingListWithEquals(LIST1),
72             newDelegatingListWithEquals(LIST1),
73             SerializableTester.reserialize(newDelegatingListWithEquals(LIST1)))
74         .addEqualityGroup(
75             newDelegatingListWithEquals(LIST2),
76             newProxyWithSubHandler1(LIST2), // Makes sure type of handler doesn't affect equality
77             newProxyWithSubHandler2(LIST2))
78         .addEqualityGroup(newDelegatingIterableWithEquals(LIST2)) // different interface
79         .testEquals();
80   }
81 
82   @SuppressWarnings("unchecked") // proxy of List<String>
newDelegatingList(List<String> delegate)83   private static List<String> newDelegatingList(List<String> delegate) {
84     return Reflection.newProxy(List.class, new DelegatingInvocationHandler(delegate));
85   }
86 
87   @SuppressWarnings("unchecked") // proxy of List<String>
newDelegatingListWithEquals(List<String> delegate)88   private static List<String> newDelegatingListWithEquals(List<String> delegate) {
89     return Reflection.newProxy(List.class, new DelegatingInvocationHandlerWithEquals(delegate));
90   }
91 
92   @SuppressWarnings("unchecked") // proxy of Iterable<String>
newDelegatingIterableWithEquals(Iterable<String> delegate)93   private static Iterable<String> newDelegatingIterableWithEquals(Iterable<String> delegate) {
94     return Reflection.newProxy(Iterable.class, new DelegatingInvocationHandlerWithEquals(delegate));
95   }
96 
97   @SuppressWarnings("unchecked") // proxy of List<String>
newProxyWithSubHandler1(List<String> delegate)98   private static List<String> newProxyWithSubHandler1(List<String> delegate) {
99     return Reflection.newProxy(List.class, new SubHandler1(delegate));
100   }
101 
102   @SuppressWarnings("unchecked") // proxy of List<String>
newProxyWithSubHandler2(List<String> delegate)103   private static List<String> newProxyWithSubHandler2(List<String> delegate) {
104     return Reflection.newProxy(List.class, new SubHandler2(delegate));
105   }
106 
newProxyWithEqualsForInterfaces(Class<?>.... interfaces)107   private static Object newProxyWithEqualsForInterfaces(Class<?>... interfaces) {
108     return Proxy.newProxyInstance(
109         AbstractInvocationHandlerTest.class.getClassLoader(),
110         interfaces,
111         new DelegatingInvocationHandlerWithEquals("a string"));
112   }
113 
114   private static class DelegatingInvocationHandler extends AbstractInvocationHandler
115       implements Serializable {
116     final Object delegate;
117 
DelegatingInvocationHandler(Object delegate)118     DelegatingInvocationHandler(Object delegate) {
119       this.delegate = checkNotNull(delegate);
120     }
121 
122     @Override
handleInvocation(Object proxy, Method method, Object[] args)123     protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
124       return method.invoke(delegate, args);
125     }
126 
127     @Override
toString()128     public String toString() {
129       return "some arbitrary string";
130     }
131   }
132 
133   private static class DelegatingInvocationHandlerWithEquals extends DelegatingInvocationHandler {
134 
DelegatingInvocationHandlerWithEquals(Object delegate)135     DelegatingInvocationHandlerWithEquals(Object delegate) {
136       super(delegate);
137     }
138 
139     @Override
equals(@ullable Object obj)140     public boolean equals(@Nullable Object obj) {
141       if (obj instanceof DelegatingInvocationHandlerWithEquals) {
142         DelegatingInvocationHandlerWithEquals that = (DelegatingInvocationHandlerWithEquals) obj;
143         return delegate.equals(that.delegate);
144       } else {
145         return false;
146       }
147     }
148 
149     @Override
hashCode()150     public int hashCode() {
151       return delegate.hashCode();
152     }
153 
154     @Override
toString()155     public String toString() {
156       return "another arbitrary string";
157     }
158   }
159 
160   private static class SubHandler1 extends DelegatingInvocationHandlerWithEquals {
SubHandler1(Object delegate)161     SubHandler1(Object delegate) {
162       super(delegate);
163     }
164   }
165 
166   private static class SubHandler2 extends DelegatingInvocationHandlerWithEquals {
SubHandler2(Object delegate)167     SubHandler2(Object delegate) {
168       super(delegate);
169     }
170   }
171 }
172