Home | History | Annotate | Download | only in reflect
      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 }
    168