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