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 Anatoly F. Bondarenko
21  */
22 
23 /**
24  * Created on 19.06.2006
25  */
26 package org.apache.harmony.jpda.tests.jdwp.ThreadReference;
27 
28 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.*;
29 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
30 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
31 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
32 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
33 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
34 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
35 
36 /**
37  * JDWP Unit test for ThreadReference.ThreadGroup command.
38  */
39 public class ThreadGroup002Test extends JDWPSyncTestCase {
40 
41     static final int testStatusPassed = 0;
42     static final int testStatusFailed = -1;
43     static final String debuggeeSignature =
44             "Lorg/apache/harmony/jpda/tests/jdwp/ThreadReference/ThreadGroup002Debuggee;";
45 
getDebuggeeClassName()46     protected String getDebuggeeClassName() {
47         return "org.apache.harmony.jpda.tests.jdwp.ThreadReference.ThreadGroup002Debuggee";
48     }
49 
50     /**
51      * This testcase exercises ThreadReference.ThreadGroup command.
52      * <BR>At first the test starts ThreadGroup002Debuggee which creates some thread
53      * groups and starts some tested threads which belong to different created thread groups.
54      * <BR>After the tested threads start, at first the test wait for the some first
55      * tested threads to finish.
56      * <BR> Then the test for every tested thread does:
57      * <BR>&nbsp;&nbsp; - performs ThreadReference.Status command;
58      * <BR>&nbsp;&nbsp; - performs the ThreadReference.ThreadGroup command;
59      * <BR>&nbsp;&nbsp; - performs the ThreadGroupReference.name command;
60      * <BR>It is expected that
61      * <BR>&nbsp;&nbsp; - all threads with status ZOMBIE are only finished tested threads;
62      * <BR>&nbsp;&nbsp; - all threads without status ZOMBIE are only NOT finished tested threads;
63      * <BR>&nbsp;&nbsp; - if status of thread is ZOMBIE then returned groupID must be null;
64      * <BR>&nbsp;&nbsp; - if status of thread is not ZOMBIE then returned groupID must not be null;
65      * <BR>&nbsp;&nbsp; - thread group name should be expected name for thread which is not ZOMBIE;
66      */
testThreadGroup002()67     public void testThreadGroup002() {
68         logWriter.println("==> testThreadGroup002: START...");
69         String debuggeeMessage = synchronizer.receiveMessage();
70         int testedThreadsNumber = 0;
71         try {
72             testedThreadsNumber = Integer.valueOf(debuggeeMessage).intValue();
73         } catch (NumberFormatException exception) {
74             logWriter.println
75                 ("## FAILURE: Exception while getting number of started threads from debuggee = " + exception);
76             synchronizer.sendMessage("FINISH");
77             printErrorAndFail("\n## Can NOT get number of started threads from debuggee! ");
78         }
79         testedThreadsNumber++; // to add debuggee main thread
80         logWriter.println("==>  Number of threads in debuggee to test = " + testedThreadsNumber);
81         String[] testedThreadsNames = new String[testedThreadsNumber];
82         String[] testedThreadGroupsNames = new String[testedThreadsNumber];
83         long[] testedThreadsIDs = new long[testedThreadsNumber];
84         String debuggeeMainThreadName = synchronizer.receiveMessage();
85         String debuggeeMainThreadGroupName = synchronizer.receiveMessage();
86         for (int i = 0; i < testedThreadsNumber; i++) {
87             if ( i < (testedThreadsNumber-1) ) {
88                 testedThreadsNames[i] = ThreadGroup002Debuggee.THREAD_NAME_PATTERN + i;
89                 testedThreadGroupsNames[i] = ThreadGroup002Debuggee.THREAD_GROUP_NAME_PATTERN + (i%2);
90             } else {
91                 testedThreadsNames[i] = debuggeeMainThreadName;
92                 testedThreadGroupsNames[i] = debuggeeMainThreadGroupName;
93             }
94             testedThreadsIDs[i] = 0;
95         }
96 
97         // getting ID of the tested thread
98         ReplyPacket allThreadIDReply = null;
99         try {
100             allThreadIDReply = debuggeeWrapper.vmMirror.getAllThreadID();
101         } catch (ReplyErrorCodeException exception) {
102             logWriter.println
103                 ("## FAILURE: Exception in vmMirror.getAllThreadID() = " + exception);
104             synchronizer.sendMessage("FINISH");
105             printErrorAndFail("\n## Can NOT get all ThreadID in debuggee! ");
106         }
107         int threads = allThreadIDReply.getNextValueAsInt();
108         logWriter.println("==>  Number of all threads in debuggee = " + threads);
109         for (int i = 0; i < threads; i++) {
110             long threadID = allThreadIDReply.getNextValueAsThreadID();
111             String threadName = null;
112             try {
113                 threadName = debuggeeWrapper.vmMirror.getThreadName(threadID);
114             } catch (ReplyErrorCodeException exception) {
115                 logWriter.println
116                     ("==> WARNING: Can NOT get thread name for threadID = " + threadID);
117                 continue;
118             }
119             int k = 0;
120             for (; k < testedThreadsNumber; k++) {
121                 if ( threadName.equals(testedThreadsNames[k]) ) {
122                     testedThreadsIDs[k] = threadID;
123                     break;
124                 }
125             }
126         }
127 
128         boolean testedThreadNotFound = false;
129         for (int i = 0; i < testedThreadsNumber; i++) {
130             if ( testedThreadsIDs[i] == 0 ) {
131                 logWriter.println("## FAILURE: Tested thread is not found out among debuggee threads!");
132                 logWriter.println("##          Thread name = " + testedThreadsNames[i]);
133                 testedThreadNotFound = true;
134             }
135         }
136         if ( testedThreadNotFound ) {
137             synchronizer.sendMessage("FINISH");
138             printErrorAndFail("\n## Some of tested threads are not found!");
139         }
140 
141         logWriter.println("==> Send signal to debuggee to continue and to finish some first threads...");
142         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
143 
144         logWriter.println("==> Wait signal from the debuggee that some first threads finished...");
145         String messageFromDebuggee = synchronizer.receiveMessageWithoutException("testThreadGroup002");
146         if ( ! JPDADebuggeeSynchronizer.SGNL_READY.equals(messageFromDebuggee) ) {
147             logWriter.println("## FAILURE: Could NOT receive expected signal from debuggee!");
148             printErrorAndFail("\n## Could NOT receive expected signal from debuggee! ");
149         }
150         int finishedTestedThreadsNumber = testedThreadsNumber/2;
151         logWriter.println
152         ("==> Number of debuggee's finished threads = " +  finishedTestedThreadsNumber);
153 
154         CommandPacket packet = null;
155         ReplyPacket reply = null;
156         String errorMessage = "";
157 
158         boolean statusCommandFailed = false;
159         boolean threadStatusFailed = false;
160         boolean groupIDFailed = false;
161         boolean threadGroupCommandFailed = false;
162         boolean groupNameFailed = false;
163 
164         logWriter.println
165         ("\n==> Check that ThreadReference.ThreadGroup command returns expected thread group for each tsted thread...");
166 
167         for (int threadCount = 0; threadCount < testedThreadsNumber; threadCount++) {
168             logWriter.println("\n==> Check for Thread: threadID = " + testedThreadsIDs[threadCount]
169                     + "; threadName = " + testedThreadsNames[threadCount]);
170             logWriter.println("==> Send ThreadReference.Status command...");
171             packet = new CommandPacket(
172                     JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
173                     JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
174             packet.setNextValueAsReferenceTypeID(testedThreadsIDs[threadCount]);
175             reply = debuggeeWrapper.vmMirror.performCommand(packet);
176             if ( ! checkReplyPacketWithoutFail(reply, "ThreadReference.Status command") ) {
177                 statusCommandFailed = true;
178                 continue;
179             }
180 
181             int threadStatus = reply.getNextValueAsInt();
182             //int suspendStatus =
183             reply.getNextValueAsInt();
184 
185             logWriter.println("==> thread status of checked thread = " + threadStatus + "("
186                     + JDWPConstants.ThreadStatus.getName(threadStatus) + ")");
187 
188             logWriter.println("==> Send ThreadReference.ThreadGroup command...");
189             packet = new CommandPacket(
190                     JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
191                     JDWPCommands.ThreadReferenceCommandSet.ThreadGroupCommand);
192             packet.setNextValueAsThreadID(testedThreadsIDs[threadCount]);
193 
194             reply = debuggeeWrapper.vmMirror.performCommand(packet);
195             if ( ! checkReplyPacketWithoutFail(reply, "ThreadReference.ThreadGroup command") ) {
196                 threadGroupCommandFailed = true;
197                 continue;
198             }
199 
200             long threadGroupID = reply.getNextValueAsThreadGroupID();
201             logWriter.println("==> thread groupID for checked thread = " + threadGroupID);
202             if (threadStatus == JDWPConstants.ThreadStatus.ZOMBIE) {
203                 if ( threadCount >= finishedTestedThreadsNumber ) {
204                     logWriter.println("## FAILURE: Unexpected status for checked thread!");
205                     logWriter.println("##          Thread witn number = " + threadCount +
206                             " should NOT be ZOMBIE!");
207                     threadStatusFailed = true;
208                     continue;
209                 }
210                 // according to JVMTI spec groupID is NULL if the thread has died
211                 if ( threadGroupID != 0 ) {
212                     logWriter.println("## FAILURE: Unexpected thread groupID for checked thread with status = ZOMBIE!");
213                     logWriter.println("##          Expected thread groupID = 0");
214                     groupIDFailed = true;
215                 }
216                 continue;
217             } else {
218                 if ( threadCount < finishedTestedThreadsNumber ) {
219                     logWriter.println("## FAILURE: Unexpected status for checked thread!");
220                     logWriter.println("##          Thread witn number = " + threadCount +
221                             " should be ZOMBIE!");
222                     threadStatusFailed = true;
223                     continue;
224                 }
225                 if ( threadGroupID == 0 ) {
226                     logWriter.println("## FAILURE: Unexpected thread groupID for checked thread with status != ZOMBIE!");
227                     logWriter.println("##          Expected thread groupID != 0");
228                     groupIDFailed = true;
229                     continue;
230                 }
231             }
232 
233             logWriter.println("==> Getting thread group name by ThreadGroupReference.Name command...");
234             packet = new CommandPacket(
235                     JDWPCommands.ThreadGroupReferenceCommandSet.CommandSetID,
236                     JDWPCommands.ThreadGroupReferenceCommandSet.NameCommand);
237             packet.setNextValueAsThreadID(threadGroupID);
238 
239             reply = debuggeeWrapper.vmMirror.performCommand(packet);
240             if ( ! checkReplyPacketWithoutFail(reply, "ThreadReference.ThreadGroup command") ) {
241                 threadGroupCommandFailed = true;
242                 continue;
243             }
244 
245             String threadGroupName = reply.getNextValueAsString();
246             logWriter.println("==> thread group name for checked thread = '" + threadGroupName + "'");
247 
248             if ( ! testedThreadGroupsNames[threadCount].equals(threadGroupName) ) {
249                 logWriter.println("## FAILURE: Unexpected thread group name for checked thread!");
250                 logWriter.println("##          Expected thread group name = '" +
251                         testedThreadGroupsNames[threadCount] + "'");
252                 groupNameFailed = true;
253             }
254         }
255 
256         if ( statusCommandFailed ) {
257             errorMessage = errorMessage +
258             "## Error found out while ThreadReference.Status command performing!\n";
259         }
260 
261         if ( threadStatusFailed ) {
262             errorMessage = errorMessage +
263             "## Unexpected thread status found out for some tested threads!\n";
264         }
265 
266         if ( groupIDFailed ) {
267             errorMessage = errorMessage +
268             "## Unexpected thread groupID found out for some tested threads!\n";
269         }
270 
271         if ( threadGroupCommandFailed ) {
272             errorMessage = errorMessage +
273             "## Error found out while ThreadReference.ThreadGroup command performing!\n";
274         }
275 
276         if ( groupNameFailed ) {
277             errorMessage = errorMessage +
278             "## Unexpected thread group name found out for some tested threads!\n";
279         }
280 
281         logWriter.println("==> Send signal to debuggee to finish...");
282         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
283 
284         if ( ! errorMessage.equals("") ) {
285             printErrorAndFail("\ntestThreadGroup002 FAILED:\n" + errorMessage);
286         }
287 
288         logWriter.println("\n==> testThreadGroup002 - OK!");
289     }
290 }
291