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 * Helper for checking reply packet error code. Calls junit fail if packet 551 * error code does not equal to expected error code. 552 * 553 * @param reply - 554 * returned from debuggee packet 555 * @param message - 556 * additional message 557 * @param errorCodeExpected - 558 * array of expected error codes 559 */ checkReplyPacket(ReplyPacket reply, String message, int errorCodeExpected)560 protected void checkReplyPacket(ReplyPacket reply, String message, 561 int errorCodeExpected) { 562 checkReplyPacket(reply, message, new int[] { errorCodeExpected }); 563 } 564 565 /** 566 * Helper for checking reply packet error code. Calls junit fail if packet 567 * error code does not equal NONE. 568 * 569 * @param reply - 570 * returned from debuggee packet 571 * @param message - 572 * additional message 573 */ checkReplyPacket(ReplyPacket reply, String message)574 protected void checkReplyPacket(ReplyPacket reply, String message) { 575 checkReplyPacket(reply, message, JDWPConstants.Error.NONE); 576 } 577 578 /** 579 * Helper for checking reply packet error code. Calls junit fail if packet 580 * error code does not equal to expected error code. 581 * 582 * @param reply - 583 * returned from debuggee packet 584 * @param message - 585 * additional message 586 * @param expected - 587 * array of expected error codes 588 */ checkReplyPacket(ReplyPacket reply, String message, int[] expected)589 protected void checkReplyPacket(ReplyPacket reply, String message, 590 int[] expected) { 591 checkReplyPacket(reply, message, expected, true /* failSign */); 592 } 593 594 /** 595 * Helper for checking reply packet error code. If reply packet does not 596 * have error - returns true. Otherwise does not call junit fail - simply 597 * prints error message and returns false. if packet error code does not 598 * equal NONE. 599 * 600 * @param reply - 601 * returned from debuggee packet 602 * @param message - 603 * additional message 604 * @return true if error is not found, or false otherwise 605 */ checkReplyPacketWithoutFail(ReplyPacket reply, String message)606 protected boolean checkReplyPacketWithoutFail(ReplyPacket reply, 607 String message) { 608 return checkReplyPacket(reply, message, 609 new int[] { JDWPConstants.Error.NONE }, false /* failSign */); 610 } 611 612 /** 613 * Helper for checking reply packet error code. If reply packet does not 614 * have unexpected error - returns true. If reply packet has got unexpected 615 * error: If failSign param = true - calls junit fail. Otherwise prints 616 * message about error and returns false. 617 * 618 * @param reply - 619 * returned from debuggee packet 620 * @param message - 621 * additional message 622 * @param expected - 623 * array of expected error codes 624 * @param failSign - 625 * defines to call junit fail or not 626 * @return true if unexpected errors are not found, or false otherwise 627 */ checkReplyPacket(ReplyPacket reply, String message, int[] expected, boolean failSign)628 protected boolean checkReplyPacket(ReplyPacket reply, String message, 629 int[] expected, boolean failSign) { 630 // check reply code against expected 631 int errorCode = reply.getErrorCode(); 632 for (int i = 0; i < expected.length; i++) { 633 if (reply.getErrorCode() == expected[i]) { 634 return true; // OK 635 } 636 } 637 638 // replay code validation failed 639 // start error message composition 640 if (null == message) { 641 message = ""; 642 } else { 643 message = message + ", "; 644 } 645 646 // format error message 647 if (expected.length == 1 && JDWPConstants.Error.NONE == expected[0]) { 648 message = message + "Error Code:<" + errorCode + "(" 649 + JDWPConstants.Error.getName(errorCode) + ")>"; 650 } else { 651 message = message + "Unexpected error code:<" + errorCode + "(" 652 + JDWPConstants.Error.getName(errorCode) + ")>" 653 + ", Expected error code" 654 + (expected.length == 1 ? ":" : "s:"); 655 for (int i = 0; i < expected.length; i++) { 656 message = message + (i > 0 ? ",<" : "<") + expected[i] + "(" 657 + JDWPConstants.Error.getName(expected[i]) + ")>"; 658 } 659 } 660 661 if (failSign) { 662 printErrorAndFail(message); 663 } 664 logWriter.printError(message); 665 return false; 666 } 667 668 /** 669 * Helper for comparison numbers and printing string equivalents. 670 * 671 * @param message - 672 * user message 673 * @param expected - 674 * expected value 675 * @param actual - 676 * actual value 677 * @param strExpected - 678 * string equivalent of expected value 679 * @param strActual - 680 * string equivalent of actual value 681 */ assertEquals(String message, long expected, long actual, String strExpected, String strActual)682 protected void assertEquals(String message, long expected, long actual, 683 String strExpected, String strActual) { 684 if (expected == actual) { 685 return; // OK 686 } 687 688 if (null == message) { 689 message = ""; 690 } 691 692 if (null == strExpected) { 693 strExpected = expected + ""; 694 } else { 695 strExpected = expected + "(" + strExpected + ")"; 696 } 697 698 if (null == strActual) { 699 strActual = actual + ""; 700 } else { 701 strActual = actual + "(" + strActual + ")"; 702 } 703 704 printErrorAndFail(message + " expected:<" + strExpected + "> but was:<" 705 + strActual + ">"); 706 } 707 708 /** 709 * Asserts that two strings are equal. 710 * 711 * @param message - 712 * user message 713 * @param expected - 714 * expected string 715 * @param actual - 716 * actual string 717 */ assertString(String message, String expected, String actual)718 protected void assertString(String message, String expected, String actual) { 719 if (null == expected) { 720 expected = ""; 721 } 722 if (null == actual) { 723 actual = ""; 724 } 725 if (expected.equals(actual)) { 726 return; // OK 727 } 728 printErrorAndFail(message + " expected:<" + expected + "> but was:<" 729 + actual + ">"); 730 } 731 732 /** 733 * Helper for checking reply packet data has been read. 734 * 735 * @param reply - 736 * reply packet from debuggee 737 */ assertAllDataRead(Packet reply)738 protected void assertAllDataRead(Packet reply) { 739 if (reply.isAllDataRead()) { 740 return; // OK 741 } 742 printErrorAndFail("Not all data has been read"); 743 } 744 745 /** 746 * Prints error message in log writer and in junit fail. 747 * 748 * @param message - 749 * error message 750 */ printErrorAndFail(String message)751 protected void printErrorAndFail(String message) { 752 logWriter.printError(message); 753 fail(message); 754 } 755 756 /** 757 * Helper for setting static int field in class with new value. 758 * 759 * @param classSignature - 760 * String defining signature of class 761 * @param fieldName - 762 * String defining field name in specified class 763 * @param newValue - 764 * int value to set for specified field 765 * @return true, if setting is successfully, or false otherwise 766 */ setStaticIntField(String classSignature, String fieldName, int newValue)767 protected boolean setStaticIntField(String classSignature, 768 String fieldName, int newValue) { 769 770 long classID = debuggeeWrapper.vmMirror.getClassID(classSignature); 771 if (classID == -1) { 772 logWriter 773 .println("## setStaticIntField(): Can NOT get classID for class signature = '" 774 + classSignature + "'"); 775 return false; 776 } 777 778 long fieldID = debuggeeWrapper.vmMirror.getFieldID(classID, fieldName); 779 if (fieldID == -1) { 780 logWriter 781 .println("## setStaticIntField(): Can NOT get fieldID for field = '" 782 + fieldName + "'"); 783 return false; 784 } 785 786 CommandPacket packet = new CommandPacket( 787 JDWPCommands.ClassTypeCommandSet.CommandSetID, 788 JDWPCommands.ClassTypeCommandSet.SetValuesCommand); 789 packet.setNextValueAsReferenceTypeID(classID); 790 packet.setNextValueAsInt(1); 791 packet.setNextValueAsFieldID(fieldID); 792 packet.setNextValueAsInt(newValue); 793 794 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 795 int errorCode = reply.getErrorCode(); 796 if (errorCode != JDWPConstants.Error.NONE) { 797 logWriter 798 .println("## setStaticIntField(): Can NOT set value for field = '" 799 + fieldName 800 + "' in class = '" 801 + classSignature 802 + "'; ClassType.SetValues command reurns error = " 803 + errorCode); 804 return false; 805 } 806 return true; 807 } 808 809 /** 810 * Removes breakpoint of the given event kind corresponding to the given 811 * request id. 812 * 813 * @param eventKind 814 * request event kind 815 * @param requestID 816 * request id 817 * @param verbose 818 * print or don't extra log info 819 */ clearEvent(byte eventKind, int requestID, boolean verbose)820 protected void clearEvent(byte eventKind, int requestID, boolean verbose) { 821 CommandPacket packet = new CommandPacket( 822 JDWPCommands.EventRequestCommandSet.CommandSetID, 823 JDWPCommands.EventRequestCommandSet.ClearCommand); 824 packet.setNextValueAsByte(eventKind); 825 packet.setNextValueAsInt(requestID); 826 if (verbose) { 827 logWriter.println("Clearing event: " 828 + JDWPConstants.EventKind.getName(eventKind) + ", id: " 829 + requestID); 830 } 831 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 832 checkReplyPacket(reply, "EventRequest::Clear command"); 833 assertAllDataRead(reply); 834 } 835 } 836