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