1 /* 2 * Copyright (C) 2011 The Android Open Source Project 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 import java.lang.reflect.*; 17 18 public class ReturnsAndArgPassing { 19 20 public static final String testName = "ReturnsAndArgPassing"; 21 check(boolean x)22 static void check(boolean x) { 23 if (!x) { 24 throw new AssertionError(testName + " Check failed"); 25 } 26 } 27 28 interface MyInterface { voidFoo()29 void voidFoo(); voidBar()30 void voidBar(); booleanFoo()31 boolean booleanFoo(); booleanBar()32 boolean booleanBar(); byteFoo()33 byte byteFoo(); byteBar()34 byte byteBar(); charFoo()35 char charFoo(); charBar()36 char charBar(); shortFoo()37 short shortFoo(); shortBar()38 short shortBar(); intFoo()39 int intFoo(); intBar()40 int intBar(); longFoo()41 long longFoo(); longBar()42 long longBar(); floatFoo()43 float floatFoo(); floatBar()44 float floatBar(); doubleFoo()45 double doubleFoo(); doubleBar()46 double doubleBar(); selectArg(int select, int a, long b, float c, double d, Object x)47 Object selectArg(int select, int a, long b, float c, double d, Object x); 48 } 49 50 static int fooInvocations = 0; 51 static int barInvocations = 0; 52 53 static class MyInvocationHandler implements InvocationHandler { 54 boolean causeNpeOnReturn = false; 55 Class<?> returnType = null; invoke(Object proxy, Method method, Object[] args)56 public Object invoke(Object proxy, Method method, Object[] args) { 57 check(proxy instanceof Proxy); 58 check(method.getDeclaringClass() == MyInterface.class); 59 String name = method.getName(); 60 // Check for moving GC bugs in proxy stubs. 61 Runtime.getRuntime().gc(); 62 if (name.endsWith("Foo")) { 63 check(args == null); 64 fooInvocations++; 65 } else if (name.endsWith("Bar")) { 66 check(args == null); 67 barInvocations++; 68 } 69 if (causeNpeOnReturn) { 70 return null; 71 } else if (name.equals("voidFoo") || name.equals("voidBar")) { 72 return null; 73 } else if (name.equals("booleanFoo")) { 74 return true; 75 } else if (name.equals("booleanBar")) { 76 return false; 77 } else if (name.equals("selectArg")) { 78 check(args.length == 6); 79 int select = (Integer)args[0]; 80 return args[select]; 81 } else { 82 try { 83 if (name.endsWith("Foo")) { 84 return returnType.getField("MAX_VALUE").get(null); 85 } else { 86 check(name.endsWith("Bar")); 87 return returnType.getField("MIN_VALUE").get(null); 88 } 89 } catch (Exception e) { 90 throw new Error("return type = " + returnType, e); 91 } 92 } 93 } 94 } 95 testProxyReturns()96 static void testProxyReturns() { 97 System.out.println(testName + ".testProxyReturns RUNNING"); 98 MyInvocationHandler myHandler = new MyInvocationHandler(); 99 MyInterface proxyMyInterface = 100 (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(), 101 new Class<?>[] { MyInterface.class }, 102 myHandler); 103 check(fooInvocations == 0); 104 proxyMyInterface.voidFoo(); 105 check(fooInvocations == 1); 106 107 check(barInvocations == 0); 108 proxyMyInterface.voidBar(); 109 check(barInvocations == 1); 110 111 check(fooInvocations == 1); 112 myHandler.returnType = Boolean.class; 113 check(proxyMyInterface.booleanFoo() == true); 114 check(fooInvocations == 2); 115 116 check(barInvocations == 1); 117 check(proxyMyInterface.booleanBar() == false); 118 check(barInvocations == 2); 119 120 check(fooInvocations == 2); 121 myHandler.returnType = Byte.class; 122 check(proxyMyInterface.byteFoo() == Byte.MAX_VALUE); 123 check(fooInvocations == 3); 124 125 check(barInvocations == 2); 126 check(proxyMyInterface.byteBar() == Byte.MIN_VALUE); 127 check(barInvocations == 3); 128 129 check(fooInvocations == 3); 130 myHandler.returnType = Character.class; 131 check(proxyMyInterface.charFoo() == Character.MAX_VALUE); 132 check(fooInvocations == 4); 133 134 check(barInvocations == 3); 135 check(proxyMyInterface.charBar() == Character.MIN_VALUE); 136 check(barInvocations == 4); 137 138 check(fooInvocations == 4); 139 myHandler.returnType = Short.class; 140 check(proxyMyInterface.shortFoo() == Short.MAX_VALUE); 141 check(fooInvocations == 5); 142 143 check(barInvocations == 4); 144 check(proxyMyInterface.shortBar() == Short.MIN_VALUE); 145 check(barInvocations == 5); 146 147 check(fooInvocations == 5); 148 myHandler.returnType = Integer.class; 149 check(proxyMyInterface.intFoo() == Integer.MAX_VALUE); 150 check(fooInvocations == 6); 151 152 check(barInvocations == 5); 153 check(proxyMyInterface.intBar() == Integer.MIN_VALUE); 154 check(barInvocations == 6); 155 156 check(fooInvocations == 6); 157 myHandler.returnType = Long.class; 158 check(proxyMyInterface.longFoo() == Long.MAX_VALUE); 159 check(fooInvocations == 7); 160 161 check(barInvocations == 6); 162 check(proxyMyInterface.longBar() == Long.MIN_VALUE); 163 check(barInvocations == 7); 164 165 check(fooInvocations == 7); 166 myHandler.returnType = Float.class; 167 check(proxyMyInterface.floatFoo() == Float.MAX_VALUE); 168 check(fooInvocations == 8); 169 170 check(barInvocations == 7); 171 check(proxyMyInterface.floatBar() == Float.MIN_VALUE); 172 check(barInvocations == 8); 173 174 check(fooInvocations == 8); 175 myHandler.returnType = Double.class; 176 check(proxyMyInterface.doubleFoo() == Double.MAX_VALUE); 177 check(fooInvocations == 9); 178 179 check(barInvocations == 8); 180 check(proxyMyInterface.doubleBar() == Double.MIN_VALUE); 181 check(barInvocations == 9); 182 183 // Toggle flag to get return values to cause NPEs 184 myHandler.causeNpeOnReturn = true; 185 186 check(fooInvocations == 9); 187 try { 188 proxyMyInterface.booleanFoo(); 189 throw new AssertionError("Expected NPE"); 190 } catch (NullPointerException e) { 191 } 192 check(fooInvocations == 10); 193 194 check(barInvocations == 9); 195 try { 196 proxyMyInterface.booleanBar(); 197 throw new AssertionError("Expected NPE"); 198 } catch (NullPointerException e) { 199 } 200 check(barInvocations == 10); 201 202 check(fooInvocations == 10); 203 try { 204 proxyMyInterface.byteFoo(); 205 throw new AssertionError("Expected NPE"); 206 } catch (NullPointerException e) { 207 } 208 check(fooInvocations == 11); 209 210 check(barInvocations == 10); 211 try { 212 proxyMyInterface.byteBar(); 213 throw new AssertionError("Expected NPE"); 214 } catch (NullPointerException e) { 215 } 216 check(barInvocations == 11); 217 218 check(fooInvocations == 11); 219 try { 220 proxyMyInterface.charFoo(); 221 throw new AssertionError("Expected NPE"); 222 } catch (NullPointerException e) { 223 } 224 check(fooInvocations == 12); 225 226 check(barInvocations == 11); 227 try { 228 proxyMyInterface.charBar(); 229 throw new AssertionError("Expected NPE"); 230 } catch (NullPointerException e) { 231 } 232 check(barInvocations == 12); 233 234 check(fooInvocations == 12); 235 try { 236 proxyMyInterface.shortFoo(); 237 throw new AssertionError("Expected NPE"); 238 } catch (NullPointerException e) { 239 } 240 check(fooInvocations == 13); 241 242 check(barInvocations == 12); 243 try { 244 proxyMyInterface.shortBar(); 245 throw new AssertionError("Expected NPE"); 246 } catch (NullPointerException e) { 247 } 248 check(barInvocations == 13); 249 250 check(fooInvocations == 13); 251 try { 252 proxyMyInterface.intFoo(); 253 throw new AssertionError("Expected NPE"); 254 } catch (NullPointerException e) { 255 } 256 check(fooInvocations == 14); 257 258 check(barInvocations == 13); 259 try { 260 proxyMyInterface.intBar(); 261 throw new AssertionError("Expected NPE"); 262 } catch (NullPointerException e) { 263 } 264 check(barInvocations == 14); 265 266 check(fooInvocations == 14); 267 try { 268 proxyMyInterface.longFoo(); 269 throw new AssertionError("Expected NPE"); 270 } catch (NullPointerException e) { 271 } 272 check(fooInvocations == 15); 273 274 check(barInvocations == 14); 275 try { 276 proxyMyInterface.longBar(); 277 throw new AssertionError("Expected NPE"); 278 } catch (NullPointerException e) { 279 } 280 check(barInvocations == 15); 281 282 check(fooInvocations == 15); 283 try { 284 proxyMyInterface.floatFoo(); 285 throw new AssertionError("Expected NPE"); 286 } catch (NullPointerException e) { 287 } 288 check(fooInvocations == 16); 289 290 check(barInvocations == 15); 291 try { 292 proxyMyInterface.floatBar(); 293 throw new AssertionError("Expected NPE"); 294 } catch (NullPointerException e) { 295 } 296 check(barInvocations == 16); 297 298 check(fooInvocations == 16); 299 try { 300 proxyMyInterface.doubleFoo(); 301 throw new AssertionError("Expected NPE"); 302 } catch (NullPointerException e) { 303 } 304 check(fooInvocations == 17); 305 306 check(barInvocations == 16); 307 try { 308 proxyMyInterface.doubleBar(); 309 throw new AssertionError("Expected NPE"); 310 } catch (NullPointerException e) { 311 } 312 check(barInvocations == 17); 313 314 // Toggle flag to stop NPEs 315 myHandler.causeNpeOnReturn = false; 316 317 check(fooInvocations == 17); 318 myHandler.returnType = Double.class; // Double -> byte == fail 319 try { 320 proxyMyInterface.byteFoo(); 321 throw new AssertionError("Expected ClassCastException"); 322 } catch (ClassCastException e) { 323 } 324 check(fooInvocations == 18); 325 326 check(barInvocations == 17); 327 try { 328 proxyMyInterface.byteBar(); 329 throw new AssertionError("Expected NPE"); 330 } catch (ClassCastException e) { 331 } 332 check(barInvocations == 18); 333 334 check(fooInvocations == 18); 335 myHandler.returnType = Float.class; // Float -> byte == fail 336 try { 337 proxyMyInterface.byteFoo(); 338 throw new AssertionError("Expected ClassCastException"); 339 } catch (ClassCastException e) { 340 } 341 check(fooInvocations == 19); 342 343 check(barInvocations == 18); 344 try { 345 proxyMyInterface.byteBar(); 346 throw new AssertionError("Expected NPE"); 347 } catch (ClassCastException e) { 348 } 349 check(barInvocations == 19); 350 351 check(fooInvocations == 19); 352 myHandler.returnType = Long.class; // Long -> byte == fail 353 try { 354 proxyMyInterface.byteFoo(); 355 throw new AssertionError("Expected ClassCastException"); 356 } catch (ClassCastException e) { 357 } 358 check(fooInvocations == 20); 359 360 check(barInvocations == 19); 361 try { 362 proxyMyInterface.byteBar(); 363 throw new AssertionError("Expected NPE"); 364 } catch (ClassCastException e) { 365 } 366 check(barInvocations == 20); 367 368 check(fooInvocations == 20); 369 myHandler.returnType = Integer.class; // Int -> byte == fail 370 try { 371 proxyMyInterface.byteFoo(); 372 throw new AssertionError("Expected ClassCastException"); 373 } catch (ClassCastException e) { 374 } 375 check(fooInvocations == 21); 376 377 check(barInvocations == 20); 378 try { 379 proxyMyInterface.byteBar(); 380 throw new AssertionError("Expected NPE"); 381 } catch (ClassCastException e) { 382 } 383 check(barInvocations == 21); 384 385 check(fooInvocations == 21); 386 myHandler.returnType = Short.class; // Short -> byte == fail 387 try { 388 proxyMyInterface.byteFoo(); 389 throw new AssertionError("Expected ClassCastException"); 390 } catch (ClassCastException e) { 391 } 392 check(fooInvocations == 22); 393 394 check(barInvocations == 21); 395 try { 396 proxyMyInterface.byteBar(); 397 throw new AssertionError("Expected NPE"); 398 } catch (ClassCastException e) { 399 } 400 check(barInvocations == 22); 401 402 check(fooInvocations == 22); 403 myHandler.returnType = Character.class; // Char -> byte == fail 404 try { 405 proxyMyInterface.byteFoo(); 406 throw new AssertionError("Expected ClassCastException"); 407 } catch (ClassCastException e) { 408 } 409 check(fooInvocations == 23); 410 411 check(barInvocations == 22); 412 try { 413 proxyMyInterface.byteBar(); 414 throw new AssertionError("Expected NPE"); 415 } catch (ClassCastException e) { 416 } 417 check(barInvocations == 23); 418 419 check(fooInvocations == 23); 420 myHandler.returnType = Character.class; // Char -> short == fail 421 try { 422 proxyMyInterface.shortFoo(); 423 throw new AssertionError("Expected ClassCastException"); 424 } catch (ClassCastException e) { 425 } 426 check(fooInvocations == 24); 427 428 check(barInvocations == 23); 429 try { 430 proxyMyInterface.shortBar(); 431 throw new AssertionError("Expected NPE"); 432 } catch (ClassCastException e) { 433 } 434 check(barInvocations == 24); 435 436 System.out.println(testName + ".testProxyReturns PASSED"); 437 } 438 testProxyArgPassing()439 static void testProxyArgPassing() { 440 System.out.println(testName + ".testProxyArgPassing RUNNING"); 441 MyInvocationHandler myHandler = new MyInvocationHandler(); 442 MyInterface proxyMyInterface = 443 (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(), 444 new Class<?>[] { MyInterface.class }, 445 myHandler); 446 447 check((Integer)proxyMyInterface.selectArg(0, Integer.MAX_VALUE, Long.MAX_VALUE, 448 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == 0); 449 check((Integer)proxyMyInterface.selectArg(1, Integer.MAX_VALUE, Long.MAX_VALUE, 450 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Integer.MAX_VALUE); 451 check((Long)proxyMyInterface.selectArg(2, Integer.MAX_VALUE, Long.MAX_VALUE, 452 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Long.MAX_VALUE); 453 check((Float)proxyMyInterface.selectArg(3, Integer.MAX_VALUE, Long.MAX_VALUE, 454 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Float.MAX_VALUE); 455 check((Double)proxyMyInterface.selectArg(4, Integer.MAX_VALUE, Long.MAX_VALUE, 456 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Double.MAX_VALUE); 457 check(proxyMyInterface.selectArg(5, Integer.MAX_VALUE, Long.MAX_VALUE, 458 Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Object.class); 459 460 System.out.println(testName + ".testProxyArgPassing PASSED"); 461 } 462 main(String args[])463 public static void main(String args[]) { 464 testProxyReturns(); 465 testProxyArgPassing(); 466 } 467 } 468