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