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