View Javadoc
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  
25  import junit.framework.TestCase;
26  
27  import java.io.Serializable;
28  import java.lang.reflect.Method;
29  import java.lang.reflect.Proxy;
30  import java.util.List;
31  
32  /**
33   * Tests for {@link AbstractInvocationHandler}.
34   *
35   * @author Ben Yu
36   */
37  public class AbstractInvocationHandlerTest extends TestCase {
38  
39    private static final ImmutableList<String> LIST1 = ImmutableList.of("one", "two");
40    private static final ImmutableList<String> LIST2 = ImmutableList.of("three");
41  
42    public void testDelegate() {
43      assertEquals(LIST1, ImmutableList.copyOf(newDelegatingList(LIST1)));
44      assertEquals(LIST1, ImmutableList.copyOf(newDelegatingListWithEquals(LIST1)));
45    }
46  
47    public void testToString() {
48      List<String> proxy = newDelegatingList(LIST1);
49      assertEquals(Proxy.getInvocationHandler(proxy).toString(), proxy.toString());
50    }
51  
52    interface A {}
53    interface B{}
54  
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(
70              newProxyWithEqualsForInterfaces(Runnable.class, List.class))
71          .addEqualityGroup(
72              newDelegatingListWithEquals(LIST1),
73              newDelegatingListWithEquals(LIST1),
74              SerializableTester.reserialize(newDelegatingListWithEquals(LIST1)))
75          .addEqualityGroup(
76              newDelegatingListWithEquals(LIST2),
77              newProxyWithSubHandler1(LIST2), // Makes sure type of handler doesn't affect equality
78              newProxyWithSubHandler2(LIST2))
79          .addEqualityGroup(newDelegatingIterableWithEquals(LIST2)) // different interface
80          .testEquals();
81    }
82  
83    @SuppressWarnings("unchecked") // proxy of List<String>
84    private static List<String> newDelegatingList(List<String> delegate) {
85      return Reflection.newProxy(List.class, new DelegatingInvocationHandler(delegate));
86    }
87  
88    @SuppressWarnings("unchecked") // proxy of List<String>
89    private static List<String> newDelegatingListWithEquals(List<String> delegate) {
90      return Reflection.newProxy(List.class, new DelegatingInvocationHandlerWithEquals(delegate));
91    }
92  
93    @SuppressWarnings("unchecked") // proxy of Iterable<String>
94    private static Iterable<String> newDelegatingIterableWithEquals(Iterable<String> delegate) {
95      return Reflection.newProxy(Iterable.class, new DelegatingInvocationHandlerWithEquals(delegate));
96    }
97  
98    @SuppressWarnings("unchecked") // proxy of List<String>
99    private static List<String> newProxyWithSubHandler1(List<String> delegate) {
100     return Reflection.newProxy(List.class, new SubHandler1(delegate));
101   }
102 
103   @SuppressWarnings("unchecked") // proxy of List<String>
104   private static List<String> newProxyWithSubHandler2(List<String> delegate) {
105     return Reflection.newProxy(List.class, new SubHandler2(delegate));
106   }
107 
108   private static Object newProxyWithEqualsForInterfaces(
109       Class<?>... interfaces) {
110     return Proxy.newProxyInstance(AbstractInvocationHandlerTest.class.getClassLoader(),
111         interfaces, new DelegatingInvocationHandlerWithEquals("a string"));
112   }
113 
114   private static class DelegatingInvocationHandler extends AbstractInvocationHandler
115       implements Serializable {
116     final Object delegate;
117 
118     DelegatingInvocationHandler(Object delegate) {
119       this.delegate = checkNotNull(delegate);
120     }
121 
122     @Override protected Object handleInvocation(Object proxy, Method method, Object[] args)
123         throws Throwable {
124       return method.invoke(delegate, args);
125     }
126 
127     @Override public String toString() {
128       return "some arbitrary string";
129     }
130   }
131 
132   private static class DelegatingInvocationHandlerWithEquals extends DelegatingInvocationHandler {
133 
134     DelegatingInvocationHandlerWithEquals(Object delegate) {
135       super(delegate);
136     }
137 
138     @Override public boolean equals(Object obj) {
139       if (obj instanceof DelegatingInvocationHandlerWithEquals) {
140         DelegatingInvocationHandlerWithEquals that = (DelegatingInvocationHandlerWithEquals) obj;
141         return delegate.equals(that.delegate);
142       } else {
143         return false;
144       }
145     }
146 
147     @Override public int hashCode() {
148       return delegate.hashCode();
149     }
150 
151     @Override public String toString() {
152       return "another arbitrary string";
153     }
154   }
155 
156   private static class SubHandler1 extends DelegatingInvocationHandlerWithEquals {
157     SubHandler1(Object delegate) {
158       super(delegate);
159     }
160   }
161 
162   private static class SubHandler2 extends DelegatingInvocationHandlerWithEquals {
163     SubHandler2(Object delegate) {
164       super(delegate);
165     }
166   }
167 }