1 /* 2 * Copyright (c) 2001, 2018, 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 package nsk.jdwp.ClassType.InvokeMethod; 25 26 import java.io.*; 27 28 import nsk.share.*; 29 import nsk.share.jpda.*; 30 import nsk.share.jdwp.*; 31 32 /** 33 * Test for JDWP command: ClassType.InvokeMethod. 34 * 35 * See invokemeth001.README for description of test execution. 36 * 37 * This class represents debugger part of the test. 38 * Test is executed by invoking method runIt(). 39 * JDWP command is tested in the method testCommand(). 40 * 41 * @see #runIt() 42 * @see #testCommand() 43 */ 44 public class invokemeth001 { 45 46 // exit status constants 47 static final int JCK_STATUS_BASE = 95; 48 static final int PASSED = 0; 49 static final int FAILED = 2; 50 51 // package and classes names 52 static final String PACKAGE_NAME = "nsk.jdwp.ClassType.InvokeMethod"; 53 static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "invokemeth001"; 54 static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; 55 56 // tested JDWP command 57 static final String JDWP_COMMAND_NAME = "ClassType.InvokeMethod"; 58 static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.InvokeMethod; 59 60 // tested class name and signature 61 static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; 62 static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; 63 64 // field and method names 65 static final String RESULT_FIELD_NAME = "result"; 66 static final String TESTED_METHOD_NAME = "testedMethod"; 67 static final String BREAKPOINT_METHOD_NAME = "run"; 68 static final int BREAKPOINT_LINE_NUMBER = invokemeth001a.BREAKPOINT_LINE_NUMBER; 69 70 // data for invoked method 71 static final int ARGUMENTS_COUNT = 1; 72 static final int INITIAL_VALUE = invokemeth001a.INITIAL_VALUE; 73 static final int ARGUMENT_VALUE = invokemeth001a.FINAL_VALUE; 74 static final int RETURN_VALUE = INITIAL_VALUE; 75 static final int INVOKE_OPTIONS = 0; 76 77 // usual scaffold objects 78 ArgumentHandler argumentHandler = null; 79 Log log = null; 80 Binder binder = null; 81 Debugee debugee = null; 82 Transport transport = null; 83 IOPipe pipe = null; 84 int waitTime = 0; // minutes 85 long timeout = 0; // milliseconds 86 boolean dead = false; 87 boolean success = true; 88 89 // data obtained from debuggee 90 long classID = 0; 91 long threadID = 0; 92 long methodID = 0; 93 94 // ------------------------------------------------------------------- 95 96 /** 97 * Start test from command line. 98 */ main(String argv[])99 public static void main (String argv[]) { 100 System.exit(run(argv,System.out) + JCK_STATUS_BASE); 101 } 102 103 /** 104 * Start JCK-compilant test. 105 */ run(String argv[], PrintStream out)106 public static int run(String argv[], PrintStream out) { 107 return new invokemeth001().runIt(argv, out); 108 } 109 110 // ------------------------------------------------------------------- 111 112 /** 113 * Perform test execution. 114 */ runIt(String argv[], PrintStream out)115 public int runIt(String argv[], PrintStream out) { 116 117 // make log for debugger messages 118 argumentHandler = new ArgumentHandler(argv); 119 log = new Log(out, argumentHandler); 120 waitTime = argumentHandler.getWaitTime(); // minutes 121 timeout = waitTime * 60 * 1000; // milliseconds 122 123 // execute test and display results 124 try { 125 log.display("\n>>> Starting debugee \n"); 126 127 // launch debuggee 128 binder = new Binder(argumentHandler, log); 129 log.display("Launching debugee VM"); 130 debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); 131 transport = debugee.getTransport(); 132 log.display(" ... debuggee launched"); 133 134 // set timeout for debuggee responces 135 log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); 136 transport.setReadTimeout(timeout); 137 log.display(" ... timeout set"); 138 139 // wait for VM_INIT event 140 log.display("Waiting for VM_INIT event"); 141 debugee.waitForVMInit(); 142 log.display(" ... VM_INIT event received"); 143 144 // query debugee for VM-dependent ID sizes 145 log.display("Querying for IDSizes"); 146 debugee.queryForIDSizes(); 147 log.display(" ... size of VM-dependent types adjusted"); 148 149 // prepare debuggee for testing and obtain required data 150 log.display("\n>>> Getting prepared for testing \n"); 151 prepareForTest(); 152 153 // test JDWP command 154 log.display("\n>> Testing JDWP command \n"); 155 testCommand(); 156 157 // check command results 158 if (success) { 159 log.display("\n>>> Checking result of tested command \n"); 160 checkResult(); 161 } 162 163 // finish debuggee 164 log.display("\n>> Finishing debuggee \n"); 165 166 // resume debuggee after testing command 167 log.display("Resuming debuggee"); 168 debugee.resume(); 169 log.display(" ... debuggee resumed"); 170 171 // wait for VM_DEATH event 172 log.display("Waiting for VM_DEATH event"); 173 debugee.waitForVMDeath(); 174 log.display(" ... VM_DEATH event received"); 175 dead = true; 176 177 } catch (Failure e) { 178 log.complain("TEST FAILED: " + e.getMessage()); 179 success = false; 180 } catch (Exception e) { 181 e.printStackTrace(out); 182 log.complain("Caught unexpected exception while running the test:\n\t" + e); 183 success = false; 184 } finally { 185 log.display("\n>>> Finishing test \n"); 186 187 // disconnect debugee and wait for its exit 188 if (debugee != null) { 189 quitDebugee(); 190 } 191 } 192 193 // check result 194 if (!success) { 195 log.complain("TEST FAILED"); 196 return FAILED; 197 } 198 out.println("TEST PASSED"); 199 return PASSED; 200 } 201 202 /** 203 * Get debuggee prepared for testing and obtain required data. 204 */ prepareForTest()205 void prepareForTest() { 206 // wait for tested class loaded on debuggee startup and obtain its classID 207 log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); 208 classID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); 209 log.display(" ... class loaded with classID: " + classID); 210 log.display(""); 211 212 // query debuggee for tested methodID 213 log.display("Getting tested methodID by name: " + TESTED_METHOD_NAME); 214 methodID = debugee.getMethodID(classID, TESTED_METHOD_NAME, true); 215 log.display(" ... got methodID: " + methodID); 216 log.display(""); 217 218 // set breakpoint and wait for debugee reached it 219 log.display("Waiting for breakpoint reached at: " 220 + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); 221 threadID = debugee.waitForBreakpointReached(classID, 222 BREAKPOINT_METHOD_NAME, 223 BREAKPOINT_LINE_NUMBER, 224 JDWP.SuspendPolicy.ALL); 225 log.display(" ... breakpoint reached with threadID: " + threadID); 226 log.display("Tested thread is suspended by breakpoint event"); 227 } 228 229 /** 230 * Perform testing JDWP command. 231 */ testCommand()232 void testCommand() { 233 // create command packet and fill requred out data 234 log.display("Create command packet:"); 235 log.display("Command: " + JDWP_COMMAND_NAME); 236 CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); 237 log.display(" classID: " + classID); 238 command.addReferenceTypeID(classID); 239 log.display(" threadID: " + threadID); 240 command.addObjectID(threadID); 241 log.display(" methodID: " + methodID); 242 command.addMethodID(methodID); 243 log.display(" arguments: " + ARGUMENTS_COUNT); 244 command.addInt(ARGUMENTS_COUNT); 245 for (int i = 0; i < ARGUMENTS_COUNT; i++) { 246 JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); 247 log.display(" arg: " + value); 248 command.addValue(value); 249 } 250 log.display(" options: " + INVOKE_OPTIONS); 251 command.addInt(INVOKE_OPTIONS); 252 command.setLength(); 253 254 // send command packet to debugee 255 try { 256 log.display("Sending command packet:\n" + command); 257 transport.write(command); 258 } catch (IOException e) { 259 log.complain("Unable to send command packet:\n\t" + e); 260 success = false; 261 return; 262 } 263 264 ReplyPacket reply = new ReplyPacket(); 265 266 // receive reply packet from debugee 267 try { 268 log.display("Waiting for reply packet"); 269 transport.read(reply); 270 log.display(" ... reply packet received:\n" + reply); 271 } catch (IOException e) { 272 log.complain("Unable to read reply packet for tested command:\n\t" + e); 273 success = false; 274 return; 275 } 276 277 // check reply packet header 278 try{ 279 log.display("Checking header of reply packet"); 280 reply.checkHeader(command.getPacketID()); 281 log.display(" ... packet header is correct"); 282 } catch (BoundException e) { 283 log.complain("Wrong header of reply packet for tested command:\n\t" 284 + e.getMessage()); 285 success = false; 286 return; 287 } 288 289 // start parsing reply packet data 290 log.display("Parsing reply packet data:"); 291 reply.resetPosition(); 292 293 // extract return value 294 JDWP.Value returnValue = null; 295 try { 296 returnValue = reply.getValue(); 297 log.display(" returnValue: " + returnValue); 298 } catch (BoundException e) { 299 log.complain("Unable to extract returnValues from reply packet:\n\t" 300 + e.getMessage()); 301 success = false; 302 return; 303 } 304 305 // extract exception tag 306 JDWP.Value exception = null; 307 try { 308 exception = reply.getValue(); 309 log.display(" exception: " + exception); 310 } catch (BoundException e) { 311 log.complain("Unable to extract exception from reply packet:\n\t" 312 + e.getMessage()); 313 success = false; 314 return; 315 } 316 317 // check for extra data in reply packet 318 if (!reply.isParsed()) { 319 log.complain("Extra trailing bytes found in reply packet at: " 320 + reply.offsetString()); 321 success = false; 322 } 323 324 log.display(" ... packed data parsed"); 325 326 // check that return value is an integer 327 if (returnValue.getTag() != JDWP.Tag.INT) { 328 log.complain("Unexpected tag of returnValue returned: " + returnValue.getTag() 329 + " (expected: " + JDWP.Tag.INT + ")"); 330 success = false; 331 } 332 333 // check that return value is as expected 334 int intValue = ((Integer)returnValue.getValue()).intValue(); 335 if (intValue != RETURN_VALUE) { 336 log.complain("Unexpected value of returnValue returned: " + intValue 337 + " (expected: " + RETURN_VALUE + ")"); 338 success = false; 339 } 340 341 // check that exception value is an object 342 if (exception.getTag() != JDWP.Tag.OBJECT) { 343 log.complain("Unexpected tag of exception returned: " + exception.getTag() 344 + " (expected: " + JDWP.Tag.OBJECT + ")"); 345 success = false; 346 } 347 348 // check that exception object is null 349 long exceptionID = ((Long)exception.getValue()).longValue(); 350 if (exceptionID != 0) { 351 log.complain("Non-null exception object returned: " + exceptionID 352 + " (expected: " + 0 + ")"); 353 success = false; 354 } 355 } 356 357 /** 358 * Check result of the tested JDWP command. 359 */ checkResult()360 void checkResult() { 361 // query debuggee for result value from a static field 362 log.display("Getting result value from static field: " + RESULT_FIELD_NAME); 363 JDWP.Value value = debugee.getStaticFieldValue(classID, RESULT_FIELD_NAME, JDWP.Tag.INT); 364 int result = ((Integer)value.getValue()).intValue(); 365 log.display(" ... got result: " + result); 366 367 // check if the result value is changed as expected 368 if (result != ARGUMENT_VALUE) { 369 log.complain("Method has not been really invoked: \n\t" 370 + "variable not changed by the method: " + result 371 + " (expected: " + ARGUMENT_VALUE + ")"); 372 success = false; 373 } else { 374 log.display("Method has been really invoked: \n\t" 375 + " variable changed by the method: " + result 376 + " (expected: " + ARGUMENT_VALUE + ")"); 377 } 378 } 379 380 /** 381 * Disconnect debuggee and wait for it exited. 382 */ quitDebugee()383 void quitDebugee() { 384 if (debugee == null) 385 return; 386 387 // disconnect debugee 388 if (!dead) { 389 try { 390 log.display("Disconnecting debuggee"); 391 debugee.dispose(); 392 log.display(" ... debuggee disconnected"); 393 } catch (Failure e) { 394 log.display("Failed to finally disconnect debuggee:\n\t" 395 + e.getMessage()); 396 } 397 } 398 399 // wait for debugee exited 400 log.display("Waiting for debuggee exit"); 401 int code = debugee.waitFor(); 402 log.display(" ... debuggee exited with exit code: " + code); 403 404 // analize debugee exit status code 405 if (code != JCK_STATUS_BASE + PASSED) { 406 log.complain("Debuggee FAILED with exit code: " + code); 407 success = false; 408 } 409 } 410 411 } 412