blob: 47d2a2bf19f69c9cdd14636870b62ce16c3a9e67 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Vitaly A. Provodin
*/
/**
* Created on 29.01.2005
*/
package org.apache.harmony.jpda.tests.jdwp.share;
import org.apache.harmony.jpda.tests.framework.TestErrorException;
import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
import org.apache.harmony.jpda.tests.framework.jdwp.Packet;
import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
/**
* Basic class for unit tests which use only one debuggee VM.
*/
public abstract class JDWPTestCase extends JDWPRawTestCase {
/**
* DebuggeeWrapper instance for launched debuggee VM.
*/
protected JDWPUnitDebuggeeWrapper debuggeeWrapper;
/**
* EventPacket instance with received VM_START event.
*/
protected EventPacket initialEvent = null;
/**
* Overrides inherited method to launch one debuggee VM, establish JDWP
* connection, and wait for VM_START event.
*/
protected void internalSetUp() throws Exception {
super.internalSetUp();
// launch debuggee process
debuggeeWrapper = createDebuggeeWrapper();
beforeConnectionSetUp();
setUpDebuggeeWrapperConnection();
beforeDebuggeeStart();
startDebuggeeWrapper();
// receive and handle initial event
receiveInitialEvent();
// adjust JDWP types length
debuggeeWrapper.vmMirror.adjustTypeLength();
logWriter.println("Adjusted VM-dependent type lengths");
}
/**
* Creates wrapper for debuggee process.
*/
protected JDWPUnitDebuggeeWrapper createDebuggeeWrapper() {
if (settings.getDebuggeeLaunchKind().equals("manual")) {
return new JDWPManualDebuggeeWrapper(settings, logWriter);
} else {
return new JDWPUnitDebuggeeWrapper(settings, logWriter);
}
}
/**
* Set up server side JDWP connection.
*/
protected void setUpDebuggeeWrapperConnection() {
debuggeeWrapper.setUpConnection();
logWriter.println("Set up server side JDWP connection.");
}
/**
* Starts wrapper for debuggee process.
*/
protected void startDebuggeeWrapper() {
debuggeeWrapper.start();
logWriter.println("Established JDWP connection with debuggee VM");
}
/**
* Receives initial VM_INIT event if debuggee is suspended on event.
*/
protected void receiveInitialEvent() {
if (settings.isDebuggeeSuspend()) {
initialEvent =
debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.VM_INIT);
logWriter.println("Received inital VM_INIT event");
}
}
/**
* Overrides inherited method to stop started debuggee VM and close all
* connections.
*/
protected void internalTearDown() {
if (debuggeeWrapper != null) {
debuggeeWrapper.stop();
logWriter.println("Closed JDWP connection with debuggee VM");
}
super.internalTearDown();
}
/**
* This method is invoked right before setting up the server side JDWP connection.
*/
protected void beforeConnectionSetUp() {
// Empty.
}
/**
* This method is invoked right before starting debuggee VM.
*/
protected void beforeDebuggeeStart() {
// Empty.
}
/**
* Opens JDWP connection with debuggee (doesn't run debuggee and doesn't
* establish synchronize connection).
*/
public void openConnection() {
debuggeeWrapper.openConnection();
logWriter.println("Opened transport connection");
debuggeeWrapper.vmMirror.adjustTypeLength();
logWriter.println("Adjusted VM-dependent type lengths");
}
/**
* Closes JDWP connection with debuggee (doesn't terminate debuggee and
* doesn't stop synchronize connection).
*/
public void closeConnection() {
if (debuggeeWrapper != null) {
debuggeeWrapper.disposeConnection();
try {
debuggeeWrapper.vmMirror.closeConnection();
} catch (Exception e) {
throw new TestErrorException(e);
}
logWriter.println("Closed transport connection");
}
}
/**
* Helper that returns reference type signature of input object ID.
*
* @param objectID -
* debuggee object ID
* @return object signature of reference type
*/
protected String getObjectSignature(long objectID) {
long classID = getObjectReferenceType(objectID);
return getClassSignature(classID);
}
/**
* Helper that returns reference type ID for input object ID.
*
* @param objectID -
* debuggee object ID
* @return reference type ID
*/
protected long getObjectReferenceType(long objectID) {
CommandPacket command = new CommandPacket(
JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
command.setNextValueAsReferenceTypeID(objectID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
checkReplyPacket(reply, "ObjectReference::ReferenceType command");
// byte refTypeTag =
reply.getNextValueAsByte();
long objectRefTypeID = reply.getNextValueAsReferenceTypeID();
return objectRefTypeID;
}
/**
* Helper for getting method ID of corresponding class and method name.
*
* @param classID -
* class ID
* @param methodName -
* method name
* @return method ID
*/
protected long getMethodID(long classID, String methodName) {
CommandPacket command = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
command.setNextValueAsClassID(classID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
checkReplyPacket(reply, "ReferenceType::Methods command");
int methods = reply.getNextValueAsInt();
for (int i = 0; i < methods; i++) {
long methodID = reply.getNextValueAsMethodID();
String name = reply.getNextValueAsString(); // method name
reply.getNextValueAsString(); // method signature
reply.getNextValueAsInt(); // method modifiers
if (name.equals(methodName)) {
return methodID;
}
}
return -1;
}
/**
* Helper for getting method ID of corresponding class, method name and signature.
*
* @param classID -
* class ID
* @param methodName -
* method name
* @param methodSignature -
* method signature
* @return method ID
*/
protected long getMethodID(long classID, String methodName, String methodSignature) {
CommandPacket command = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
command.setNextValueAsClassID(classID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
checkReplyPacket(reply, "ReferenceType::Methods command");
int methods = reply.getNextValueAsInt();
for (int i = 0; i < methods; i++) {
long methodID = reply.getNextValueAsMethodID();
String name = reply.getNextValueAsString(); // method name
String signature = reply.getNextValueAsString();
reply.getNextValueAsInt(); // method modifiers
if (name.equals(methodName) && signature.equals(methodSignature)) {
return methodID;
}
}
return -1;
}
/**
* Issues LineTable command.
*
* @param classID -
* class ID
* @param methodID -
* method ID
* @return reply packet
*/
protected ReplyPacket getLineTable(long classID, long methodID) {
CommandPacket lineTableCommand = new CommandPacket(
JDWPCommands.MethodCommandSet.CommandSetID,
JDWPCommands.MethodCommandSet.LineTableCommand);
lineTableCommand.setNextValueAsReferenceTypeID(classID);
lineTableCommand.setNextValueAsMethodID(methodID);
ReplyPacket lineTableReply = debuggeeWrapper.vmMirror
.performCommand(lineTableCommand);
checkReplyPacket(lineTableReply, "Method::LineTable command");
return lineTableReply;
}
/**
* Helper for getting method name of corresponding class and method ID.
*
* @param classID class id
* @param methodID method id
* @return String
*/
protected String getMethodName(long classID, long methodID) {
CommandPacket packet = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
packet.setNextValueAsClassID(classID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "ReferenceType::Methods command");
int methods = reply.getNextValueAsInt();
for (int i = 0; i < methods; i++) {
long mid = reply.getNextValueAsMethodID();
String name = reply.getNextValueAsString();
reply.getNextValueAsString();
reply.getNextValueAsInt();
if (mid == methodID) {
return name;
}
}
return "unknown";
}
/**
* Returns jni signature for selected classID
*
* @param classID
* @return jni signature for selected classID
*/
protected String getClassSignature(long classID) {
CommandPacket command = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
command.setNextValueAsReferenceTypeID(classID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
checkReplyPacket(reply, "ReferenceType::Signature command");
String signature = reply.getNextValueAsString();
return signature;
}
/**
* Returns classID for the selected jni signature
*
* @param signature
* @return classID for the selected jni signature
*/
protected long getClassIDBySignature(String signature) {
logWriter.println("=> Getting reference type ID for class: "
+ signature);
CommandPacket packet = new CommandPacket(
JDWPCommands.VirtualMachineCommandSet.CommandSetID,
JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
packet.setNextValueAsString(signature);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command");
int classes = reply.getNextValueAsInt();
logWriter.println("=> Returned number of classes: " + classes);
long classID = 0;
for (int i = 0; i < classes; i++) {
reply.getNextValueAsByte();
classID = reply.getNextValueAsReferenceTypeID();
reply.getNextValueAsInt();
// we need the only class, even if there were multiply ones
break;
}
assertTrue(
"VirtualMachine::ClassesBySignature command returned invalid classID:<"
+ classID + "> for signature " + signature, classID > 0);
return classID;
}
/**
* Returns reference type ID.
*
* @param signature
* @return type ID for the selected jni signature
*/
protected long getReferenceTypeID(String signature) {
CommandPacket packet = new CommandPacket(
JDWPCommands.VirtualMachineCommandSet.CommandSetID,
JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
packet.setNextValueAsString(signature);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command");
int classes = reply.getNextValueAsInt();
// this class may be loaded only once
assertEquals("Invalid number of classes for reference type: "
+ signature + ",", 1, classes);
byte refTypeTag = reply.getNextValueAsByte();
long classID = reply.getNextValueAsReferenceTypeID();
int status = reply.getNextValueAsInt();
logWriter.println("VirtualMachine.ClassesBySignature: classes="
+ classes + " refTypeTag=" + refTypeTag + " typeID= " + classID
+ " status=" + status);
assertAllDataRead(reply);
assertEquals("", JDWPConstants.TypeTag.CLASS, refTypeTag);
return classID;
}
/**
* Helper function for resuming debuggee.
*/
protected void resumeDebuggee() {
logWriter.println("=> Resume debuggee");
CommandPacket packet = new CommandPacket(
JDWPCommands.VirtualMachineCommandSet.CommandSetID,
JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
logWriter.println("Sending VirtualMachine::Resume command...");
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "VirtualMachine::Resume command");
assertAllDataRead(reply);
}
/**
* Performs string creation in debuggee.
*
* @param value -
* content for new string
* @return StringID of new created string
*/
protected long createString(String value) {
CommandPacket packet = new CommandPacket(
JDWPCommands.VirtualMachineCommandSet.CommandSetID,
JDWPCommands.VirtualMachineCommandSet.CreateStringCommand);
packet.setNextValueAsString(value);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "VirtualMachine::CreateString command");
long stringID = reply.getNextValueAsStringID();
return stringID;
}
/**
* Returns corresponding string from string ID.
*
* @param stringID -
* string ID
* @return string value
*/
protected String getStringValue(long stringID) {
CommandPacket packet = new CommandPacket(
JDWPCommands.StringReferenceCommandSet.CommandSetID,
JDWPCommands.StringReferenceCommandSet.ValueCommand);
packet.setNextValueAsObjectID(stringID);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "StringReference::Value command");
String returnedTestString = reply.getNextValueAsString();
return returnedTestString;
}
/**
* Multiple field verification routine.
*
* @param refTypeID -
* reference type ID
* @param checkedFieldNames -
* list of field names to be checked
* @return list of field IDs
*/
protected long[] checkFields(long refTypeID, String checkedFieldNames[]) {
return checkFields(refTypeID, checkedFieldNames, null, null);
}
/**
* Single field verification routine.
*
* @param refTypeID -
* reference type ID
* @param fieldName -
* name of single field
* @return filed ID
*/
protected long checkField(long refTypeID, String fieldName) {
return checkFields(refTypeID, new String[] { fieldName }, null, null)[0];
}
/**
* Multiple field verification routine.
*
* @param refTypeID -
* reference type ID
* @param checkedFieldNames -
* list of field names to be checked
* @param expectedSignatures -
* list of expected field signatures
* @param expectedModifiers -
* list of expected field modifiers
* @return list of field IDs
*/
protected long[] checkFields(long refTypeID, String checkedFieldNames[],
String expectedSignatures[], int expectedModifiers[]) {
boolean checkedFieldFound[] = new boolean[checkedFieldNames.length];
long checkedFieldIDs[] = new long[checkedFieldNames.length];
logWriter
.println("=> Send ReferenceType::Fields command and get field ID(s)");
CommandPacket fieldsCommand = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
fieldsCommand.setNextValueAsReferenceTypeID(refTypeID);
ReplyPacket fieldsReply = debuggeeWrapper.vmMirror
.performCommand(fieldsCommand);
fieldsCommand = null;
checkReplyPacket(fieldsReply, "ReferenceType::Fields command");
int returnedFieldsNumber = fieldsReply.getNextValueAsInt();
logWriter
.println("=> Returned fields number = " + returnedFieldsNumber);
int checkedFieldsNumber = checkedFieldNames.length;
final int fieldSyntheticFlag = 0xf0000000;
int nameDuplicated = 0;
String fieldNameDuplicated = null; // <= collects all duplicated fields
int nameMissing = 0;
String fieldNameMissing = null; // <= collects all missed fields
for (int i = 0; i < returnedFieldsNumber; i++) {
long returnedFieldID = fieldsReply.getNextValueAsFieldID();
String returnedFieldName = fieldsReply.getNextValueAsString();
String returnedFieldSignature = fieldsReply.getNextValueAsString();
int returnedFieldModifiers = fieldsReply.getNextValueAsInt();
logWriter.println("");
logWriter.println("=> Field ID: " + returnedFieldID);
logWriter.println("=> Field name: " + returnedFieldName);
logWriter.println("=> Field signature: " + returnedFieldSignature);
logWriter.println("=> Field modifiers: 0x"
+ Integer.toHexString(returnedFieldModifiers));
if ((returnedFieldModifiers & fieldSyntheticFlag) == fieldSyntheticFlag) {
continue; // do not check synthetic fields
}
for (int k = 0; k < checkedFieldsNumber; k++) {
if (!checkedFieldNames[k].equals(returnedFieldName)) {
continue;
}
if (checkedFieldFound[k]) {
logWriter.println("");
logWriter
.println("## FAILURE: The field is found repeatedly in the list");
logWriter.println("## Field Name: " + returnedFieldName);
logWriter.println("## Field ID: " + returnedFieldID);
logWriter.println("## Field Signature: "
+ returnedFieldSignature);
logWriter.println("## Field Modifiers: 0x"
+ Integer.toHexString(returnedFieldModifiers));
fieldNameDuplicated = (0 == nameDuplicated ? returnedFieldName
: fieldNameDuplicated + "," + returnedFieldName);
nameDuplicated++;
break;
}
checkedFieldFound[k] = true;
checkedFieldIDs[k] = returnedFieldID;
if (null != expectedSignatures) {
assertString(
"Invalid field signature is returned for field:"
+ returnedFieldName + ",",
expectedSignatures[k], returnedFieldSignature);
}
if (null != expectedModifiers) {
assertEquals(
"Invalid field modifiers are returned for field:"
+ returnedFieldName + ",",
expectedModifiers[k], returnedFieldModifiers);
}
break;
}
}
for (int k = 0; k < checkedFieldsNumber; k++) {
if (!checkedFieldFound[k]) {
logWriter.println("");
logWriter
.println("\n## FAILURE: Expected field is NOT found in the list of retuned fields:");
logWriter.println("## Field name = " + checkedFieldNames[k]);
fieldNameMissing = 0 == nameMissing ? checkedFieldNames[k]
: fieldNameMissing + "," + checkedFieldNames[k];
nameMissing++;
// break;
}
}
// String thisTestName = this.getClass().getName();
// logWriter.println("==> " + thisTestName + " for " + thisCommandName +
// ": FAILED");
if (nameDuplicated > 1) {
fail("Duplicated fields are found in the retuned by FieldsCommand list: "
+ fieldNameDuplicated);
}
if (nameDuplicated > 0) {
fail("Duplicated field is found in the retuned by FieldsCommand list: "
+ fieldNameDuplicated);
}
if (nameMissing > 1) {
fail("Expected fields are NOT found in the retuned by FieldsCommand list: "
+ fieldNameMissing);
}
if (nameMissing > 0) {
fail("Expected field is NOT found in the retuned by FieldsCommand list: "
+ fieldNameMissing);
}
logWriter.println("");
if (1 == checkedFieldsNumber) {
logWriter
.println("=> Expected field was found and field ID was got");
} else {
logWriter
.println("=> Expected fields were found and field IDs were got");
}
assertAllDataRead(fieldsReply);
return checkedFieldIDs;
}
/**
* Checks thread status and suspend status of a thread
*
* @param eventThreadID
* the thread ID to check
* @param expectedThreadStatus
* the expected thread status
* @param expectedSuspendStatus
* the expected suspend status
*/
protected void checkThreadState(long eventThreadID, byte expectedThreadStatus,
byte expectedSuspendStatus) {
CommandPacket commandPacket = new CommandPacket(
JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
commandPacket.setNextValueAsThreadID(eventThreadID);
ReplyPacket replyPacket = debuggeeWrapper.vmMirror.performCommand(commandPacket);
debuggeeWrapper.vmMirror.checkReply(replyPacket);
int threadStatus = replyPacket.getNextValueAsInt();
int suspendStatus = replyPacket.getNextValueAsInt();
assertAllDataRead(replyPacket);
assertEquals("Invalid thread status", threadStatus, expectedThreadStatus,
JDWPConstants.ThreadStatus.getName(expectedThreadStatus),
JDWPConstants.ThreadStatus.getName(threadStatus));
assertEquals("Invalid suspend status", suspendStatus, expectedSuspendStatus,
JDWPConstants.SuspendStatus.getName(expectedSuspendStatus),
JDWPConstants.SuspendStatus.getName(suspendStatus));
}
/**
* Helper for checking reply packet error code. Calls junit fail if packet
* error code does not equal to expected error code.
*
* @param reply -
* returned from debuggee packet
* @param message -
* additional message
* @param errorCodeExpected -
* array of expected error codes
*/
protected void checkReplyPacket(ReplyPacket reply, String message,
int errorCodeExpected) {
checkReplyPacket(reply, message, new int[] { errorCodeExpected });
}
/**
* Helper for checking reply packet error code. Calls junit fail if packet
* error code does not equal NONE.
*
* @param reply -
* returned from debuggee packet
* @param message -
* additional message
*/
protected void checkReplyPacket(ReplyPacket reply, String message) {
checkReplyPacket(reply, message, JDWPConstants.Error.NONE);
}
/**
* Helper for checking reply packet error code. Calls junit fail if packet
* error code does not equal to expected error code.
*
* @param reply -
* returned from debuggee packet
* @param message -
* additional message
* @param expected -
* array of expected error codes
*/
protected void checkReplyPacket(ReplyPacket reply, String message,
int[] expected) {
checkReplyPacket(reply, message, expected, true /* failSign */);
}
/**
* Helper for checking reply packet error code. If reply packet does not
* have error - returns true. Otherwise does not call junit fail - simply
* prints error message and returns false. if packet error code does not
* equal NONE.
*
* @param reply -
* returned from debuggee packet
* @param message -
* additional message
* @return true if error is not found, or false otherwise
*/
protected boolean checkReplyPacketWithoutFail(ReplyPacket reply,
String message) {
return checkReplyPacket(reply, message,
new int[] { JDWPConstants.Error.NONE }, false /* failSign */);
}
/**
* Helper for checking reply packet error code. If reply packet does not
* have unexpected error - returns true. If reply packet has got unexpected
* error: If failSign param = true - calls junit fail. Otherwise prints
* message about error and returns false.
*
* @param reply -
* returned from debuggee packet
* @param message -
* additional message
* @param expected -
* array of expected error codes
* @param failSign -
* defines to call junit fail or not
* @return true if unexpected errors are not found, or false otherwise
*/
protected boolean checkReplyPacket(ReplyPacket reply, String message,
int[] expected, boolean failSign) {
// check reply code against expected
int errorCode = reply.getErrorCode();
for (int i = 0; i < expected.length; i++) {
if (reply.getErrorCode() == expected[i]) {
return true; // OK
}
}
// replay code validation failed
// start error message composition
if (null == message) {
message = "";
} else {
message = message + ", ";
}
// format error message
if (expected.length == 1 && JDWPConstants.Error.NONE == expected[0]) {
message = message + "Error Code:<" + errorCode + "("
+ JDWPConstants.Error.getName(errorCode) + ")>";
} else {
message = message + "Unexpected error code:<" + errorCode + "("
+ JDWPConstants.Error.getName(errorCode) + ")>"
+ ", Expected error code"
+ (expected.length == 1 ? ":" : "s:");
for (int i = 0; i < expected.length; i++) {
message = message + (i > 0 ? ",<" : "<") + expected[i] + "("
+ JDWPConstants.Error.getName(expected[i]) + ")>";
}
}
if (failSign) {
printErrorAndFail(message);
}
logWriter.printError(message);
return false;
}
/**
* Helper for comparison numbers and printing string equivalents.
*
* @param message -
* user message
* @param expected -
* expected value
* @param actual -
* actual value
* @param strExpected -
* string equivalent of expected value
* @param strActual -
* string equivalent of actual value
*/
protected void assertEquals(String message, long expected, long actual,
String strExpected, String strActual) {
if (expected == actual) {
return; // OK
}
if (null == message) {
message = "";
}
if (null == strExpected) {
strExpected = expected + "";
} else {
strExpected = expected + "(" + strExpected + ")";
}
if (null == strActual) {
strActual = actual + "";
} else {
strActual = actual + "(" + strActual + ")";
}
printErrorAndFail(message + " expected:<" + strExpected + "> but was:<"
+ strActual + ">");
}
/**
* Asserts that two strings are equal.
*
* @param message -
* user message
* @param expected -
* expected string
* @param actual -
* actual string
*/
protected void assertString(String message, String expected, String actual) {
if (null == expected) {
expected = "";
}
if (null == actual) {
actual = "";
}
if (expected.equals(actual)) {
return; // OK
}
printErrorAndFail(message + " expected:<" + expected + "> but was:<"
+ actual + ">");
}
/**
* Helper for checking reply packet data has been read.
*
* @param reply -
* reply packet from debuggee
*/
protected void assertAllDataRead(Packet reply) {
if (reply.isAllDataRead()) {
return; // OK
}
printErrorAndFail("Not all data has been read");
}
/**
* Asserts that two JDWP event kinds are equal.
*
* @param message
* user message
* @param expected
* expected event kind
* @param actual
* actual event kind
*/
protected void assertEventKindEquals(String message, byte expected, byte actual) {
if (expected != actual) {
StringBuilder builder = new StringBuilder(message);
builder.append(": expected ");
builder.append(expected);
builder.append(" (");
builder.append(JDWPConstants.EventKind.getName(expected));
builder.append(") but was ");
builder.append(actual);
builder.append(" (");
builder.append(JDWPConstants.EventKind.getName(actual));
builder.append(")");
printErrorAndFail(builder.toString());
}
}
/**
* Asserts that two JDWP tags are equal.
*
* @param message
* user message
* @param expected
* expected tag
* @param actual
* actual tag
*/
protected void assertTagEquals(String message, byte expected, byte actual) {
if (expected != actual) {
StringBuilder builder = new StringBuilder(message);
builder.append(": expected ");
builder.append(expected);
builder.append(" (");
builder.append(JDWPConstants.Tag.getName(expected));
builder.append(") but was ");
builder.append(actual);
builder.append(" (");
builder.append(JDWPConstants.Tag.getName(actual));
builder.append(")");
printErrorAndFail(builder.toString());
}
}
/**
* Prints error message in log writer and in junit fail.
*
* @param message -
* error message
*/
protected void printErrorAndFail(String message) {
logWriter.printError(message);
fail(message);
}
/**
* Helper for setting static int field in class with new value.
*
* @param classSignature -
* String defining signature of class
* @param fieldName -
* String defining field name in specified class
* @param newValue -
* int value to set for specified field
* @return true, if setting is successfully, or false otherwise
*/
protected boolean setStaticIntField(String classSignature,
String fieldName, int newValue) {
long classID = debuggeeWrapper.vmMirror.getClassID(classSignature);
if (classID == -1) {
logWriter
.println("## setStaticIntField(): Can NOT get classID for class signature = '"
+ classSignature + "'");
return false;
}
long fieldID = debuggeeWrapper.vmMirror.getFieldID(classID, fieldName);
if (fieldID == -1) {
logWriter
.println("## setStaticIntField(): Can NOT get fieldID for field = '"
+ fieldName + "'");
return false;
}
CommandPacket packet = new CommandPacket(
JDWPCommands.ClassTypeCommandSet.CommandSetID,
JDWPCommands.ClassTypeCommandSet.SetValuesCommand);
packet.setNextValueAsReferenceTypeID(classID);
packet.setNextValueAsInt(1);
packet.setNextValueAsFieldID(fieldID);
packet.setNextValueAsInt(newValue);
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
int errorCode = reply.getErrorCode();
if (errorCode != JDWPConstants.Error.NONE) {
logWriter
.println("## setStaticIntField(): Can NOT set value for field = '"
+ fieldName
+ "' in class = '"
+ classSignature
+ "'; ClassType.SetValues command reurns error = "
+ errorCode);
return false;
}
return true;
}
/**
* Removes breakpoint of the given event kind corresponding to the given
* request id.
*
* @param eventKind
* request event kind
* @param requestID
* request id
* @param verbose
* print or don't extra log info
*/
protected void clearEvent(byte eventKind, int requestID, boolean verbose) {
CommandPacket packet = new CommandPacket(
JDWPCommands.EventRequestCommandSet.CommandSetID,
JDWPCommands.EventRequestCommandSet.ClearCommand);
packet.setNextValueAsByte(eventKind);
packet.setNextValueAsInt(requestID);
if (verbose) {
logWriter.println("Clearing event: "
+ JDWPConstants.EventKind.getName(eventKind) + ", id: "
+ requestID);
}
ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
checkReplyPacket(reply, "EventRequest::Clear command");
assertAllDataRead(reply);
}
}