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