Home | History | Annotate | Download | only in reflect
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package tests.api.java.lang.reflect;
     19 
     20 import dalvik.annotation.KnownFailure;
     21 import dalvik.annotation.TestLevel;
     22 import dalvik.annotation.TestTargetNew;
     23 import dalvik.annotation.TestTargetClass;
     24 
     25 import java.lang.reflect.InvocationHandler;
     26 import java.lang.reflect.Method;
     27 import java.lang.reflect.Proxy;
     28 import java.lang.reflect.UndeclaredThrowableException;
     29 
     30 import tests.support.Support_Proxy_I1;
     31 import tests.support.Support_Proxy_I2;
     32 import tests.support.Support_Proxy_ParentException;
     33 import tests.support.Support_Proxy_SubException;
     34 
     35 @TestTargetClass(
     36         value = Proxy.class,
     37         untestedMethods= {
     38             @TestTargetNew(
     39                 level = TestLevel.NOT_NECESSARY,
     40                 notes = "Interface without implementation. Whether method is " +
     41                         "called from proxy is tested by ProxyTest.",
     42                 clazz = InvocationHandler.class,
     43                 method = "invoke",
     44                 args = { Object.class, Method.class, Object[].class }
     45             )
     46         }
     47 )
     48 public class ProxyTest extends junit.framework.TestCase {
     49 
     50     /*
     51      * When multiple interfaces define the same method, the list of thrown
     52      * exceptions are those which can be mapped to another exception in the
     53      * other method:
     54      *
     55      * String foo(String s) throws SubException, LinkageError;
     56      *
     57      * UndeclaredThrowableException wrappers any checked exception which is not
     58      * in the merged list. So ParentException would be wrapped, BUT LinkageError
     59      * would not be since its not an Error/RuntimeException.
     60      *
     61      * interface I1 { String foo(String s) throws ParentException, LinkageError; }
     62      * interface I2 { String foo(String s) throws SubException, Error; }
     63      */
     64 
     65     interface Broken1 {
     66         public float method(float _number0, float _number1);
     67     }
     68 
     69     class Broken1Invoke implements InvocationHandler {
     70         public Object invoke(Object proxy, Method method, Object[] args)
     71                 throws Throwable {
     72             return args[1];
     73         }
     74     }
     75 
     76     class ProxyCoonstructorTest extends Proxy {
     77         protected ProxyCoonstructorTest(InvocationHandler h) {
     78             super(h);
     79         }
     80     }
     81 
     82     /**
     83      * @tests java.lang.reflect.Proxy#getProxyClass(java.lang.ClassLoader,
     84      *        java.lang.Class[])
     85      */
     86     @TestTargetNew(
     87         level = TestLevel.COMPLETE,
     88         notes = "",
     89         method = "getProxyClass",
     90         args = {java.lang.ClassLoader.class, java.lang.Class[].class}
     91     )
     92     public void test_getProxyClassLjava_lang_ClassLoader$Ljava_lang_Class() {
     93         Class proxy = Proxy.getProxyClass(Support_Proxy_I1.class
     94                 .getClassLoader(), new Class[] { Support_Proxy_I1.class });
     95 
     96         assertTrue("Did not create a Proxy subclass ",
     97                 proxy.getSuperclass() == Proxy.class);
     98         assertTrue("Does not believe its a Proxy class ", Proxy
     99                 .isProxyClass(proxy));
    100 
    101         assertTrue("Does not believe it's a Proxy class ", Proxy
    102                 .isProxyClass(Proxy.getProxyClass(null,
    103                         new Class[] { Comparable.class })));
    104 
    105         boolean aborted = false;
    106 // TODO: We load the test classes in the bootclasspath, so they are visible
    107 // to the default loader. We can re-enable this test once we move the CTS
    108 // tests to the system classpath.
    109 //
    110 //        try {
    111 //            Proxy.getProxyClass(null, new Class[] { Support_Proxy_I1.class,
    112 //                    Support_Proxy_I2.class });
    113 //        } catch (IllegalArgumentException e) {
    114 //            aborted = true;
    115 //        }
    116 //        assertTrue("Default classLoader should not see app class ", aborted);
    117 
    118         aborted = false;
    119         try {
    120             Proxy.getProxyClass(Support_Proxy_I1.class.getClassLoader(),
    121                     (Class<?>[]) null);
    122             fail("NPE expected");
    123         } catch (NullPointerException e) {
    124             aborted = true;
    125         }
    126         assertTrue("NPE not thrown", aborted);
    127 
    128         aborted = false;
    129         try {
    130             Proxy.getProxyClass(Support_Proxy_I1.class.getClassLoader(),
    131                     new Class<?>[] {Support_Proxy_I1.class, null});
    132             fail("NPE expected");
    133         } catch (NullPointerException e) {
    134             aborted = true;
    135         }
    136         assertTrue("NPE not thrown", aborted);
    137     }
    138 
    139     /**
    140      * @tests java.lang.reflect.Proxy#Proxy(java.lang.reflect.InvocationHandler)
    141      */
    142     @TestTargetNew(
    143         level = TestLevel.COMPLETE,
    144         notes = "",
    145         method = "Proxy",
    146         args = {java.lang.reflect.InvocationHandler.class}
    147     )
    148     public void test_ProxyLjava_lang_reflect_InvocationHandler() {
    149         assertNotNull(new ProxyCoonstructorTest(new InvocationHandler() {
    150             public Object invoke(Object proxy, Method method, Object[] args)
    151                     throws Throwable {
    152                 return null;
    153             }
    154         }));
    155     }
    156 
    157 
    158 
    159     /**
    160      * @tests java.lang.reflect.Proxy#newProxyInstance(java.lang.ClassLoader,
    161      *        java.lang.Class[], java.lang.reflect.InvocationHandler)
    162      */
    163     @TestTargetNew(
    164         level = TestLevel.COMPLETE,
    165         notes = "",
    166         method = "newProxyInstance",
    167         args = {java.lang.ClassLoader.class, java.lang.Class[].class, java.lang.reflect.InvocationHandler.class}
    168     )
    169     public void test_newProxyInstanceLjava_lang_ClassLoader$Ljava_lang_ClassLjava_lang_reflect_InvocationHandler() {
    170         Object p = Proxy.newProxyInstance(Support_Proxy_I1.class
    171                 .getClassLoader(), new Class[] { Support_Proxy_I1.class,
    172                 Support_Proxy_I2.class }, new InvocationHandler() {
    173             public Object invoke(Object proxy, Method method, Object[] args)
    174                     throws Throwable {
    175                 if (method.getName().equals("equals"))
    176                     return new Boolean(proxy == args[0]);
    177                 if (method.getName().equals("array"))
    178                     return new int[] { (int) ((long[]) args[0])[1], -1 };
    179                 if (method.getName().equals("string")) {
    180                     if ("".equals(args[0]))
    181                         throw new Support_Proxy_SubException();
    182                     if ("clone".equals(args[0]))
    183                         throw new Support_Proxy_ParentException();
    184                     if ("error".equals(args[0]))
    185                         throw new ArrayStoreException();
    186                     if ("any".equals(args[0]))
    187                         throw new IllegalAccessException();
    188                 }
    189                 return null;
    190             }
    191         });
    192 
    193         Support_Proxy_I1 proxy = (Support_Proxy_I1) p;
    194         assertTrue("Failed identity test ", proxy.equals(proxy));
    195         assertTrue("Failed not equals test ", !proxy.equals(""));
    196         int[] result = (int[]) proxy.array(new long[] { 100L, -200L });
    197         assertEquals("Failed primitive type conversion test ", -200, result[0]);
    198 
    199         boolean worked = false;
    200         try {
    201             proxy.string("");
    202         } catch (Support_Proxy_SubException e) {
    203             worked = true;
    204         } catch (Support_Proxy_ParentException e) { // is never thrown
    205         }
    206         assertTrue("Problem converting exception ", worked);
    207 
    208         worked = false;
    209         try {
    210             proxy.string("clone");
    211         } catch (Support_Proxy_ParentException e) { // is never thrown
    212         } catch (UndeclaredThrowableException e) {
    213             worked = true;
    214         }
    215         assertTrue("Problem converting exception ", worked);
    216 
    217         worked = false;
    218         try {
    219             proxy.string("error");
    220         } catch (Support_Proxy_ParentException e) { // is never thrown
    221         } catch (UndeclaredThrowableException e) {
    222         } catch (RuntimeException e) {
    223             worked = e.getClass() == ArrayStoreException.class;
    224         }
    225         assertTrue("Problem converting exception ", worked);
    226 
    227         worked = false;
    228         try {
    229             proxy.string("any");
    230         } catch (Support_Proxy_ParentException e) { // is never thrown
    231         } catch (UndeclaredThrowableException e) {
    232             worked = true;
    233         }
    234         assertTrue("Problem converting exception ", worked);
    235 
    236         Broken1 proxyObject = null;
    237         try {
    238             proxyObject = (Broken1) Proxy.newProxyInstance(Broken1.class
    239                     .getClassLoader(), new Class[] { Broken1.class },
    240                     new Broken1Invoke());
    241         } catch (Throwable e) {
    242             fail("Failed to create proxy for class: " + Broken1.class + " - "
    243                     + e);
    244         }
    245         float brokenResult = proxyObject.method(2.1f, 5.8f);
    246         assertTrue("Invalid invoke result", brokenResult == 5.8f);
    247     }
    248 
    249     /**
    250      * @tests java.lang.reflect.Proxy#isProxyClass(java.lang.Class)
    251      */
    252     @TestTargetNew(
    253         level = TestLevel.COMPLETE,
    254         notes = "",
    255         method = "isProxyClass",
    256         args = {java.lang.Class.class}
    257     )
    258     public void test_isProxyClassLjava_lang_Class() {
    259         Class proxy = Proxy.getProxyClass(Support_Proxy_I1.class
    260                 .getClassLoader(), new Class[] { Support_Proxy_I1.class });
    261 
    262         class Fake extends Proxy {
    263             Fake() {
    264                 super(null);
    265             }
    266         }
    267 
    268         Proxy fake = new Proxy(new InvocationHandler() {
    269             public Object invoke(Object proxy, Method method, Object[] args)
    270                     throws Throwable {
    271                 return null;
    272             }
    273         }) {
    274         };
    275 
    276         assertTrue("Does not believe its a Proxy class ", Proxy
    277                 .isProxyClass(proxy));
    278         assertTrue("Proxy subclasses do not count ", !Proxy
    279                 .isProxyClass(Fake.class));
    280         assertTrue("Is not a runtime generated Proxy class ", !Proxy
    281                 .isProxyClass(fake.getClass()));
    282         boolean thrown = false;
    283         try{
    284         Proxy.isProxyClass(null);
    285         } catch (NullPointerException ex){
    286             thrown = true;
    287         }
    288         assertTrue("NPE not thrown.", thrown);
    289     }
    290 
    291     /**
    292      * @tests java.lang.reflect.Proxy#getInvocationHandler(java.lang.Object)
    293      */
    294     @TestTargetNew(
    295         level = TestLevel.COMPLETE,
    296         notes = "",
    297         method = "getInvocationHandler",
    298         args = {java.lang.Object.class}
    299     )
    300     public void test_getInvocationHandlerLjava_lang_Object() {
    301         InvocationHandler handler = new InvocationHandler() {
    302             public Object invoke(Object proxy, Method method, Object[] args)
    303                     throws Throwable {
    304                 return null;
    305             }
    306         };
    307 
    308         Object p = Proxy.newProxyInstance(Support_Proxy_I1.class
    309                 .getClassLoader(), new Class[] { Support_Proxy_I1.class },
    310                 handler);
    311 
    312         assertTrue("Did not return invocation handler ", Proxy
    313                 .getInvocationHandler(p) == handler);
    314         boolean aborted = false;
    315         try {
    316             Proxy.getInvocationHandler("");
    317         } catch (IllegalArgumentException e) {
    318             aborted = true;
    319         }
    320         assertTrue("Did not detect non proxy object ", aborted);
    321     }
    322 
    323     //Regression Test for HARMONY-2355
    324     @TestTargetNew(
    325         level = TestLevel.PARTIAL,
    326         notes = "Regression test. Exceptions are not verified.",
    327         method = "newProxyInstance",
    328         args = {java.lang.ClassLoader.class, java.lang.Class[].class, java.lang.reflect.InvocationHandler.class}
    329     )
    330     public void test_newProxyInstance_withCompatibleReturnTypes() {
    331         Object o = Proxy
    332                 .newProxyInstance(this.getClass().getClassLoader(),
    333                         new Class[] { ITestReturnObject.class,
    334                                 ITestReturnString.class },
    335                         new TestProxyHandler(new TestProxyImpl()));
    336         assertNotNull(o);
    337     }
    338 
    339     @TestTargetNew(
    340         level = TestLevel.PARTIAL,
    341         notes = "IllegalArgumentException is verified.",
    342         method = "newProxyInstance",
    343         args = {java.lang.ClassLoader.class, java.lang.Class[].class, java.lang.reflect.InvocationHandler.class}
    344     )
    345     public void test_newProxyInstance_withNonCompatibleReturnTypes() {
    346         try {
    347             Proxy.newProxyInstance(this.getClass().getClassLoader(),
    348                     new Class[] { ITestReturnInteger.class,
    349                             ITestReturnString.class }, new TestProxyHandler(
    350                             new TestProxyImpl()));
    351             fail("should throw IllegalArgumentException");
    352         } catch (IllegalArgumentException e) {
    353             // expected
    354         }
    355 
    356     }
    357 
    358     public static interface ITestReturnObject {
    359         Object f();
    360     }
    361 
    362     public static interface ITestReturnString {
    363         String f();
    364     }
    365 
    366     public static interface ITestReturnInteger {
    367         Integer f();
    368     }
    369 
    370     public static class TestProxyImpl implements ITestReturnObject,
    371             ITestReturnString {
    372         public String f() {
    373             // do nothing
    374             return null;
    375         }
    376     }
    377 
    378     public static class TestProxyHandler implements InvocationHandler {
    379         private Object proxied;
    380 
    381         public TestProxyHandler(Object object) {
    382             proxied = object;
    383         }
    384 
    385         public Object invoke(Object object, Method method, Object[] args)
    386                 throws Throwable {
    387             // do nothing
    388             return method.invoke(proxied, args);
    389         }
    390 
    391     }
    392 
    393     protected void setUp() {
    394     }
    395 
    396     protected void tearDown() {
    397     }
    398 }
    399