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.ThreadReference;
20
21import org.apache.harmony.jpda.tests.framework.TestErrorException;
22import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
23import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
24import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
25import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
26import org.apache.harmony.jpda.tests.framework.jdwp.Value;
27import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.Tag;
28import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
29import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
30
31/**
32 * JDWP Unit test for ThreadReference.ForceEarlyReturn command.
33 */
34public class ForceEarlyReturnTest extends JDWPSyncTestCase {
35
36    static final String thisCommandName = "ThreadReference.ForceEarlyReturn command ";
37
38    static String thisTestName;
39
40    static String testThreadName;
41
42    static final int EXPECTED_INT = 5;
43
44    static final short EXPECTED_SHORT = 20;
45
46    static final char EXPECTED_CHAR = 'A';
47
48    static final byte EXPECTED_BYTE = 30;
49
50    static final boolean EXPECTED_BOOLEAN = true;
51
52    static Value expectedValue;
53
54    static final String debuggeeSignature = "Lorg/apache/harmony/jpda/tests/jdwp/ThreadReference/ForceEarlyReturnDebuggee;";
55
56    protected String getDebuggeeClassName() {
57        return "org.apache.harmony.jpda.tests.jdwp.ThreadReference.ForceEarlyReturnDebuggee";
58    }
59
60    // ForceEarlyReturn needs canForceEarlyReturn VM capability support
61    private boolean isCapability() {
62        // check capability, relevant for this test
63        logWriter.println("=> Check capability: canForceEarlyReturn");
64        debuggeeWrapper.vmMirror.capabilities();
65        boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canForceEarlyReturn;
66        return isCapability;
67    }
68
69    private String toString(Value value) {
70
71        switch (value.getTag()) {
72        case JDWPConstants.Tag.BOOLEAN_TAG:
73            return (new Boolean(value.getBooleanValue())).toString();
74        case JDWPConstants.Tag.BYTE_TAG:
75            return (new Byte(value.getByteValue())).toString();
76        case JDWPConstants.Tag.CHAR_TAG:
77            return (new Character(value.getCharValue())).toString();
78        case JDWPConstants.Tag.INT_TAG:
79            return (new Integer(value.getIntValue())).toString();
80        case JDWPConstants.Tag.SHORT_TAG:
81            return (new Short(value.getShortValue())).toString();
82        }
83        return "";
84    }
85
86    public void RunTestForceEarlyReturn() {
87        logWriter.println("==> " + thisTestName + " for " + thisCommandName
88                + ": START...");
89        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
90
91        if (!isCapability()) {
92            logWriter
93                    .println("##WARNING: this VM dosn't possess capability: canForceEarlyReturn");
94            return;
95        }
96        // Tell debuggee to start a thread
97        synchronizer.sendMessage(testThreadName);
98
99        // Wait until the func_Int is processing.
100        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
101
102        // Getting ID of the tested thread
103        logWriter.println("==> testedThreadName = " + testThreadName);
104        logWriter.println("==> Get testedThreadID...");
105        long testedThreadID = debuggeeWrapper.vmMirror
106                .getThreadID(testThreadName);
107        logWriter.println("==> Get testedThreadID is" + testedThreadID);
108
109        // Suspend the VM before perform command
110        logWriter.println("==> testedThreadID = " + testedThreadID);
111        logWriter.println("==> suspend testedThread...");
112        debuggeeWrapper.vmMirror.suspendThread(testedThreadID);
113
114        // Compose the ForceEarlyReturn command
115        CommandPacket forceEarlyReturnPacket = new CommandPacket(
116                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
117                JDWPCommands.ThreadReferenceCommandSet.ForceEarlyReturnCommand);
118        forceEarlyReturnPacket.setNextValueAsThreadID(testedThreadID);
119        forceEarlyReturnPacket.setNextValueAsValue(expectedValue);
120
121        // Perform the command
122        logWriter.println("==> Perform " + thisCommandName);
123        ReplyPacket forceEarlyReturnReply = debuggeeWrapper.vmMirror
124                .performCommand(forceEarlyReturnPacket);
125        forceEarlyReturnPacket = null;
126
127        checkReplyPacket(forceEarlyReturnReply,
128                "ThreadReference::ForceEarlyReturn command");
129
130        // Resume the thread
131        logWriter.println("==> testedThreadID = " + testedThreadID);
132        logWriter.println("==> resume testedThread...");
133        debuggeeWrapper.vmMirror.resumeThread(testedThreadID);
134
135        String actualValue = synchronizer.receiveMessage();
136        // Check the early returned value
137        if (!actualValue.equals(toString(expectedValue))) {
138            printErrorAndFail(thisCommandName
139                    + "returned value is not set by ForceEarlyReturn command"
140                    + " expected:<" + expectedValue.toString() + "> but was:<"
141                    + actualValue + ">");
142        }
143        logWriter
144                .println("==> CHECK: PASSED: returned value does set by ForceEarlyReturn command.");
145        logWriter.println("==> Returned value: " + actualValue);
146
147        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
148    }
149
150    /**
151     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
152     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
153     * name through which to start a specific thread. Then the test performs the
154     * ThreadReference.ForceEarlyReturn command for the tested thread and gets
155     * the returned value of the called method. The returned value should be
156     * equal to the value which is used in ForceEarlyReturn Command. In this
157     * testcase, an Int value is returned.
158     */
159    public void testForceEarlyReturn_ReturnInt() {
160        thisTestName = "testForceEarlyReturn_ReturnInt";
161        testThreadName = ForceEarlyReturnDebuggee.THREAD_INT;
162        expectedValue = new Value(EXPECTED_INT);
163        RunTestForceEarlyReturn();
164    }
165
166    /**
167     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
168     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
169     * name through which to start a specific thread. Then the test performs the
170     * ThreadReference.ForceEarlyReturn command for the tested thread and gets
171     * the returned value of the called method. The returned value should be
172     * equal to the value which is used in ForceEarlyReturn Command. In this
173     * testcase, an Short value is returned.
174     */
175    public void testForceEarlyReturn_ReturnShort() {
176        thisTestName = "testForceEarlyReturn_ReturnShort";
177        testThreadName = ForceEarlyReturnDebuggee.THREAD_SHORT;
178        expectedValue = new Value(EXPECTED_SHORT);
179        RunTestForceEarlyReturn();
180    }
181
182    /**
183     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
184     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
185     * name through which to start a specific thread. Then the test performs the
186     * ThreadReference.ForceEarlyReturn command for the tested thread and gets
187     * the returned value of the called method. The returned value should be
188     * equal to the value which is used in ForceEarlyReturn Command. In this
189     * testcase, an Byte value is returned.
190     */
191    public void testForceEarlyReturn_ReturnByte() {
192        thisTestName = "testForceEarlyReturn_ReturnByte";
193        testThreadName = ForceEarlyReturnDebuggee.THREAD_BYTE;
194        expectedValue = new Value(EXPECTED_BYTE);
195        RunTestForceEarlyReturn();
196    }
197
198    /**
199     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
200     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
201     * name through which to start a specific thread. Then the test performs the
202     * ThreadReference.ForceEarlyReturn command for the tested thread and gets
203     * the returned value of the called method. The returned value should be
204     * equal to the value which is used in ForceEarlyReturn Command. In this
205     * testcase, an Char value is returned.
206     */
207    public void testForceEarlyReturn_ReturnChar() {
208        thisTestName = "testForceEarlyReturn_ReturnChar";
209        testThreadName = ForceEarlyReturnDebuggee.THREAD_CHAR;
210        expectedValue = new Value(EXPECTED_CHAR);
211        RunTestForceEarlyReturn();
212    }
213
214    /**
215     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
216     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
217     * name through which to start a specific thread. Then the test performs the
218     * ThreadReference.ForceEarlyReturn command for the tested thread and gets
219     * the returned value of the called method. The returned value should be
220     * equal to the value which is used in ForceEarlyReturn Command. In this
221     * testcase, an Boolean value is returned.
222     */
223    public void testForceEarlyReturn_ReturnBoolean() {
224        thisTestName = "testForceEarlyReturn_ReturnBoolean";
225        testThreadName = ForceEarlyReturnDebuggee.THREAD_BOOLEAN;
226        expectedValue = new Value(EXPECTED_BOOLEAN);
227        RunTestForceEarlyReturn();
228    }
229
230    /**
231     * This testcase exercises ThreadReference.ForceEarlyReturn command. <BR>
232     * At first the test starts ForceEarlyReturnDebuggee and send it the thread
233     * name through which to start a specific thread. Then the test performs the
234     * ThreadReference.ForceEarlyReturn command for the tested thread without
235     * suspending the VM. In this testcase, THREAD_NOT_SUSPENDED exception is returned.
236     */
237    public void testForceEarlyReturn_NotSuspended() {
238        thisTestName = "testForceEarlyReturn_NotSuspended";
239        testThreadName = "test";
240        expectedValue = new Value(Tag.VOID_TAG, 0);
241
242        logWriter.println("==> " + thisTestName + " for " + thisCommandName
243                + ": START...");
244        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
245
246        if (!isCapability()) {
247            logWriter
248                    .println("##WARNING: this VM dosn't possess capability: canForceEarlyReturn");
249            return;
250        }
251        // Tell debuggee to start a thread
252        synchronizer.sendMessage(testThreadName);
253
254        // Wait thread signal.
255        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
256
257        // Getting ID of the tested thread
258        logWriter.println("==> testedThreadName = " + testThreadName);
259        logWriter.println("==> Get testedThreadID...");
260        long testedThreadID = debuggeeWrapper.vmMirror
261                .getThreadID(testThreadName);
262        logWriter.println("==> Get testedThreadID is" + testedThreadID);
263
264        // Compose the ForceEarlyReturn command
265        CommandPacket forceEarlyReturnPacket = new CommandPacket(
266                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
267                JDWPCommands.ThreadReferenceCommandSet.ForceEarlyReturnCommand);
268        forceEarlyReturnPacket.setNextValueAsThreadID(testedThreadID);
269        forceEarlyReturnPacket.setNextValueAsValue(expectedValue);
270
271        // Perform the command
272        logWriter.println("==> Perform " + thisCommandName);
273        ReplyPacket forceEarlyReturnReply = debuggeeWrapper.vmMirror
274                .performCommand(forceEarlyReturnPacket);
275        forceEarlyReturnPacket = null;
276
277        short errorCode = forceEarlyReturnReply.getErrorCode();
278        if (errorCode != JDWPConstants.Error.NONE) {
279            if (errorCode == JDWPConstants.Error.THREAD_NOT_SUSPENDED) {
280                logWriter
281                        .println("=> CHECK PASSED: Expected error (THREAD_NOT_SUSPENDED) is returned");
282                synchronizer.sendMessage("ThreadExit");
283                synchronizer
284                        .sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
285                return;
286            }
287        }
288        printErrorAndFail(thisCommandName
289                + " should throw exception when VM is not suspended.");
290
291    }
292}
293