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.SetValues; 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.SetValues. 34 * 35 * See setvalues001.README for description of test execution. 36 * 37 * Test is executed by invoking method runIt(). 38 * JDWP command is tested in method testCommand(). 39 * 40 * @see #runIt() 41 * @see #testCommand() 42 */ 43 public class setvalues001 { 44 45 // exit status constants 46 static final int JCK_STATUS_BASE = 95; 47 static final int PASSED = 0; 48 static final int FAILED = 2; 49 50 // communication signals constants 51 static final String READY = "ready"; 52 static final String RUN = "run"; 53 static final String DONE = "done"; 54 static final String ERROR = "error"; 55 static final String QUIT = "quit"; 56 57 // package and classes names constants 58 static final String PACKAGE_NAME = "nsk.jdwp.ClassType.SetValues"; 59 static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "setvalues001"; 60 static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; 61 62 // tested JDWP command constants 63 static final String JDWP_COMMAND_NAME = "ClassType.SetValues"; 64 static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.SetValues; 65 66 // tested class name and signature constants 67 static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; 68 static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; 69 70 // target values class name and signature constants 71 static final String TARGET_VALUES_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TargetValuesClass"; 72 static final String TARGET_VALUES_CLASS_SIGNATURE = "L" + TARGET_VALUES_CLASS_NAME.replace('.', '/') + ";"; 73 74 // usual scaffold objects 75 ArgumentHandler argumentHandler = null; 76 Log log = null; 77 Binder binder = null; 78 Debugee debugee = null; 79 Transport transport = null; 80 IOPipe pipe = null; 81 82 // test passed or not 83 boolean success = true; 84 85 // ------------------------------------------------------------------- 86 87 /** 88 * Start test from command line. 89 */ main(String argv[])90 public static void main (String argv[]) { 91 System.exit(run(argv,System.out) + JCK_STATUS_BASE); 92 } 93 94 /** 95 * Start JCK-compilant test. 96 */ run(String argv[], PrintStream out)97 public static int run(String argv[], PrintStream out) { 98 return new setvalues001().runIt(argv, out); 99 } 100 101 // ------------------------------------------------------------------- 102 103 /** 104 * Perform test execution. 105 */ runIt(String argv[], PrintStream out)106 public int runIt(String argv[], PrintStream out) { 107 108 // make log for debugger messages 109 argumentHandler = new ArgumentHandler(argv); 110 log = new Log(out, argumentHandler); 111 112 // execute test and display results 113 try { 114 log.display("\n>>> Preparing debugee for testing \n"); 115 116 // launch debugee 117 binder = new Binder(argumentHandler, log); 118 log.display("Launching debugee"); 119 debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); 120 transport = debugee.getTransport(); 121 pipe = debugee.createIOPipe(); 122 123 // make debuggee ready for testing 124 prepareDebugee(); 125 126 // work with prepared debugee 127 try { 128 log.display("\n>>> Obtaining requred data from debugee \n"); 129 130 // query debugee for classID for the class with target values 131 log.display("Getting classID for class with target values by signature:\n" 132 + " " + TARGET_VALUES_CLASS_SIGNATURE); 133 long targetValuesClassID = 134 debugee.getReferenceTypeID(TARGET_VALUES_CLASS_SIGNATURE); 135 log.display(" got classID: " + targetValuesClassID); 136 137 // query debugee for fieldIDs of the class static fields 138 log.display("Getting fieldIDs for static fields of the class"); 139 long targetValuesFieldIDs[] = queryClassFieldIDs(targetValuesClassID); 140 log.display(" got fields: " + targetValuesFieldIDs.length); 141 int count = targetValuesFieldIDs.length; 142 143 // query debugee for values of the fields 144 log.display("Getting values of the static fields"); 145 JDWP.Value targetValues[] = 146 queryClassFieldValues(targetValuesClassID, targetValuesFieldIDs); 147 log.display(" got values: " + targetValues.length); 148 if (targetValues.length != count) { 149 throw new Failure("Unexpected number of static fields values received: " 150 + targetValues.length + "(expected: " + count + ")"); 151 } 152 153 // query debugee for classID of the tested class 154 log.display("Getting tested classID by signature:\n" 155 + " " + TESTED_CLASS_SIGNATURE); 156 long testedClassID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); 157 log.display(" got classID: " + testedClassID); 158 159 // query debugee for fieldIDs of tested class static fields 160 log.display("Getting fieldIDs for static fields of the tested class"); 161 long testedFieldIDs[] = queryClassFieldIDs(testedClassID); 162 log.display(" got fields: " + testedFieldIDs.length); 163 if (testedFieldIDs.length != count) { 164 throw new Failure("Unexpected number of static fields of tested class received: " 165 + testedFieldIDs.length + "(expected: " + count + ")"); 166 } 167 168 // perform testing JDWP command 169 log.display("\n>>> Testing JDWP command \n"); 170 testCommand(testedClassID, testedFieldIDs, targetValues); 171 172 // check confirmation from debuggee that values have been set properly 173 log.display("\n>>> Checking that the values have been set properly \n"); 174 checkValuesChanged(); 175 176 } finally { 177 // quit debugee 178 log.display("\n>>> Finishing test \n"); 179 quitDebugee(); 180 } 181 182 } catch (Failure e) { 183 log.complain("TEST FAILED: " + e.getMessage()); 184 e.printStackTrace(out); 185 success = false; 186 } catch (Exception e) { 187 log.complain("Caught unexpected exception:\n" + e); 188 e.printStackTrace(out); 189 success = false; 190 } 191 192 if (!success) { 193 log.complain("TEST FAILED"); 194 return FAILED; 195 } 196 197 out.println("TEST PASSED"); 198 return PASSED; 199 200 } 201 202 /** 203 * Prepare debugee for testing and waiting for ready signal. 204 */ prepareDebugee()205 void prepareDebugee() { 206 // wait for VM_INIT event from debugee 207 log.display("Waiting for VM_INIT event"); 208 debugee.waitForVMInit(); 209 210 // query debugee for VM-dependent ID sizes 211 log.display("Querying for IDSizes"); 212 debugee.queryForIDSizes(); 213 214 // resume initially suspended debugee 215 log.display("Resuming debugee VM"); 216 debugee.resume(); 217 218 // wait for READY signal from debugee 219 log.display("Waiting for signal from debugee: " + READY); 220 String signal = pipe.readln(); 221 log.display("Received signal from debugee: " + signal); 222 if (! signal.equals(READY)) { 223 throw new TestBug("Unexpected signal received form debugee: " + signal 224 + " (expected: " + READY + ")"); 225 } 226 } 227 228 /** 229 * Sending debugee signal to quit and waiting for it exits. 230 */ quitDebugee()231 void quitDebugee() { 232 // send debugee signal to quit 233 log.display("Sending signal to debugee: " + QUIT); 234 pipe.println(QUIT); 235 236 // wait for debugee exits 237 log.display("Waiting for debugee exits"); 238 int code = debugee.waitFor(); 239 240 // analize debugee exit status code 241 if (code == JCK_STATUS_BASE + PASSED) { 242 log.display("Debugee PASSED with exit code: " + code); 243 } else { 244 log.complain("Debugee FAILED with exit code: " + code); 245 success = false; 246 } 247 } 248 249 /** 250 * Query debugee for fieldID's of the class static fields. 251 */ queryClassFieldIDs(long classID)252 long[] queryClassFieldIDs(long classID) { 253 // compose ReferenceType.Fields command packet 254 CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields); 255 command.addReferenceTypeID(classID); 256 command.setLength(); 257 258 // send the command and receive reply 259 ReplyPacket reply = debugee.receiveReplyFor(command); 260 261 // extract fieldIDs from the reply packet 262 try { 263 reply.resetPosition(); 264 265 int declared = reply.getInt(); 266 long[] fieldIDs = new long[declared]; 267 268 for (int i = 0; i < declared; i++ ) { 269 long fieldID = reply.getFieldID(); 270 String name = reply.getString(); 271 String signature = reply.getString(); 272 int modBits = reply.getInt(); 273 274 fieldIDs[i] = fieldID; 275 } 276 return fieldIDs; 277 } catch (BoundException e) { 278 log.complain("Unable to parse reply packet for ReferenceType.Fields command:\n\t" 279 + e); 280 log.complain("Received reply packet:\n" 281 + reply); 282 throw new Failure("Error occured while getting static fieldIDs for classID: " + classID); 283 } 284 } 285 286 /** 287 * Query debugee for values of the class static fields. 288 */ queryClassFieldValues(long classID, long fieldIDs[])289 JDWP.Value[] queryClassFieldValues(long classID, long fieldIDs[]) { 290 // compose ReferenceType.Fields command packet 291 int count = fieldIDs.length; 292 CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.GetValues); 293 command.addReferenceTypeID(classID); 294 command.addInt(count); 295 for (int i = 0; i < count; i++) { 296 command.addFieldID(fieldIDs[i]); 297 } 298 command.setLength(); 299 300 // send the command and receive reply 301 ReplyPacket reply = debugee.receiveReplyFor(command); 302 303 // extract values from the reply packet 304 try { 305 reply.resetPosition(); 306 307 int valuesCount = reply.getInt(); 308 JDWP.Value values[] = new JDWP.Value[valuesCount]; 309 for (int i = 0; i < valuesCount; i++ ) { 310 JDWP.Value value = reply.getValue(); 311 values[i] = value; 312 } 313 return values; 314 } catch (BoundException e) { 315 log.complain("Unable to parse reply packet for ReferenceType.GetValues command:\n\t" 316 + e); 317 log.complain("Received reply packet:\n" 318 + reply); 319 throw new Failure("Error occured while getting static fields values for classID: " + classID); 320 } 321 } 322 323 /** 324 * Perform testing JDWP command for specified classID. 325 */ testCommand(long classID, long fieldIDs[], JDWP.Value values[])326 void testCommand(long classID, long fieldIDs[], JDWP.Value values[]) { 327 int count = fieldIDs.length; 328 329 // create command packet 330 log.display("Create command packet:"); 331 log.display("Command: " + JDWP_COMMAND_NAME); 332 CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); 333 334 // add out data to the command packet 335 log.display(" classID: " + classID); 336 command.addReferenceTypeID(classID); 337 log.display(" values: " + count); 338 command.addInt(count); 339 for (int i = 0; i < count; i++) { 340 log.display(" field #" + i +":"); 341 log.display(" fieldID: " + fieldIDs[i]); 342 command.addFieldID(fieldIDs[i]); 343 344 JDWP.Value value = values[i]; 345 JDWP.UntaggedValue untaggedValue = 346 new JDWP.UntaggedValue(value.getValue()); 347 log.display(" untagged_value: " + untaggedValue.getValue()); 348 command.addUntaggedValue(untaggedValue, value.getTag()); 349 } 350 command.setLength(); 351 352 // send command packet to debugee 353 try { 354 log.display("Sending command packet:\n" + command); 355 transport.write(command); 356 } catch (IOException e) { 357 log.complain("Unable to send command packet:\n" + e); 358 success = false; 359 return; 360 } 361 362 ReplyPacket reply = new ReplyPacket(); 363 364 // receive reply packet from debugee 365 try { 366 log.display("Waiting for reply packet"); 367 transport.read(reply); 368 log.display("Reply packet received:\n" + reply); 369 } catch (IOException e) { 370 log.complain("Unable to read reply packet:\n" + e); 371 success = false; 372 return; 373 } 374 375 // check reply packet header 376 try{ 377 log.display("Checking reply packet header"); 378 reply.checkHeader(command.getPacketID()); 379 } catch (BoundException e) { 380 log.complain("Bad header of reply packet: " + e.getMessage()); 381 success = false; 382 } 383 384 // start parsing reply packet data 385 log.display("Parsing reply packet:"); 386 reply.resetPosition(); 387 388 // no data to extract 389 390 // check for extra data in reply packet 391 if (! reply.isParsed()) { 392 log.complain("Extra trailing bytes found in reply packet at: " 393 + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); 394 success = false; 395 } 396 } 397 398 /** 399 * Check confiramtion from debuggee that values are changed. 400 */ checkValuesChanged()401 void checkValuesChanged() { 402 // send debugee signal RUN 403 log.display("Sending signal to debugee: " + RUN); 404 pipe.println(RUN); 405 406 // wait for DONE signal from debugee 407 log.display("Waiting for signal from debugee: " + DONE); 408 String signal = pipe.readln(); 409 log.display("Received signal from debugee: " + signal); 410 411 // check received signal 412 if (signal == null) { 413 throw new TestBug("<null> signal received from debugee: " + signal 414 + " (expected: " + DONE + ")"); 415 } else if (signal.equals(DONE)) { 416 log.display("All static fields values have been correctly set into debuggee VM"); 417 } else if (signal.equals(ERROR)) { 418 log.complain("Not all static fields values have been correctly set into debuggee VM"); 419 success = false; 420 } else { 421 throw new TestBug("Unexpected signal received from debugee: " + signal 422 + " (expected: " + DONE + ")"); 423 } 424 } 425 426 } 427