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 Pavel N. Vyssotski
21 */
22
23// $Id: InvokeMethod002Test.java,v 1.4 2006/06/20 11:15:16 rscherba Exp $
24
25package org.apache.harmony.jpda.tests.jdwp.ClassType;
26
27import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
28import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
29import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
30import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
31import org.apache.harmony.jpda.tests.framework.jdwp.TaggedObject;
32import org.apache.harmony.jpda.tests.framework.jdwp.Value;
33import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
34import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
35
36
37/**
38 * JDWP unit test for ClassType.InvokeMethod command.
39 */
40public class InvokeMethod002Test extends JDWPSyncTestCase {
41    protected String getDebuggeeClassName() {
42        return "org.apache.harmony.jpda.tests.jdwp.share.debuggee.InvokeMethodDebuggee";
43    }
44
45    /**
46     * This testcase checks ClassType.InvokeMethod command.
47     * <BR>Checked method is
48     * <BR>public static String testMethod3(
49     *       int, int[], int[][], String, String[], String[][])
50     * <BR>of org.apache.harmony.jpda.tests.jdwp.share.debuggee.InvokeMethodDebuggee class.
51     * <BR> The testcase expects that returned value is not null object and returned
52     * exception object is null;
53     */
54    private void testInvokeMethod(boolean deliberately_screw_up_types) {
55        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
56
57        // Get referenceTypeID
58        CommandPacket packet = new CommandPacket(
59            JDWPCommands.VirtualMachineCommandSet.CommandSetID,
60            JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
61        String classSig = "Lorg/apache/harmony/jpda/tests/jdwp/share/debuggee/InvokeMethodDebuggee;";
62        packet.setNextValueAsString(classSig);
63
64        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
65        checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command");
66
67        int classes = reply.getNextValueAsInt();
68        assertEquals("VirtualMachine::ClassesBySignature returned invalid number of classes,",
69                1, classes); //this class may be loaded only once
70        byte refTypeTag = reply.getNextValueAsByte();
71        long classID = reply.getNextValueAsReferenceTypeID();
72        int status = reply.getNextValueAsInt();
73        assertAllDataRead(reply);
74        assertEquals("VirtualMachine::ClassesBySignature returned invalid TypeTag,",
75                JDWPConstants.TypeTag.CLASS, refTypeTag,
76                JDWPConstants.TypeTag.getName(JDWPConstants.TypeTag.CLASS),
77                JDWPConstants.TypeTag.getName(refTypeTag));
78
79        logWriter.println(" VirtualMachine.ClassesBySignature: classes="
80            + classes + " refTypeTag=" + refTypeTag + " classID= " + classID
81            + " status=" + status);
82
83        // Get methodID
84        packet = new CommandPacket(
85            JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
86            JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
87        packet.setNextValueAsClassID(classID);
88
89        reply = debuggeeWrapper.vmMirror.performCommand(packet);
90        checkReplyPacket(reply, "ReferenceType::Methods command");
91
92        int declared = reply.getNextValueAsInt();
93        logWriter.println(" ReferenceType.Methods: declared=" + declared);
94        long targetMethodID = 0;
95        for (int i = 0; i < declared; i++) {
96            long methodID = reply.getNextValueAsMethodID();
97            String name = reply.getNextValueAsString();
98            String signature = reply.getNextValueAsString();
99            int modBits = reply.getNextValueAsInt();
100            logWriter.println("  methodID=" + methodID + " name=" + name
101                + " signature=" + signature + " modBits=" + modBits);
102            if (name.equals("testMethod3")) {
103                targetMethodID = methodID;
104            }
105        }
106        assertAllDataRead(reply);
107
108        // Set EventRequest
109        packet = new CommandPacket(
110            JDWPCommands.EventRequestCommandSet.CommandSetID,
111            JDWPCommands.EventRequestCommandSet.SetCommand);
112        packet.setNextValueAsByte(JDWPConstants.EventKind.METHOD_ENTRY);
113        packet.setNextValueAsByte(JDWPConstants.SuspendPolicy.ALL);
114        packet.setNextValueAsInt(1);
115        packet.setNextValueAsByte((byte) 5);
116        packet.setNextValueAsString("*.InvokeMethodDebuggee");
117
118        reply = debuggeeWrapper.vmMirror.performCommand(packet);
119        checkReplyPacket(reply, "EventRequest::Set command");
120
121        int requestID = reply.getNextValueAsInt();
122        logWriter.println(" EventRequest.Set: requestID=" + requestID);
123        assertAllDataRead(reply);
124        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
125
126        long targetThreadID = 0;
127        // Wait event
128        CommandPacket event = debuggeeWrapper.vmMirror.receiveEvent();
129        byte suspendPolicy = event.getNextValueAsByte();
130        int events = event.getNextValueAsInt();
131        logWriter.println(" EVENT_THREAD event: suspendPolicy=" + suspendPolicy
132            + " events=" + events);
133        for (int i = 0; i < events; i++) {
134            byte eventKind = event.getNextValueAsByte();
135            int newRequestID = event.getNextValueAsInt();
136            long threadID = event.getNextValueAsThreadID();
137            //Location location =
138                event.getNextValueAsLocation();
139            logWriter.println("  EVENT_THREAD event " + i + ": eventKind="
140                + eventKind + " requestID=" + newRequestID + " threadID="
141                + threadID);
142            if (newRequestID == requestID) {
143                targetThreadID = threadID;
144            }
145        }
146        assertAllDataRead(event);
147        assertTrue("Invalid targetThreadID, must be != 0", targetThreadID != 0);
148
149        //  Let's clear event request
150        packet = new CommandPacket(
151            JDWPCommands.EventRequestCommandSet.CommandSetID,
152            JDWPCommands.EventRequestCommandSet.ClearCommand);
153        packet.setNextValueAsByte(JDWPConstants.EventKind.METHOD_ENTRY);
154        packet.setNextValueAsInt(requestID);
155
156        reply = debuggeeWrapper.vmMirror.performCommand(packet);
157        checkReplyPacket(reply, "EventRequest::Clear command");
158        assertAllDataRead(reply);
159
160        logWriter.println("Read values of fields to pass them as arguments:");
161        String fieldNames[] = {
162            "checkInt",
163            "checkIntArray",
164            "checkIntArray2",
165            "checkString",
166            "checkStringArray",
167            "checkStringArray2",
168            "checkClass",
169            "checkClassArray",
170            "checkClassArray2"
171        };
172        long[] fieldIDs = {0,0,0,0,0,0,0,0,0};
173        Value[] fieldValues = {null,null,null,null,null,null,null,null,null};
174
175        if (deliberately_screw_up_types) {
176            fieldNames[1] = "checkStringArray";
177            fieldNames[4] = "checkIntArray";
178        }
179
180        packet = new CommandPacket(
181            JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
182            JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
183        packet.setNextValueAsReferenceTypeID(classID);
184
185        reply = debuggeeWrapper.vmMirror.performCommand(packet);
186        checkReplyPacket(reply, "ReferenceType::Fields command");
187
188        int fieldsCount = reply.getNextValueAsInt();
189        assertTrue("Invalid fieldsCount=" + fieldsCount + ", must be >= " + fieldValues.length
190                , fieldsCount >= fieldValues.length);
191
192        for (int i = 0; i < fieldsCount; i++) {
193            long id = reply.getNextValueAsFieldID();
194            String name = reply.getNextValueAsString();
195            //String signature =
196                reply.getNextValueAsString();
197            //int modifiers =
198                reply.getNextValueAsInt();
199            for (int k = 0; k < fieldNames.length; k++) {
200                if (fieldNames[k].equals(name)) {
201                    fieldIDs[k] = id;
202                    logWriter.println("  name=" + name + ", ID=" + id);
203                    break;
204                }
205            }
206        }
207        assertAllDataRead(reply);
208
209        for (int i = 0; i < fieldIDs.length; i++) {
210            if (fieldIDs[i] == 0) {
211                logWriter.println(
212                    "ERROR: \"" + fieldNames[i] + "\" field not found");
213                fail("\"" + fieldNames[i] + "\" field not found");
214            }
215        }
216
217        packet = new CommandPacket(
218            JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
219            JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand);
220        packet.setNextValueAsReferenceTypeID(classID);
221        packet.setNextValueAsInt(fieldIDs.length);
222        for (int i = 0; i < fieldIDs.length; i++) {
223            packet.setNextValueAsFieldID(fieldIDs[i]);
224        }
225
226        reply = debuggeeWrapper.vmMirror.performCommand(packet);
227        checkReplyPacket(reply, "ReferenceType::GetValues command");
228
229        int valuesCount = reply.getNextValueAsInt();
230        for (int i = 0; i < valuesCount; i++) {
231            fieldValues[i] = reply.getNextValueAsValue();
232        }
233        assertAllDataRead(reply);
234
235        // Make InvokeMethod
236        packet = new CommandPacket(
237            JDWPCommands.ClassTypeCommandSet.CommandSetID,
238            JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand);
239        packet.setNextValueAsClassID(classID);
240        packet.setNextValueAsThreadID(targetThreadID);
241        packet.setNextValueAsMethodID(targetMethodID);
242        packet.setNextValueAsInt(fieldValues.length);
243        for (int i = 0; i < fieldValues.length; i++) {
244            packet.setNextValueAsValue(fieldValues[i]);
245        }
246        packet.setNextValueAsInt(0);
247        logWriter.println(" Send ClassType.InvokeMethod");
248        reply = debuggeeWrapper.vmMirror.performCommand(packet);
249
250        if (deliberately_screw_up_types) {
251            checkReplyPacket(reply, "ClassType::InvokeMethod command",
252                             JDWPConstants.Error.ILLEGAL_ARGUMENT);
253        } else {
254            checkReplyPacket(reply, "ClassType::InvokeMethod command");
255
256            Value returnValue = reply.getNextValueAsValue();
257            logWriter.println(" ClassType.InvokeMethod: returnValue=" + returnValue);
258
259            String returnedString = getStringValue(returnValue.getLongValue());
260            logWriter.println(" ClassType.InvokeMethod: returnedString=" + returnedString);
261            assertEquals("qwerty", returnedString);
262
263            TaggedObject exception = reply.getNextValueAsTaggedObject();
264            assertNotNull("ClassType::InvokeMethod returned null exception",
265                          exception);
266            assertEquals("ClassType::InvokeMethod returned invalid exception objectID,",
267                         0, exception.objectID);
268            assertEquals("ClassType::InvokeMethod returned invalid exception.tag",
269                         JDWPConstants.Tag.OBJECT_TAG, exception.tag,
270                         JDWPConstants.Tag.getName(JDWPConstants.Tag.OBJECT_TAG),
271                         JDWPConstants.Tag.getName(exception.tag));
272            logWriter.println(" ClassType.InvokeMethod: exception.tag=" + exception.tag +
273                              " exception.objectID=" + exception.objectID);
274        }
275
276        assertAllDataRead(reply);
277
278        //  Let's resume application
279        packet = new CommandPacket(
280            JDWPCommands.VirtualMachineCommandSet.CommandSetID,
281            JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
282        reply = debuggeeWrapper.vmMirror.performCommand(packet);
283        checkReplyPacket(reply, "VirtualMachine::Resume command");
284        assertAllDataRead(reply);
285
286        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
287    }
288
289    public void testInvokeMethod_right_argument_types() {
290        testInvokeMethod(false);
291    }
292
293    public void testInvokeMethod_wrong_argument_types() {
294        testInvokeMethod(true);
295    }
296}
297