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.reflect; 18 19import static com.google.common.base.Preconditions.checkNotNull; 20 21import com.google.common.collect.ImmutableList; 22import com.google.common.testing.EqualsTester; 23import com.google.common.testing.SerializableTester; 24 25import junit.framework.TestCase; 26 27import java.io.Serializable; 28import java.lang.reflect.Method; 29import java.lang.reflect.Proxy; 30import java.util.List; 31 32/** 33 * Tests for {@link AbstractInvocationHandler}. 34 * 35 * @author Ben Yu 36 */ 37public 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} 168