1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Vitaly A. Provodin 21 */ 22 23 /** 24 * Created on 29.01.2005 25 */ 26 package org.apache.harmony.jpda.tests.jdwp.share; 27 28 import org.apache.harmony.jpda.tests.framework.TestErrorException; 29 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 30 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket; 31 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 32 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 33 import org.apache.harmony.jpda.tests.framework.jdwp.Packet; 34 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 35 36 /** 37 * Basic class for unit tests which use only one debuggee VM. 38 */ 39 public abstract class JDWPTestCase extends JDWPRawTestCase { 40 41 /** 42 * DebuggeeWrapper instance for launched debuggee VM. 43 */ 44 protected JDWPUnitDebuggeeWrapper debuggeeWrapper; 45 46 /** 47 * EventPacket instance with received VM_START event. 48 */ 49 protected EventPacket initialEvent = null; 50 51 /** 52 * Overrides inherited method to launch one debuggee VM, establish JDWP 53 * connection, and wait for VM_START event. 54 */ internalSetUp()55 protected void internalSetUp() throws Exception { 56 super.internalSetUp(); 57 58 // launch debuggee process 59 debuggeeWrapper = createDebuggeeWrapper(); 60 beforeDebuggeeStart(debuggeeWrapper); 61 startDebuggeeWrapper(); 62 63 // receive and handle initial event 64 receiveInitialEvent(); 65 66 // adjust JDWP types length 67 debuggeeWrapper.vmMirror.adjustTypeLength(); 68 logWriter.println("Adjusted VM-dependent type lengths"); 69 } 70 71 /** 72 * Creates wrapper for debuggee process. 73 */ createDebuggeeWrapper()74 protected JDWPUnitDebuggeeWrapper createDebuggeeWrapper() { 75 if (settings.getDebuggeeLaunchKind().equals("manual")) { 76 return new JDWPManualDebuggeeWrapper(settings, logWriter); 77 } else { 78 return new JDWPUnitDebuggeeWrapper(settings, logWriter); 79 } 80 } 81 82 /** 83 * Starts wrapper for debuggee process. 84 */ startDebuggeeWrapper()85 protected void startDebuggeeWrapper() { 86 debuggeeWrapper.start(); 87 logWriter.println("Established JDWP connection with debuggee VM"); 88 } 89 90 /** 91 * Receives initial VM_INIT event if debuggee is suspended on event. 92 */ receiveInitialEvent()93 protected void receiveInitialEvent() { 94 if (settings.isDebuggeeSuspend()) { 95 initialEvent = 96 debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.VM_INIT); 97 logWriter.println("Received inital VM_INIT event"); 98 } 99 } 100 101 /** 102 * Overrides inherited method to stop started debuggee VM and close all 103 * connections. 104 */ internalTearDown()105 protected void internalTearDown() { 106 if (debuggeeWrapper != null) { 107 debuggeeWrapper.stop(); 108 logWriter.println("Closed JDWP connection with debuggee VM"); 109 } 110 super.internalTearDown(); 111 } 112 113 /** 114 * This method is invoked right before starting debuggee VM. 115 */ beforeDebuggeeStart(JDWPUnitDebuggeeWrapper debuggeeWrapper)116 protected void beforeDebuggeeStart(JDWPUnitDebuggeeWrapper debuggeeWrapper) { 117 118 } 119 120 /** 121 * Opens JDWP connection with debuggee (doesn't run debuggee and doesn't 122 * establish synchronize connection). 123 */ openConnection()124 public void openConnection() { 125 debuggeeWrapper.openConnection(); 126 logWriter.println("Opened transport connection"); 127 debuggeeWrapper.vmMirror.adjustTypeLength(); 128 logWriter.println("Adjusted VM-dependent type lengths"); 129 } 130 131 /** 132 * Closes JDWP connection with debuggee (doesn't terminate debuggee and 133 * doesn't stop synchronize connection). 134 */ closeConnection()135 public void closeConnection() { 136 if (debuggeeWrapper != null) { 137 debuggeeWrapper.disposeConnection(); 138 try { 139 debuggeeWrapper.vmMirror.closeConnection(); 140 } catch (Exception e) { 141 throw new TestErrorException(e); 142 } 143 logWriter.println("Closed transport connection"); 144 } 145 } 146 147 /** 148 * Helper that returns reference type signature of input object ID. 149 * 150 * @param objectID - 151 * debuggee object ID 152 * @return object signature of reference type 153 */ getObjectSignature(long objectID)154 protected String getObjectSignature(long objectID) { 155 long classID = getObjectReferenceType(objectID); 156 return getClassSignature(classID); 157 } 158 159 /** 160 * Helper that returns reference type ID for input object ID. 161 * 162 * @param objectID - 163 * debuggee object ID 164 * @return reference type ID 165 */ getObjectReferenceType(long objectID)166 protected long getObjectReferenceType(long objectID) { 167 CommandPacket command = new CommandPacket( 168 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 169 JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand); 170 command.setNextValueAsReferenceTypeID(objectID); 171 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command); 172 checkReplyPacket(reply, "ObjectReference::ReferenceType command"); 173 // byte refTypeTag = 174 reply.getNextValueAsByte(); 175 long objectRefTypeID = reply.getNextValueAsReferenceTypeID(); 176 return objectRefTypeID; 177 } 178 179 /** 180 * Helper for getting method ID of corresponding class and method name. 181 * 182 * @param classID - 183 * class ID 184 * @param methodName - 185 * method name 186 * @return method ID 187 */ getMethodID(long classID, String methodName)188 protected long getMethodID(long classID, String methodName) { 189 CommandPacket command = new CommandPacket( 190 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 191 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand); 192 command.setNextValueAsClassID(classID); 193 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command); 194 checkReplyPacket(reply, "ReferenceType::Methods command"); 195 int methods = reply.getNextValueAsInt(); 196 for (int i = 0; i < methods; i++) { 197 long methodID = reply.getNextValueAsMethodID(); 198 String name = reply.getNextValueAsString(); // method name 199 reply.getNextValueAsString(); // method signature 200 reply.getNextValueAsInt(); // method modifiers 201 if (name.equals(methodName)) { 202 return methodID; 203 } 204 } 205 return -1; 206 } 207 208 /** 209 * Issues LineTable command. 210 * 211 * @param classID - 212 * class ID 213 * @param methodID - 214 * method ID 215 * @return reply packet 216 */ getLineTable(long classID, long methodID)217 protected ReplyPacket getLineTable(long classID, long methodID) { 218 CommandPacket lineTableCommand = new CommandPacket( 219 JDWPCommands.MethodCommandSet.CommandSetID, 220 JDWPCommands.MethodCommandSet.LineTableCommand); 221 lineTableCommand.setNextValueAsReferenceTypeID(classID); 222 lineTableCommand.setNextValueAsMethodID(methodID); 223 ReplyPacket lineTableReply = debuggeeWrapper.vmMirror 224 .performCommand(lineTableCommand); 225 checkReplyPacket(lineTableReply, "Method::LineTable command"); 226 return lineTableReply; 227 } 228 229 /** 230 * Helper for getting method name of corresponding class and method ID. 231 * 232 * @param classID class id 233 * @param methodID method id 234 * @return String 235 */ getMethodName(long classID, long methodID)236 protected String getMethodName(long classID, long methodID) { 237 CommandPacket packet = new CommandPacket( 238 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 239 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand); 240 packet.setNextValueAsClassID(classID); 241 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 242 checkReplyPacket(reply, "ReferenceType::Methods command"); 243 int methods = reply.getNextValueAsInt(); 244 for (int i = 0; i < methods; i++) { 245 long mid = reply.getNextValueAsMethodID(); 246 String name = reply.getNextValueAsString(); 247 reply.getNextValueAsString(); 248 reply.getNextValueAsInt(); 249 if (mid == methodID) { 250 return name; 251 } 252 } 253 return "unknown"; 254 } 255 256 /** 257 * Returns jni signature for selected classID 258 * 259 * @param classID 260 * @return jni signature for selected classID 261 */ getClassSignature(long classID)262 protected String getClassSignature(long classID) { 263 CommandPacket command = new CommandPacket( 264 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 265 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand); 266 command.setNextValueAsReferenceTypeID(classID); 267 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command); 268 checkReplyPacket(reply, "ReferenceType::Signature command"); 269 String signature = reply.getNextValueAsString(); 270 return signature; 271 } 272 273 /** 274 * Returns classID for the selected jni signature 275 * 276 * @param signature 277 * @return classID for the selected jni signature 278 */ getClassIDBySignature(String signature)279 protected long getClassIDBySignature(String signature) { 280 logWriter.println("=> Getting reference type ID for class: " 281 + signature); 282 CommandPacket packet = new CommandPacket( 283 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 284 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand); 285 packet.setNextValueAsString(signature); 286 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 287 checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command"); 288 int classes = reply.getNextValueAsInt(); 289 logWriter.println("=> Returned number of classes: " + classes); 290 long classID = 0; 291 for (int i = 0; i < classes; i++) { 292 reply.getNextValueAsByte(); 293 classID = reply.getNextValueAsReferenceTypeID(); 294 reply.getNextValueAsInt(); 295 // we need the only class, even if there were multiply ones 296 break; 297 } 298 assertTrue( 299 "VirtualMachine::ClassesBySignature command returned invalid classID:<" 300 + classID + "> for signature " + signature, classID > 0); 301 return classID; 302 } 303 304 /** 305 * Returns reference type ID. 306 * 307 * @param signature 308 * @return type ID for the selected jni signature 309 */ getReferenceTypeID(String signature)310 protected long getReferenceTypeID(String signature) { 311 CommandPacket packet = new CommandPacket( 312 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 313 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand); 314 packet.setNextValueAsString(signature); 315 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 316 checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command"); 317 int classes = reply.getNextValueAsInt(); 318 // this class may be loaded only once 319 assertEquals("Invalid number of classes for reference type: " 320 + signature + ",", 1, classes); 321 byte refTypeTag = reply.getNextValueAsByte(); 322 long classID = reply.getNextValueAsReferenceTypeID(); 323 int status = reply.getNextValueAsInt(); 324 logWriter.println("VirtualMachine.ClassesBySignature: classes=" 325 + classes + " refTypeTag=" + refTypeTag + " typeID= " + classID 326 + " status=" + status); 327 assertAllDataRead(reply); 328 assertEquals("", JDWPConstants.TypeTag.CLASS, refTypeTag); 329 return classID; 330 } 331 332 /** 333 * Helper function for resuming debuggee. 334 */ resumeDebuggee()335 protected void resumeDebuggee() { 336 logWriter.println("=> Resume debuggee"); 337 CommandPacket packet = new CommandPacket( 338 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 339 JDWPCommands.VirtualMachineCommandSet.ResumeCommand); 340 logWriter.println("Sending VirtualMachine::Resume command..."); 341 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 342 checkReplyPacket(reply, "VirtualMachine::Resume command"); 343 assertAllDataRead(reply); 344 } 345 346 /** 347 * Performs string creation in debuggee. 348 * 349 * @param value - 350 * content for new string 351 * @return StringID of new created string 352 */ createString(String value)353 protected long createString(String value) { 354 CommandPacket packet = new CommandPacket( 355 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 356 JDWPCommands.VirtualMachineCommandSet.CreateStringCommand); 357 packet.setNextValueAsString(value); 358 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 359 checkReplyPacket(reply, "VirtualMachine::CreateString command"); 360 long stringID = reply.getNextValueAsStringID(); 361 return stringID; 362 } 363 364 /** 365 * Returns corresponding string from string ID. 366 * 367 * @param stringID - 368 * string ID 369 * @return string value 370 */ getStringValue(long stringID)371 protected String getStringValue(long stringID) { 372 CommandPacket packet = new CommandPacket( 373 JDWPCommands.StringReferenceCommandSet.CommandSetID, 374 JDWPCommands.StringReferenceCommandSet.ValueCommand); 375 packet.setNextValueAsObjectID(stringID); 376 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 377 checkReplyPacket(reply, "StringReference::Value command"); 378 String returnedTestString = reply.getNextValueAsString(); 379 return returnedTestString; 380 } 381 382 /** 383 * Multiple field verification routine. 384 * 385 * @param refTypeID - 386 * reference type ID 387 * @param checkedFieldNames - 388 * list of field names to be checked 389 * @return list of field IDs 390 */ checkFields(long refTypeID, String checkedFieldNames[])391 protected long[] checkFields(long refTypeID, String checkedFieldNames[]) { 392 return checkFields(refTypeID, checkedFieldNames, null, null); 393 } 394 395 /** 396 * Single field verification routine. 397 * 398 * @param refTypeID - 399 * reference type ID 400 * @param fieldName - 401 * name of single field 402 * @return filed ID 403 */ checkField(long refTypeID, String fieldName)404 protected long checkField(long refTypeID, String fieldName) { 405 return checkFields(refTypeID, new String[] { fieldName }, null, null)[0]; 406 } 407 408 /** 409 * Multiple field verification routine. 410 * 411 * @param refTypeID - 412 * reference type ID 413 * @param checkedFieldNames - 414 * list of field names to be checked 415 * @param expectedSignatures - 416 * list of expected field signatures 417 * @param expectedModifiers - 418 * list of expected field modifiers 419 * @return list of field IDs 420 */ checkFields(long refTypeID, String checkedFieldNames[], String expectedSignatures[], int expectedModifiers[])421 protected long[] checkFields(long refTypeID, String checkedFieldNames[], 422 String expectedSignatures[], int expectedModifiers[]) { 423 424 boolean checkedFieldFound[] = new boolean[checkedFieldNames.length]; 425 long checkedFieldIDs[] = new long[checkedFieldNames.length]; 426 427 logWriter 428 .println("=> Send ReferenceType::Fields command and get field ID(s)"); 429 430 CommandPacket fieldsCommand = new CommandPacket( 431 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 432 JDWPCommands.ReferenceTypeCommandSet.FieldsCommand); 433 fieldsCommand.setNextValueAsReferenceTypeID(refTypeID); 434 ReplyPacket fieldsReply = debuggeeWrapper.vmMirror 435 .performCommand(fieldsCommand); 436 fieldsCommand = null; 437 checkReplyPacket(fieldsReply, "ReferenceType::Fields command"); 438 439 int returnedFieldsNumber = fieldsReply.getNextValueAsInt(); 440 logWriter 441 .println("=> Returned fields number = " + returnedFieldsNumber); 442 443 int checkedFieldsNumber = checkedFieldNames.length; 444 final int fieldSyntheticFlag = 0xf0000000; 445 446 int nameDuplicated = 0; 447 String fieldNameDuplicated = null; // <= collects all duplicated fields 448 int nameMissing = 0; 449 String fieldNameMissing = null; // <= collects all missed fields 450 451 for (int i = 0; i < returnedFieldsNumber; i++) { 452 long returnedFieldID = fieldsReply.getNextValueAsFieldID(); 453 String returnedFieldName = fieldsReply.getNextValueAsString(); 454 String returnedFieldSignature = fieldsReply.getNextValueAsString(); 455 int returnedFieldModifiers = fieldsReply.getNextValueAsInt(); 456 logWriter.println(""); 457 logWriter.println("=> Field ID: " + returnedFieldID); 458 logWriter.println("=> Field name: " + returnedFieldName); 459 logWriter.println("=> Field signature: " + returnedFieldSignature); 460 logWriter.println("=> Field modifiers: 0x" 461 + Integer.toHexString(returnedFieldModifiers)); 462 if ((returnedFieldModifiers & fieldSyntheticFlag) == fieldSyntheticFlag) { 463 continue; // do not check synthetic fields 464 } 465 for (int k = 0; k < checkedFieldsNumber; k++) { 466 if (!checkedFieldNames[k].equals(returnedFieldName)) { 467 continue; 468 } 469 if (checkedFieldFound[k]) { 470 logWriter.println(""); 471 logWriter 472 .println("## FAILURE: The field is found repeatedly in the list"); 473 logWriter.println("## Field Name: " + returnedFieldName); 474 logWriter.println("## Field ID: " + returnedFieldID); 475 logWriter.println("## Field Signature: " 476 + returnedFieldSignature); 477 logWriter.println("## Field Modifiers: 0x" 478 + Integer.toHexString(returnedFieldModifiers)); 479 fieldNameDuplicated = (0 == nameDuplicated ? returnedFieldName 480 : fieldNameDuplicated + "," + returnedFieldName); 481 nameDuplicated++; 482 break; 483 } 484 checkedFieldFound[k] = true; 485 checkedFieldIDs[k] = returnedFieldID; 486 if (null != expectedSignatures) { 487 assertString( 488 "Invalid field signature is returned for field:" 489 + returnedFieldName + ",", 490 expectedSignatures[k], returnedFieldSignature); 491 } 492 if (null != expectedModifiers) { 493 assertEquals( 494 "Invalid field modifiers are returned for field:" 495 + returnedFieldName + ",", 496 expectedModifiers[k], returnedFieldModifiers); 497 } 498 break; 499 } 500 } 501 502 for (int k = 0; k < checkedFieldsNumber; k++) { 503 if (!checkedFieldFound[k]) { 504 logWriter.println(""); 505 logWriter 506 .println("\n## FAILURE: Expected field is NOT found in the list of retuned fields:"); 507 logWriter.println("## Field name = " + checkedFieldNames[k]); 508 fieldNameMissing = 0 == nameMissing ? checkedFieldNames[k] 509 : fieldNameMissing + "," + checkedFieldNames[k]; 510 nameMissing++; 511 // break; 512 } 513 } 514 515 // String thisTestName = this.getClass().getName(); 516 // logWriter.println("==> " + thisTestName + " for " + thisCommandName + 517 // ": FAILED"); 518 519 if (nameDuplicated > 1) { 520 fail("Duplicated fields are found in the retuned by FieldsCommand list: " 521 + fieldNameDuplicated); 522 } 523 if (nameDuplicated > 0) { 524 fail("Duplicated field is found in the retuned by FieldsCommand list: " 525 + fieldNameDuplicated); 526 } 527 if (nameMissing > 1) { 528 fail("Expected fields are NOT found in the retuned by FieldsCommand list: " 529 + fieldNameMissing); 530 } 531 if (nameMissing > 0) { 532 fail("Expected field is NOT found in the retuned by FieldsCommand list: " 533 + fieldNameMissing); 534 } 535 536 logWriter.println(""); 537 if (1 == checkedFieldsNumber) { 538 logWriter 539 .println("=> Expected field was found and field ID was got"); 540 } else { 541 logWriter 542 .println("=> Expected fields were found and field IDs were got"); 543 } 544 545 assertAllDataRead(fieldsReply); 546 return checkedFieldIDs; 547 } 548 549 /** 550 * Checks thread status and suspend status of a thread 551 * 552 * @param eventThreadID 553 * the thread ID to check 554 * @param expectedThreadStatus 555 * the expected thread status 556 * @param expectedSuspendStatus 557 * the expected suspend status 558 */ checkThreadState(long eventThreadID, byte expectedThreadStatus, byte expectedSuspendStatus)559 protected void checkThreadState(long eventThreadID, byte expectedThreadStatus, 560 byte expectedSuspendStatus) { 561 CommandPacket commandPacket = new CommandPacket( 562 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 563 JDWPCommands.ThreadReferenceCommandSet.StatusCommand); 564 commandPacket.setNextValueAsThreadID(eventThreadID); 565 ReplyPacket replyPacket = debuggeeWrapper.vmMirror.performCommand(commandPacket); 566 debuggeeWrapper.vmMirror.checkReply(replyPacket); 567 568 int threadStatus = replyPacket.getNextValueAsInt(); 569 int suspendStatus = replyPacket.getNextValueAsInt(); 570 assertAllDataRead(replyPacket); 571 572 assertEquals("Invalid thread status", threadStatus, expectedThreadStatus, 573 JDWPConstants.ThreadStatus.getName(expectedThreadStatus), 574 JDWPConstants.ThreadStatus.getName(threadStatus)); 575 assertEquals("Invalid suspend status", suspendStatus, expectedSuspendStatus, 576 JDWPConstants.SuspendStatus.getName(expectedSuspendStatus), 577 JDWPConstants.SuspendStatus.getName(suspendStatus)); 578 } 579 580 /** 581 * Helper for checking reply packet error code. Calls junit fail if packet 582 * error code does not equal to expected error code. 583 * 584 * @param reply - 585 * returned from debuggee packet 586 * @param message - 587 * additional message 588 * @param errorCodeExpected - 589 * array of expected error codes 590 */ checkReplyPacket(ReplyPacket reply, String message, int errorCodeExpected)591 protected void checkReplyPacket(ReplyPacket reply, String message, 592 int errorCodeExpected) { 593 checkReplyPacket(reply, message, new int[] { errorCodeExpected }); 594 } 595 596 /** 597 * Helper for checking reply packet error code. Calls junit fail if packet 598 * error code does not equal NONE. 599 * 600 * @param reply - 601 * returned from debuggee packet 602 * @param message - 603 * additional message 604 */ checkReplyPacket(ReplyPacket reply, String message)605 protected void checkReplyPacket(ReplyPacket reply, String message) { 606 checkReplyPacket(reply, message, JDWPConstants.Error.NONE); 607 } 608 609 /** 610 * Helper for checking reply packet error code. Calls junit fail if packet 611 * error code does not equal to expected error code. 612 * 613 * @param reply - 614 * returned from debuggee packet 615 * @param message - 616 * additional message 617 * @param expected - 618 * array of expected error codes 619 */ checkReplyPacket(ReplyPacket reply, String message, int[] expected)620 protected void checkReplyPacket(ReplyPacket reply, String message, 621 int[] expected) { 622 checkReplyPacket(reply, message, expected, true /* failSign */); 623 } 624 625 /** 626 * Helper for checking reply packet error code. If reply packet does not 627 * have error - returns true. Otherwise does not call junit fail - simply 628 * prints error message and returns false. if packet error code does not 629 * equal NONE. 630 * 631 * @param reply - 632 * returned from debuggee packet 633 * @param message - 634 * additional message 635 * @return true if error is not found, or false otherwise 636 */ checkReplyPacketWithoutFail(ReplyPacket reply, String message)637 protected boolean checkReplyPacketWithoutFail(ReplyPacket reply, 638 String message) { 639 return checkReplyPacket(reply, message, 640 new int[] { JDWPConstants.Error.NONE }, false /* failSign */); 641 } 642 643 /** 644 * Helper for checking reply packet error code. If reply packet does not 645 * have unexpected error - returns true. If reply packet has got unexpected 646 * error: If failSign param = true - calls junit fail. Otherwise prints 647 * message about error and returns false. 648 * 649 * @param reply - 650 * returned from debuggee packet 651 * @param message - 652 * additional message 653 * @param expected - 654 * array of expected error codes 655 * @param failSign - 656 * defines to call junit fail or not 657 * @return true if unexpected errors are not found, or false otherwise 658 */ checkReplyPacket(ReplyPacket reply, String message, int[] expected, boolean failSign)659 protected boolean checkReplyPacket(ReplyPacket reply, String message, 660 int[] expected, boolean failSign) { 661 // check reply code against expected 662 int errorCode = reply.getErrorCode(); 663 for (int i = 0; i < expected.length; i++) { 664 if (reply.getErrorCode() == expected[i]) { 665 return true; // OK 666 } 667 } 668 669 // replay code validation failed 670 // start error message composition 671 if (null == message) { 672 message = ""; 673 } else { 674 message = message + ", "; 675 } 676 677 // format error message 678 if (expected.length == 1 && JDWPConstants.Error.NONE == expected[0]) { 679 message = message + "Error Code:<" + errorCode + "(" 680 + JDWPConstants.Error.getName(errorCode) + ")>"; 681 } else { 682 message = message + "Unexpected error code:<" + errorCode + "(" 683 + JDWPConstants.Error.getName(errorCode) + ")>" 684 + ", Expected error code" 685 + (expected.length == 1 ? ":" : "s:"); 686 for (int i = 0; i < expected.length; i++) { 687 message = message + (i > 0 ? ",<" : "<") + expected[i] + "(" 688 + JDWPConstants.Error.getName(expected[i]) + ")>"; 689 } 690 } 691 692 if (failSign) { 693 printErrorAndFail(message); 694 } 695 logWriter.printError(message); 696 return false; 697 } 698 699 /** 700 * Helper for comparison numbers and printing string equivalents. 701 * 702 * @param message - 703 * user message 704 * @param expected - 705 * expected value 706 * @param actual - 707 * actual value 708 * @param strExpected - 709 * string equivalent of expected value 710 * @param strActual - 711 * string equivalent of actual value 712 */ assertEquals(String message, long expected, long actual, String strExpected, String strActual)713 protected void assertEquals(String message, long expected, long actual, 714 String strExpected, String strActual) { 715 if (expected == actual) { 716 return; // OK 717 } 718 719 if (null == message) { 720 message = ""; 721 } 722 723 if (null == strExpected) { 724 strExpected = expected + ""; 725 } else { 726 strExpected = expected + "(" + strExpected + ")"; 727 } 728 729 if (null == strActual) { 730 strActual = actual + ""; 731 } else { 732 strActual = actual + "(" + strActual + ")"; 733 } 734 735 printErrorAndFail(message + " expected:<" + strExpected + "> but was:<" 736 + strActual + ">"); 737 } 738 739 /** 740 * Asserts that two strings are equal. 741 * 742 * @param message - 743 * user message 744 * @param expected - 745 * expected string 746 * @param actual - 747 * actual string 748 */ assertString(String message, String expected, String actual)749 protected void assertString(String message, String expected, String actual) { 750 if (null == expected) { 751 expected = ""; 752 } 753 if (null == actual) { 754 actual = ""; 755 } 756 if (expected.equals(actual)) { 757 return; // OK 758 } 759 printErrorAndFail(message + " expected:<" + expected + "> but was:<" 760 + actual + ">"); 761 } 762 763 /** 764 * Helper for checking reply packet data has been read. 765 * 766 * @param reply - 767 * reply packet from debuggee 768 */ assertAllDataRead(Packet reply)769 protected void assertAllDataRead(Packet reply) { 770 if (reply.isAllDataRead()) { 771 return; // OK 772 } 773 printErrorAndFail("Not all data has been read"); 774 } 775 776 /** 777 * Prints error message in log writer and in junit fail. 778 * 779 * @param message - 780 * error message 781 */ printErrorAndFail(String message)782 protected void printErrorAndFail(String message) { 783 logWriter.printError(message); 784 fail(message); 785 } 786 787 /** 788 * Helper for setting static int field in class with new value. 789 * 790 * @param classSignature - 791 * String defining signature of class 792 * @param fieldName - 793 * String defining field name in specified class 794 * @param newValue - 795 * int value to set for specified field 796 * @return true, if setting is successfully, or false otherwise 797 */ setStaticIntField(String classSignature, String fieldName, int newValue)798 protected boolean setStaticIntField(String classSignature, 799 String fieldName, int newValue) { 800 801 long classID = debuggeeWrapper.vmMirror.getClassID(classSignature); 802 if (classID == -1) { 803 logWriter 804 .println("## setStaticIntField(): Can NOT get classID for class signature = '" 805 + classSignature + "'"); 806 return false; 807 } 808 809 long fieldID = debuggeeWrapper.vmMirror.getFieldID(classID, fieldName); 810 if (fieldID == -1) { 811 logWriter 812 .println("## setStaticIntField(): Can NOT get fieldID for field = '" 813 + fieldName + "'"); 814 return false; 815 } 816 817 CommandPacket packet = new CommandPacket( 818 JDWPCommands.ClassTypeCommandSet.CommandSetID, 819 JDWPCommands.ClassTypeCommandSet.SetValuesCommand); 820 packet.setNextValueAsReferenceTypeID(classID); 821 packet.setNextValueAsInt(1); 822 packet.setNextValueAsFieldID(fieldID); 823 packet.setNextValueAsInt(newValue); 824 825 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 826 int errorCode = reply.getErrorCode(); 827 if (errorCode != JDWPConstants.Error.NONE) { 828 logWriter 829 .println("## setStaticIntField(): Can NOT set value for field = '" 830 + fieldName 831 + "' in class = '" 832 + classSignature 833 + "'; ClassType.SetValues command reurns error = " 834 + errorCode); 835 return false; 836 } 837 return true; 838 } 839 840 /** 841 * Removes breakpoint of the given event kind corresponding to the given 842 * request id. 843 * 844 * @param eventKind 845 * request event kind 846 * @param requestID 847 * request id 848 * @param verbose 849 * print or don't extra log info 850 */ clearEvent(byte eventKind, int requestID, boolean verbose)851 protected void clearEvent(byte eventKind, int requestID, boolean verbose) { 852 CommandPacket packet = new CommandPacket( 853 JDWPCommands.EventRequestCommandSet.CommandSetID, 854 JDWPCommands.EventRequestCommandSet.ClearCommand); 855 packet.setNextValueAsByte(eventKind); 856 packet.setNextValueAsInt(requestID); 857 if (verbose) { 858 logWriter.println("Clearing event: " 859 + JDWPConstants.EventKind.getName(eventKind) + ", id: " 860 + requestID); 861 } 862 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 863 checkReplyPacket(reply, "EventRequest::Clear command"); 864 assertAllDataRead(reply); 865 } 866 } 867