VarargsTest.java revision 10093:056cd206a147
1218893Sdim/* 2218893Sdim * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3218893Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4218893Sdim * 5218893Sdim * This code is free software; you can redistribute it and/or modify it 6234353Sdim * under the terms of the GNU General Public License version 2 only, as 7218893Sdim * published by the Free Software Foundation. 8218893Sdim * 9218893Sdim * This code is distributed in the hope that it will be useful, but WITHOUT 10218893Sdim * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11218893Sdim * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12226633Sdim * version 2 for more details (a copy is included in the LICENSE file that 13221345Sdim * accompanied this code). 14218893Sdim * 15218893Sdim * You should have received a copy of the GNU General Public License version 16226633Sdim * 2 along with this work; if not, write to the Free Software Foundation, 17218893Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18218893Sdim * 19218893Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20221345Sdim * or visit www.oracle.com if you need additional information or have any 21226633Sdim * questions. 22226633Sdim */ 23226633Sdim 24226633Sdim/** 25234353Sdim * @test 26218893Sdim * @bug 4870984 27218893Sdim * @summary JPDA: Add support for RFE 4856541 - varargs 28218893Sdim * 29218893Sdim * @author jjh 30218893Sdim * 31226633Sdim * @run build TestScaffold VMConnection TargetListener TargetAdapter 32218893Sdim * @run compile -g VarargsTest.java 33218893Sdim * @run driver VarargsTest 34218893Sdim */ 35218893Sdimimport com.sun.jdi.*; 36218893Sdimimport com.sun.jdi.event.*; 37218893Sdimimport com.sun.jdi.request.*; 38218893Sdim 39234353Sdimimport java.util.*; 40218893Sdim 41218893Sdim /********** target program **********/ 42218893Sdim 43218893Sdimclass VarargsTarg { 44218893Sdim 45218893Sdim // These are args that will get passed 46218893Sdim static String[] strArray = new String[] {"a", "b"}; 47218893Sdim static int[] intArray = new int[] {1, 2}; 48218893Sdim 49218893Sdim // We will pass these to a varargs instance method 50 static VarargsTarg vt1 = new VarargsTarg("vt1", ""); 51 static VarargsTarg vt2 = new VarargsTarg("vt2", ""); 52 53 String iname; 54 55 VarargsTarg(String ... name) { 56 iname = ""; 57 for (int ii = 0; ii < name.length; ii++) { 58 iname += name[ii]; 59 } 60 } 61 62 public static void main(String[] args){ 63 System.out.println("Howdy!"); 64 /* 65 * This isn't really part of the test, it just shows 66 * the kinds of calls the debugger test will do and lets 67 * you verify how javac handles these calls. 68 */ 69 System.out.println("debuggee: " + varString()); 70 System.out.println("debuggee: " + varString(null)); 71 System.out.println("debuggee: " + varString("a")); 72 System.out.println("debuggee: " + varString("b", "c")); 73 System.out.println("debuggee: " + fixedString(null)); 74 System.out.println("debuggee: " + vt1.varStringInstance(vt1, vt2)); 75 System.out.println("debuggge: " + varInt(1, 2, 3)); 76 System.out.println("debuggee: " + varInteger( new Integer(89))); 77 78 // Should be autoboxed: javac converts the ints to Integers 79 // Needs a new method in java.lang.Integer which is only 80 // in the generics workspace. 81 System.out.println("debugggee: " + varInteger(3, 5, 6)); 82 83 System.out.println("Goodbye from VarargsTarg!"); 84 bkpt(); 85 } 86 static void bkpt() { 87 } 88 89 /* 90 * Define the methods to be called from the debugger 91 */ 92 static String fixedInt(int p1) { 93 return "" + p1; 94 } 95 96 static String fixedInteger(Integer p1) { 97 return "" + p1; 98 } 99 100 static String varInt(int... ss) { 101 String retVal = ""; 102 for (int ii = 0; ii < ss.length; ii++) { 103 retVal += ss[ii]; 104 } 105 return retVal; 106 } 107 108 static String varInteger(Integer... ss) { 109 String retVal = ""; 110 for (int ii = 0; ii < ss.length; ii++) { 111 retVal += ss[ii]; 112 } 113 return retVal; 114 } 115 116 static String varString(String... ss) { 117 if (ss == null) { 118 return "-null-"; 119 } 120 121 String retVal = ""; 122 for (int ii = 0; ii < ss.length; ii++) { 123 retVal += ss[ii]; 124 } 125 return retVal; 126 } 127 128 static String varString2(int p1, String... ss) { 129 return p1 + varString(ss); 130 } 131 132 static String fixedString(String ss) { 133 return "-fixed-"; 134 } 135 136 String varStringInstance(VarargsTarg... args) { 137 if (args == null) { 138 return "-null-"; 139 } 140 //System.out.println("debugee: ss length = " + ss.length); 141 String retVal = iname + ": "; 142 for (int ii = 0; ii < args.length; ii++) { 143 retVal += args[ii].iname; 144 } 145 return retVal; 146 } 147 148} 149 150 /********** test program **********/ 151 152public class VarargsTest extends TestScaffold { 153 ClassType targetClass; 154 ThreadReference mainThread; 155 156 VarargsTest (String args[]) { 157 super(args); 158 } 159 160 public static void main(String[] args) throws Exception { 161 new VarargsTest(args).startTests(); 162 } 163 164 void fail(String reason) { 165 failure(reason); 166 } 167 168 /* 169 * Call a method in the debuggee and verify the return value. 170 */ 171 void doInvoke(Object ct, Method mm, List args, Object expected) { 172 StringReference returnValue = null; 173 try { 174 returnValue = doInvokeNoVerify(ct, mm, args); 175 } catch (Exception ee) { 176 fail("failure: invokeMethod got exception : " + ee); 177 ee.printStackTrace(); 178 return; 179 } 180 if (!returnValue.value().equals(expected)) { 181 fail("failure: expected \"" + expected + "\", got \"" + 182 returnValue.value() + "\""); 183 } 184 } 185 186 /* 187 * Call a method in the debuggee. 188 */ 189 StringReference doInvokeNoVerify(Object ct, Method mm, List args) 190 throws Exception { 191 StringReference returnValue = null; 192 if (ct instanceof ClassType) { 193 returnValue = (StringReference)((ClassType)ct). 194 invokeMethod(mainThread, mm, args, 0); 195 } else { 196 returnValue = (StringReference)((ObjectReference)ct). 197 invokeMethod(mainThread, mm, args, 0); 198 } 199 return returnValue; 200 } 201 202 /********** test core **********/ 203 204 protected void runTests() throws Exception { 205 /* 206 * Get to the top of main() 207 * to determine targetClass and mainThread 208 */ 209 BreakpointEvent bpe = startToMain("VarargsTarg"); 210 targetClass = (ClassType)bpe.location().declaringType(); 211 mainThread = bpe.thread(); 212 213 /* 214 * Run past the calls the debuggee makes 215 * just to see what they do. 216 */ 217 bpe = resumeTo("VarargsTarg", "bkpt", "()V"); 218 219 /* 220 * Find Method objects for varString and varString2 221 * Both are tested just to show that the code works 222 * if there is just one param or if there is more than one. 223 */ 224 ReferenceType rt = findReferenceType("VarargsTarg"); 225 226 List mList; 227 228 /* 229 * The test consists of calling the varargs static and instance methods 230 * (and constructor) passing primitives, Strings, and Objects, and also 231 * passing arrays of the above instead of individual args. 232 * The same code is used in the underlying JDI implementations 233 * for calling instance methods, static methods, and constructors 234 * so this test doesn't have to try all possible argument configurations 235 * with each type of method. 236 */ 237 238 mList = rt.methodsByName("varString"); 239 Method varString = (Method)mList.get(0); 240 241 mList = rt.methodsByName("varString2"); 242 Method varString2 = (Method)mList.get(0); 243 244 if (!varString.isVarArgs()) { 245 fail("failure: varString is not flagged as being var args"); 246 } 247 if (!varString2.isVarArgs()) { 248 fail("failure: varString2 is not flagged as being var args"); 249 } 250 251 /* 252 * Setup arg lists for both varString and varString2 that 253 * have null in the varargs position. 254 */ 255 256 { 257 // call varString() 258 ArrayList nullArg1 = new ArrayList(0); 259 doInvoke(targetClass, varString, nullArg1, ""); 260 } 261 { 262 // call varString(null) 263 ArrayList nullArg1 = new ArrayList(1); 264 nullArg1.add(null); 265 doInvoke(targetClass, varString, nullArg1, "-null-"); 266 } 267 { 268 // call varString(9) 269 ArrayList nullArg2 = new ArrayList(1); 270 nullArg2.add(vm().mirrorOf(9)); 271 doInvoke(targetClass, varString2, nullArg2, "9"); 272 } 273 { 274 // call varString(9, null) 275 ArrayList nullArg2 = new ArrayList(2); 276 nullArg2.add(vm().mirrorOf(9)); 277 nullArg2.add(null); 278 doInvoke(targetClass, varString2, nullArg2, "9-null-"); 279 } 280 { 281 ArrayList args1 = new ArrayList(4); 282 args1.add(vm().mirrorOf("1")); 283 284 // call varString("1") 285 doInvoke(targetClass, varString, args1, "1"); 286 287 // call varString("1", "2") 288 args1.add(vm().mirrorOf("2")); 289 args1.add(vm().mirrorOf("3")); 290 args1.add(vm().mirrorOf("4")); 291 doInvoke(targetClass, varString, args1, "1234"); 292 } 293 { 294 ArrayList args2 = new ArrayList(2); 295 args2.add(vm().mirrorOf(9)); 296 args2.add(vm().mirrorOf("1")); 297 298 // call varString2(9, "1"); 299 doInvoke(targetClass, varString2, args2, "91"); 300 301 // call varString2(9, "1", "2"); 302 args2.add(vm().mirrorOf("2")); 303 doInvoke(targetClass, varString2, args2, "912"); 304 } 305 306 { 307 /* 308 * Passing an array of Strings should work too. 309 */ 310 Field ff = targetClass.fieldByName("strArray"); 311 Value vv1 = targetClass.getValue(ff); 312 313 // call varString(new String[] {"a", "b"}) 314 ArrayList argsArray = new ArrayList(1); 315 argsArray.add(vv1); 316 doInvoke(targetClass, varString, argsArray, "ab"); 317 318 /* 319 * But passing an array of Strings and another String 320 * should fail 321 */ 322 argsArray.add(vm().mirrorOf("x")); 323 boolean isOk = false; 324 try { 325 // call varString(new String[] {"a", "b"}, "x") 326 doInvokeNoVerify(targetClass, varString, argsArray); 327 } catch (Exception ee) { 328 /* 329 * Since the number of args passed is > than 330 * the number of params, JDI assumes they are var args 331 * and tries to put the array containing the "a" and 332 * "be" elements into a the first element of an array 333 * of Strings. This fails because you can't store 334 * an array into a String 335 */ 336 isOk = true; 337 //ee.printStackTrace(); 338 } 339 if (!isOk) { 340 fail("failure: an array and a String didn't cause an exception"); 341 } 342 } 343 344 { 345 /* 346 * Test calling instance method instead of static method, 347 * and passing non-String objects 348 */ 349 Field vtField = targetClass.fieldByName("vt1"); 350 Value vv1 = targetClass.getValue(vtField); 351 352 vtField = targetClass.fieldByName("vt2"); 353 Value vv2 = targetClass.getValue(vtField); 354 355 /* Create a new instance by calling the varargs 356 * ctor. 357 * call new VarargsTarg("vt3", "xx"); 358 */ 359 Value vv3; 360 { 361 mList = rt.methodsByName("<init>"); 362 Method ctor = (Method)mList.get(0); 363 if (!ctor.isVarArgs()) { 364 fail("failure: Constructor is not varargs"); 365 } 366 ArrayList argsArray = new ArrayList(2); 367 argsArray.add(vm().mirrorOf("vt3")); 368 argsArray.add(vm().mirrorOf("xx")); 369 vv3 = targetClass.newInstance(mainThread, ctor, argsArray, 0); 370 } 371 // call vt1.varStringInstance(vv1, vv2, vv3) 372 mList = rt.methodsByName("varStringInstance"); 373 Method varStringInstance = (Method)mList.get(0); 374 375 ArrayList argsArray = new ArrayList(3); 376 argsArray.add(vv1); 377 argsArray.add(vv2); 378 argsArray.add(vv3); 379 doInvoke(vv1, varStringInstance, argsArray, "vt1: vt1vt2vt3xx"); 380 } 381 { 382 /* 383 * tests with primitive types 384 */ 385 List mlist; 386 Method mm; 387 ArrayList ll = new ArrayList(2); 388 389 // call fixedInt(21) 390 mlist = rt.methodsByName("fixedInt"); 391 mm = (Method)mlist.get(0); 392 ll.add(vm().mirrorOf(21)); 393 doInvoke(targetClass, mm, ll, "21"); 394 395 // autoboxing is not implemented in JDI. 396 // call fixedInteger(21) 397 //mlist = rt.methodsByName("fixedInteger"); 398 //mm = (Method)mlist.get(0); 399 //doInvoke(targetClass, mm, ll, "21"); 400 401 mlist = rt.methodsByName("varInt"); 402 mm = (Method)mlist.get(0); 403 404 // call varInt( new int[] {1, 2}); 405 Field ff = targetClass.fieldByName("intArray"); 406 Value vv1 = targetClass.getValue(ff); 407 ll.set(0, vv1); 408 doInvoke(targetClass, mm, ll, "12"); 409 410 // call varInt(21, 22) 411 ll.set(0, vm().mirrorOf(21)); 412 ll.add(vm().mirrorOf(22)); 413 doInvoke(targetClass, mm, ll, "2122"); 414 415 mlist = rt.methodsByName("varInteger"); 416 mm = (Method)mlist.get(0); 417 418 // call varInteger(1, 2) 419 // autoboxing is not implemented. 420 //doInvoke(targetClass, mm, ll, "2122"); 421 } 422 423 /* 424 * We don't really need this for the test, but 425 * but without it, we sometimes hit 4728096. 426 */ 427 listenUntilVMDisconnect(); 428 /* 429 * deal with results of test 430 * if anything has called failure("foo") testFailed will be true 431 */ 432 if (!testFailed) { 433 println("VarargsTest: passed"); 434 } else { 435 throw new Exception("VarargsTest: failed"); 436 } 437 } 438} 439