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