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