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
19package org.apache.harmony.jpda.tests.jdwp.ObjectReference;
20
21import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
22import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
23import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
24import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
25import org.apache.harmony.jpda.tests.framework.jdwp.TaggedObject;
26import org.apache.harmony.jpda.tests.framework.jdwp.Value;
27import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
28import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
29
30
31/**
32 * JDWP unit test for ObjectReference.InvokeMethod command.
33 */
34public class InvokeMethod003Test extends JDWPSyncTestCase {
35    protected String getDebuggeeClassName() {
36        return "org.apache.harmony.jpda.tests.jdwp.ObjectReference.InvokeMethod003Debuggee";
37    }
38
39    /**
40     * This testcase exercises ObjectReference.InvokeMethod command.
41     * <BR>The test first starts the debuggee, requests METHOD_ENTRY event so
42     * the application suspends on first invoke.
43     * <BR>Then sends ObjectReference.InvokeMethod command to invoke method
44     * Object.toString on an instance of a subclass of Object overriding the
45     * method toString.
46     * <BR>Checks that returned value is expected string value and returned
47     * exception object is null.
48     * <BR>Finally resumes the application.
49     */
50    public void testInvokeMethod_toString() {
51        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
52
53        // Get debuggee class ID.
54        String debuggeeClassSig = "Lorg/apache/harmony/jpda/tests/jdwp/ObjectReference/InvokeMethod003Debuggee;";
55        long debuggeeTypeID = debuggeeWrapper.vmMirror.getClassID(debuggeeClassSig);
56        assertTrue("Failed to find debuggee class", debuggeeTypeID != 0);
57
58        // Set METHOD_ENTRY event request so application is suspended.
59        CommandPacket packet = new CommandPacket(
60                JDWPCommands.EventRequestCommandSet.CommandSetID,
61                JDWPCommands.EventRequestCommandSet.SetCommand);
62        packet.setNextValueAsByte(JDWPConstants.EventKind.METHOD_ENTRY);
63        packet.setNextValueAsByte(JDWPConstants.SuspendPolicy.ALL);
64        packet.setNextValueAsInt(1);
65        packet.setNextValueAsByte((byte) 4);  // class-only modifier.
66        packet.setNextValueAsReferenceTypeID(debuggeeTypeID);
67        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
68        checkReplyPacket(reply, "EventRequest::Set command");
69
70        int requestID = reply.getNextValueAsInt();
71        logWriter.println(" EventRequest.Set: requestID=" + requestID);
72        assertAllDataRead(reply);
73        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
74
75        long targetThreadID = 0;
76        // Wait for METHOD_ENTRY event and collect event thread.
77        CommandPacket event = debuggeeWrapper.vmMirror.receiveEvent();
78        byte suspendPolicy = event.getNextValueAsByte();
79        int events = event.getNextValueAsInt();
80        logWriter.println(" EVENT_THREAD event: suspendPolicy=" + suspendPolicy + " events=" + events);
81        for (int i = 0; i < events; i++) {
82            byte eventKind = event.getNextValueAsByte();
83            int newRequestID = event.getNextValueAsInt();
84            long threadID = event.getNextValueAsThreadID();
85            //Location location =
86                event.getNextValueAsLocation();
87            logWriter.println("  EVENT_THREAD event " + i + ": eventKind="
88                    + eventKind + " requestID=" + newRequestID + " threadID="
89                    + threadID);
90            if (newRequestID == requestID) {
91                targetThreadID = threadID;
92            }
93        }
94        assertAllDataRead(event);
95        assertTrue("Invalid targetThreadID, must be != 0", targetThreadID != 0);
96
97        //  Now we're suspended, clear event request.
98        packet = new CommandPacket(
99                JDWPCommands.EventRequestCommandSet.CommandSetID,
100                JDWPCommands.EventRequestCommandSet.ClearCommand);
101        packet.setNextValueAsByte(JDWPConstants.EventKind.METHOD_ENTRY);
102        packet.setNextValueAsInt(requestID);
103        reply = debuggeeWrapper.vmMirror.performCommand(packet);
104        checkReplyPacket(reply, "EventRequest::Clear command");
105        assertAllDataRead(reply);
106
107        // Load value of the invoke's receiver.
108        long receiverFieldID = debuggeeWrapper.vmMirror.getFieldID(debuggeeTypeID, "invokeReceiver");
109        assertTrue("Failed to find receiver field", receiverFieldID != 0);
110
111        logWriter.println(" Send ReferenceType.GetValues");
112        packet = new CommandPacket(
113                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
114                JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand);
115        packet.setNextValueAsReferenceTypeID(debuggeeTypeID);
116        packet.setNextValueAsInt(1);  // looking for one field.
117        packet.setNextValueAsFieldID(receiverFieldID);  // the field we're looking for.
118        reply = debuggeeWrapper.vmMirror.performCommand(packet);
119        checkReplyPacket(reply, "ReferenceType::GetValues command");
120        int valuesCount = reply.getNextValueAsInt();  // number of field values.
121        Value fieldValue = reply.getNextValueAsValue();
122        assertAllDataRead(reply);
123        assertEquals("Not the right number of values", 1, valuesCount);
124        assertNotNull("Received null value", fieldValue);
125        assertEquals("Expected an object value", JDWPConstants.Tag.OBJECT_TAG, fieldValue.getTag());
126        long receiverObjectID = fieldValue.getLongValue();
127        assertTrue("Field is null", receiverObjectID != 0);
128
129        // Get test class ID.
130        String testClassSig = "Lorg/apache/harmony/jpda/tests/jdwp/ObjectReference/InvokeMethod003Debuggee$TestClass;";
131        long testTypeID = debuggeeWrapper.vmMirror.getClassID(testClassSig);
132        assertTrue("Failed to find test class", testTypeID != 0);
133
134        // Get java.lang.Object class ID.
135        long objectTypeID = debuggeeWrapper.vmMirror.getClassID("Ljava/lang/Object;");
136        assertTrue("Failed to find java.lang.Object class", objectTypeID != 0);
137
138        // Get java.lang.Object.toString method ID.
139        long targetMethodID = debuggeeWrapper.vmMirror.getMethodID(objectTypeID, "toString");
140        assertTrue("Failed to find method", targetMethodID != 0);
141
142        // Invoke method.
143        packet = new CommandPacket(
144                JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
145                JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand);
146        packet.setNextValueAsObjectID(receiverObjectID);
147        packet.setNextValueAsThreadID(targetThreadID);
148        packet.setNextValueAsClassID(testTypeID);  // TestClass type ID.
149        packet.setNextValueAsMethodID(targetMethodID);  // Object.toString method ID.
150        packet.setNextValueAsInt(0);  // no arguments.
151        packet.setNextValueAsInt(0);  // invoke options.
152        logWriter.println(" Send ObjectReference.InvokeMethod without Exception");
153        reply = debuggeeWrapper.vmMirror.performCommand(packet);
154        checkReplyPacket(reply, "ObjectReference::InvokeMethod command");
155
156        Value returnValue = reply.getNextValueAsValue();
157        assertNotNull("Returned value is null", returnValue);
158        assertEquals("Returned value tag is incorrect", JDWPConstants.Tag.STRING_TAG, returnValue.getTag());
159        long stringID = returnValue.getLongValue();
160        assertTrue("Returned string is null", stringID != 0);
161
162        String returnedString = debuggeeWrapper.vmMirror.getStringValue(stringID);
163        assertEquals("Invalid returned value,", "TestClass.toString()", returnedString);
164        logWriter.println(" ObjectReference.InvokeMethod: returnedString=\""
165                + returnedString + "\"");
166
167        TaggedObject exception = reply.getNextValueAsTaggedObject();
168        assertNotNull("Returned exception is null", exception);
169        assertTrue("Invalid exception object ID:<" + exception.objectID + ">", exception.objectID == 0);
170        assertEquals("Invalid exception tag,", JDWPConstants.Tag.OBJECT_TAG, exception.tag
171                , JDWPConstants.Tag.getName(JDWPConstants.Tag.OBJECT_TAG)
172                , JDWPConstants.Tag.getName(exception.tag));
173        logWriter.println(" ClassType.InvokeMethod: exception.tag="
174                + exception.tag + " exception.objectID=" + exception.objectID);
175        assertAllDataRead(reply);
176
177        //  Let's resume application
178        debuggeeWrapper.vmMirror.resume();
179
180        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
181    }
182}
183