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