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