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