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 package org.apache.harmony.jpda.tests.jdwp.ThreadReference;
20 
21 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
22 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
23 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
24 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
25 import org.apache.harmony.jpda.tests.framework.jdwp.TaggedObject;
26 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
27 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
28 
29 /**
30  * JDWP Unit test for ThreadReference.OwnedMonitorsStackDepthInfo command.
31  */
32 public class OwnedMonitorsStackDepthInfoTest extends JDWPSyncTestCase {
33 
34     static final String thisCommandName = "ThreadReference.OwnedMonitorsStackDepthInfo command ";
35 
getDebuggeeClassName()36     protected String getDebuggeeClassName() {
37         return "org.apache.harmony.jpda.tests.jdwp.ThreadReference.OwnedMonitorsStackDepthInfoDebuggee";
38     }
39 
40     // OwnedMonitorsStackDepthInfo needs canGetMonitorFrameInfo VM capability support
isCapability()41     private boolean isCapability() {
42         // check capability, relevant for this test
43         logWriter.println("=> Check capability: canGetMonitorFrameInfo");
44         debuggeeWrapper.vmMirror.capabilities();
45         boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canGetMonitorFrameInfo;
46         return isCapability;
47     }
48 
jdwpGetFrameCount(long threadID)49     private int jdwpGetFrameCount(long threadID) {
50       CommandPacket packet = new CommandPacket(JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
51                                                JDWPCommands.ThreadReferenceCommandSet.FrameCountCommand);
52       packet.setNextValueAsThreadID(threadID);
53 
54       ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
55       checkReplyPacket(reply, "ThreadReference::FrameCount command");
56       return reply.getNextValueAsInt();
57     }
58 
59     /**
60      * This testcase exercises ThreadReference.OwnedMonitorsStackDepthInfo
61      * command. <BR>
62      * At first the test starts OwnedMonitorsStackDepthInfoDebuggee which runs
63      * the tested thread 'TESTED_THREAD'. <BR>
64      * Then the test performs the ThreadReference.OwnedMonitorsStackDepthInfo
65      * command for the tested thread and gets list of monitor objects.
66      * The returned monitor objects are equal to expected count and their stack depth are
67      *  equal to expected depth. This test will perform MonitorInfo to guarrantee that returend
68      *  monitors do belong to the test thread.
69      */
testOwnedMonitorsStackDepthInfo()70     public void testOwnedMonitorsStackDepthInfo() {
71         String thisTestName = "testOwnedMonitorsStackDepthInfo";
72         logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START...");
73         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
74 
75         // Ensure we signal the debuggee to continue at the end of the test.
76         finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE;
77 
78         if (!isCapability()) {
79             logWriter.println("##WARNING: this VM dosn't possess capability: canGetMonitorFrameInfo");
80             return;
81         }
82 
83         // Getting ID of the tested thread
84         logWriter.println("==> testedThreadName = "
85                 + OwnedMonitorsStackDepthInfoDebuggee.TESTED_THREAD);
86         logWriter.println("==> Get testedThreadID...");
87         long testedThreadID = debuggeeWrapper.vmMirror
88                 .getThreadID(OwnedMonitorsStackDepthInfoDebuggee.TESTED_THREAD);
89 
90         // Compose the OwnedMonitorsStackDepthInfo command
91         CommandPacket stackDepthPacket = new CommandPacket(
92                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
93                 JDWPCommands.ThreadReferenceCommandSet.OwnedMonitorsStackDepthInfoCommand);
94         stackDepthPacket.setNextValueAsThreadID(testedThreadID);
95 
96         // Suspend the VM before perform command
97         logWriter.println("==> testedThreadID = " + testedThreadID);
98         logWriter.println("==> suspend testedThread...");
99         debuggeeWrapper.vmMirror.suspendThread(testedThreadID);
100 
101         // There are various monitors held in the outermost frames, but there may be
102         // implementation-specific locks held below that (since the thread will actually be
103         // suspended somewhere in I/O code). See OwnedMonitorsStackDepthInfoDebuggee.run().
104         int frameCount = jdwpGetFrameCount(testedThreadID);
105         int expectedMonitorCount = 3;
106         int[] expectedStackDepth = new int[] { frameCount - 4, frameCount - 4, frameCount - 2 };
107 
108         // Perform the command and attain the reply package
109         ReplyPacket stackDepthReply = debuggeeWrapper.vmMirror.performCommand(stackDepthPacket);
110         checkReplyPacket(stackDepthReply, "ThreadReference::OwnedMonitorsStackDepthInfo command");
111 
112         // Analyze the reply package
113         int actualMonitorCount = stackDepthReply.getNextValueAsInt();
114         logWriter.println("==> Owned monitors: " + actualMonitorCount);
115         assertTrue(actualMonitorCount >= expectedMonitorCount);
116         logWriter.println("==> CHECK: PASSED: actualMonitorCount >= expectedMonitorCount");
117 
118         int currentMonitor = 0;
119         for (int i = 0; i < actualMonitorCount; ++i) {
120             // Attain monitor object ID
121             TaggedObject monitorObject = stackDepthReply.getNextValueAsTaggedObject();
122 
123             // Attain monitor stack depth
124             int actualStackDepth = stackDepthReply.getNextValueAsInt();
125             logWriter.println("==> Stack depth: " + actualStackDepth);
126             if (expectedStackDepth[currentMonitor] != actualStackDepth) {
127                 continue;
128             }
129 
130             /*
131              *  Test the returned monitor object does belong to the test thread by MonitorInfo Command
132              */
133             // Compose the MonitorInfo Command
134             CommandPacket monitorInfoPacket = new CommandPacket(
135                     JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
136                     JDWPCommands.ObjectReferenceCommandSet.MonitorInfoCommand);
137             monitorInfoPacket.setNextValueAsObjectID(monitorObject.objectID);
138 
139             // Perform the command and attain the reply package
140             ReplyPacket monitorInfoReply = debuggeeWrapper.vmMirror.performCommand(monitorInfoPacket);
141             checkReplyPacket(monitorInfoReply, "ObjectReference::MonitorInfo command");
142 
143             // Attain thread id from monitor info
144             long ownerThreadID = monitorInfoReply.getNextValueAsThreadID();
145             assertEquals(thisCommandName + "returned monitor is not owned by test thread", ownerThreadID, testedThreadID, null, null);
146 
147             logWriter.println("==> CHECK: PASSED: returned monitor does belong to the test thread.");
148             logWriter.println("==> Monitor owner thread ID: " + ownerThreadID);
149 
150             ++currentMonitor;
151         }
152 
153         assertAllDataRead(stackDepthReply);
154     }
155 
156 
testOwnedMonitorsStackDepthInfo_Unsuspended()157     public void testOwnedMonitorsStackDepthInfo_Unsuspended() {
158         String thisTestName = "testOwnedMonitorsStackDepthInfo";
159         logWriter.println("==> " + thisTestName + " for " + thisCommandName
160                 + ": START...");
161         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
162 
163         // Ensure we signal the debuggee to continue at the end of the test.
164         finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE;
165 
166         if (!isCapability()) {
167             logWriter
168                     .println("##WARNING: this VM dosn't possess capability: OwnedMonitorsStackDepthInfo");
169             return;
170         }
171 
172         // Getting ID of the tested thread
173         logWriter.println("==> testedThreadName = "
174                 + OwnedMonitorsStackDepthInfoDebuggee.TESTED_THREAD);
175         logWriter.println("==> Get testedThreadID...");
176         long testedThreadID = debuggeeWrapper.vmMirror
177                 .getThreadID(OwnedMonitorsStackDepthInfoDebuggee.TESTED_THREAD);
178 
179         // Compose the OwnedMonitorsStackDepthInfo command
180         CommandPacket stackDepthPacket = new CommandPacket(
181                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
182                 JDWPCommands.ThreadReferenceCommandSet.OwnedMonitorsStackDepthInfoCommand);
183         stackDepthPacket.setNextValueAsThreadID(testedThreadID);
184 
185         // Perform the command and attain the reply package
186         ReplyPacket checkedReply = debuggeeWrapper.vmMirror
187                 .performCommand(stackDepthPacket);
188         short errorCode = checkedReply.getErrorCode();
189         if (errorCode != JDWPConstants.Error.NONE) {
190             if (errorCode == JDWPConstants.Error.THREAD_NOT_SUSPENDED) {
191                 logWriter.println("=> CHECK PASSED: Expected error (THREAD_NOT_SUSPENDED) is returned");
192                 return;
193             }
194         }
195         printErrorAndFail(thisCommandName + " should throw exception when VM is not suspended.");
196     }
197 }
198