1 /*
2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.jdi.ThreadGroupReference.suspend;
25 
26 import nsk.share.*;
27 import nsk.share.jpda.*;
28 import nsk.share.jdi.*;
29 
30 import com.sun.jdi.*;
31 import java.util.*;
32 import java.io.*;
33 
34 /**
35  * The test for the implementation of an object of the type     <BR>
36  * ThreadGroupReference.                                        <BR>
37  *                                                              <BR>
38  * The test checks up that results of the method                <BR>
39  * <code>com.sun.jdi.ThreadGroupReference.suspend()</code>      <BR>
40  * complies with its spec.                                      <BR>
41  * <BR>
42  * The case for testing includes four ThreadGroup objects defined       <BR>
43  * in a debuggee and their mirrors in a debugger.                       <BR>
44  * Parenthood relationships between the objects are as follows:         <BR>
45  *    threadGroups 2&3 are subgroups of threadGroup1                    <BR>
46  *    threadGroup4 is a subgroup of threadGroup3                        <BR>
47  * The objects are created together with three threads, Thread 2,3,4,   <BR>
48  * belonging to the corresponding subgroups.                            <BR>
49  * The test works as follows. After being started up,                   <BR>                                            <BR>
50  * the debuggee creates a 'lockingObject' for synchronizing threads,    <BR>
51  * enters a synchronized block in which it creates the threads,         <BR>
52  * informs the debugger of the threads creation,                        <BR>
53  * and is waiting for reply.                                            <BR>
54  * Since the threads use the same locking object in their 'run' methods <BR>
55  * they are locked up until main thread leaves the synchronized block.  <BR>
56  * Upon the receiption a message from the debuggee,                     <BR>
57  * the debugger gets mirrors of threadGroups and checks up that:        <BR>
58  *  - group4.suspend(); suspends only Thread4;                          <BR>
59  *  - group3.suspend(); suspends Thread3 and Thread4;                   <BR>
60  *  - group2.suspend(); suspends only Thread2;                          <BR>
61  *  - group1.suspend(); suspends Thread2, Thread3 and Thread4.          <BR>
62  */
63 
64 public class suspend001 {
65 
66     //----------------------------------------------------- templete section
67     static final int PASSED = 0;
68     static final int FAILED = 2;
69     static final int PASS_BASE = 95;
70 
71     //----------------------------------------------------- templete parameters
72     static final String
73     sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/suspend/suspend001  ",
74     sHeader2 = "--> debugger: ",
75     sHeader3 = "##> debugger: ";
76 
77     //----------------------------------------------------- main method
78 
main(String argv[])79     public static void main (String argv[]) {
80         int result = run(argv, System.out);
81         System.exit(result + PASS_BASE);
82     }
83 
run(String argv[], PrintStream out)84     public static int run (String argv[], PrintStream out) {
85         return new suspend001().runThis(argv, out);
86     }
87 
88     //--------------------------------------------------   log procedures
89 
90     private static Log  logHandler;
91 
log1(String message)92     private static void log1(String message) {
93         logHandler.display(sHeader1 + message);
94     }
log2(String message)95     private static void log2(String message) {
96         logHandler.display(sHeader2 + message);
97     }
log3(String message)98     private static void log3(String message) {
99         logHandler.complain(sHeader3 + message);
100     }
101 
102     //  ************************************************    test parameters
103 
104     private String debuggeeName =
105         "nsk.jdi.ThreadGroupReference.suspend.suspend001a";
106 
107     private String testedClassName =
108         "nsk.jdi.ThreadGroupReference.suspend.Threadsuspend001a";
109 
110     //String mName = "nsk.jdi.ThreadGroupReference.suspend";
111 
112     //====================================================== test program
113     //------------------------------------------------------ common section
114 
115     static ArgumentHandler      argsHandler;
116 
117     static int waitTime;
118 
119     static VirtualMachine      vm  = null;
120 
121     ReferenceType     testedclass  = null;
122     ThreadReference   thread2      = null;
123     ThreadReference   mainThread   = null;
124 
125     static int  testExitCode = PASSED;
126 
127     static final int returnCode0 = 0;
128     static final int returnCode1 = 1;
129     static final int returnCode2 = 2;
130     static final int returnCode3 = 3;
131     static final int returnCode4 = 4;
132 
133     //------------------------------------------------------ methods
134 
runThis(String argv[], PrintStream out)135     private int runThis (String argv[], PrintStream out) {
136 
137         Debugee debuggee;
138 
139         argsHandler     = new ArgumentHandler(argv);
140         logHandler      = new Log(out, argsHandler);
141         Binder binder   = new Binder(argsHandler, logHandler);
142 
143         if (argsHandler.verbose()) {
144             debuggee = binder.bindToDebugee(debuggeeName + " -vbs");
145         } else {
146             debuggee = binder.bindToDebugee(debuggeeName);
147         }
148 
149         waitTime = argsHandler.getWaitTime();
150 
151 
152         IOPipe pipe     = new IOPipe(debuggee);
153 
154         debuggee.redirectStderr(out);
155         log2("issuspended002a debuggee launched");
156         debuggee.resume();
157 
158         String line = pipe.readln();
159         if ((line == null) || !line.equals("ready")) {
160             log3("signal received is not 'ready' but: " + line);
161             return FAILED;
162         } else {
163             log2("'ready' recieved");
164         }
165 
166         vm = debuggee.VM();
167 
168     //------------------------------------------------------  testing section
169         log1("      TESTING BEGINS");
170 
171         for (int i = 0; ; i++) {
172 
173             pipe.println("newcheck");
174             line = pipe.readln();
175 
176             if (line.equals("checkend")) {
177                 log2("     : returned string is 'checkend'");
178                 break ;
179             } else if (!line.equals("checkready")) {
180                 log3("ERROR: returned string is not 'checkready'");
181                 testExitCode = FAILED;
182                 break ;
183             }
184 
185             log1("new checkready: #" + i);
186 
187             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part
188 
189             int expresult = returnCode0;
190 
191             List            classes      = null;
192 
193             ThreadGroupReference groups[] = { null, null, null, null };
194 
195             String groupNames [] = {  "threadGroup1Obj",
196                                       "threadGroup2Obj",
197                                       "threadGroup3Obj",
198                                       "threadGroup4Obj"  };
199 
200             List            threads;
201             ListIterator    iterator;
202             int             flag;
203             String          threadName;
204             ThreadReference thread;
205 
206             String threadNames [] = { "Thread2", "Thread3", "Thread4" };
207 
208             ReferenceType mainthreadClass = null;
209             ReferenceType thread2Class    = null;
210 
211             label0: {
212 
213                 log2("getting ThreadReference objects");
214                 try {
215                     classes         = vm.classesByName(testedClassName);
216                     thread2Class    = (ReferenceType) classes.get(0);
217                     classes         = vm.classesByName(debuggeeName);
218                     mainthreadClass = (ReferenceType) classes.get(0);
219                 } catch ( Exception e) {
220                     log3("ERROR: Exception at very beginning !? : " + e);
221                     expresult = returnCode1;
222                     break label0;
223                 }
224 
225                 log2("      getting a List of all threadGroups");
226                 for (int i1 = 0; i1 < 4; i1++) {
227                     groups[i1] = (ThreadGroupReference)
228                              mainthreadClass.getValue(mainthreadClass.fieldByName(groupNames[i1]));
229                 }
230 
231                 log2("      getting a List of all running threads");
232                 threads = vm.allThreads();
233 
234 
235                 log2("......checking up threads suspended with groups[3].suspend()");
236                 log2("         expected: 'Thread4'");
237                 groups[3].suspend();
238 
239                 iterator = threads.listIterator();
240                 flag = 0;
241                 for ( int i2 = 0; iterator.hasNext(); i2++ ) {
242                     thread = (ThreadReference) iterator.next();
243                     if (!thread.isSuspended())
244                         continue;
245                     threadName = thread.name();
246                     if (threadName.equals(threadNames[0]))
247                          flag |= 1;
248                     else if (threadName.equals(threadNames[1]))
249                          flag |= 2;
250                     else if (threadName.equals(threadNames[2]))
251                          flag |= 4;
252                     else flag |= 8;
253                 }
254                 if (flag != 4) {
255                     expresult = returnCode1;
256                     if (flag == 0)
257                         log3("ERROR: no threads suspunded");
258                     if ((flag & 4) == 0)
259                         log3("ERROR: 'Thread4' is not among suspended threads");
260                     if ((flag & 2) != 0)
261                         log3("ERROR: 'Thread3' is also suspended");
262                     if ((flag & 1) != 0)
263                         log3("ERROR: 'Thread2' is also suspended");
264                     if (flag >= 8)
265                         log3("ERROR: some extra thread(s) is also suspended");
266                 }
267                 vm.resume();
268 
269 
270                 log2("......checking up threads suspended with groups[2].suspend()");
271                 log2("         expected: 'Thread3' and 'Thread4'");
272                 groups[2].suspend();
273 
274                 iterator = threads.listIterator();
275                 flag = 0;
276                 for ( int i2 = 0; iterator.hasNext(); i2++ ) {
277                     thread = (ThreadReference) iterator.next();
278                     if (!thread.isSuspended())
279                         continue;
280                     threadName = thread.name();
281                     if (threadName.equals(threadNames[0]))
282                          flag |= 1;
283                     else if (threadName.equals(threadNames[1]))
284                          flag |= 2;
285                     else if (threadName.equals(threadNames[2]))
286                          flag |= 4;
287                     else flag |= 8;
288                 }
289                 if (flag != 6) {
290                     expresult = returnCode1;
291                     if (flag == 0)
292                         log3("ERROR: no threads suspunded");
293                     if ((flag & 4) == 0)
294                         log3("ERROR: 'Thread4' is not among suspended threads");
295                     if ((flag & 2) == 0)
296                         log3("ERROR: 'Thread3' is not among suspended threads");
297                     if ((flag & 1) != 0)
298                         log3("ERROR: 'Thread2' is also suspended");
299                     if (flag >= 8)
300                         log3("ERROR: some extra thread(s) is also suspended");
301                 }
302                 vm.resume();
303 
304 
305                 log2("......checking up threads suspended with groups[1].suspend()");
306                 log2("         expected: 'Thread2'");
307                 groups[1].suspend();
308 
309                 iterator = threads.listIterator();
310                 flag = 0;
311                 for ( int i2 = 0; iterator.hasNext(); i2++ ) {
312                     thread = (ThreadReference) iterator.next();
313                     if (!thread.isSuspended())
314                         continue;
315                     threadName = thread.name();
316                     if (threadName.equals(threadNames[0]))
317                          flag |= 1;
318                     else if (threadName.equals(threadNames[1]))
319                          flag |= 2;
320                     else if (threadName.equals(threadNames[2]))
321                          flag |= 4;
322                     else flag |= 8;
323                 }
324                 if (flag != 1) {
325                     expresult = returnCode1;
326                     if (flag == 0)
327                         log3("ERROR: no threads suspunded");
328                     if ((flag & 4) != 0)
329                         log3("ERROR: 'Thread4' is among suspended threads");
330                     if ((flag & 2) != 0)
331                         log3("ERROR: 'Thread3' is among suspended threads");
332                     if ((flag & 1) == 0)
333                         log3("ERROR: 'Thread2' is not among suspended threads");
334                     if (flag >= 8)
335                         log3("ERROR: some extra thread(s) is also suspended");
336                 }
337                 vm.resume();
338 
339                 log2("......checking up threads suspended with groups[0].suspend()");
340                 log2("         expected: 'Thread2', 'Thread3', and 'Thread4'");
341                 groups[0].suspend();
342 
343                 iterator = threads.listIterator();
344                 flag = 0;
345                 for ( int i2 = 0; iterator.hasNext(); i2++ ) {
346                     thread = (ThreadReference) iterator.next();
347                     if (!thread.isSuspended())
348                         continue;
349                     threadName = thread.name();
350                     if (threadName.equals(threadNames[0]))
351                          flag |= 1;
352                     else if (threadName.equals(threadNames[1]))
353                          flag |= 2;
354                     else if (threadName.equals(threadNames[2]))
355                          flag |= 4;
356                     else flag |= 8;
357                 }
358                 if (flag != 7) {
359                     expresult = returnCode1;
360                     if (flag == 0)
361                         log3("ERROR: no threads suspunded");
362                     if ((flag & 4) == 0)
363                         log3("ERROR: 'Thread4' is not among suspended threads");
364                     if ((flag & 2) == 0)
365                         log3("ERROR: 'Thread3' is not among suspended threads");
366                     if ((flag & 1) == 0)
367                         log3("ERROR: 'Thread2' is not among suspended threads");
368                     if (flag >= 8)
369                         log3("ERROR: some extra thread(s) is also suspended");
370                 }
371                 vm.resume();
372 
373 
374 
375 
376                 log2("......instructing mainThread to leave synchronized block");
377                 pipe.println("continue");
378                 line = pipe.readln();
379                 if (!line.equals("docontinue")) {
380                     log3("ERROR: returned string is not 'docontinue'");
381                     expresult = returnCode4;
382                 }
383             }
384             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
385             log2("     the end of testing");
386             if (expresult != returnCode0)
387                 testExitCode = FAILED;
388         }
389         log1("      TESTING ENDS");
390 
391     //--------------------------------------------------   test summary section
392     //-------------------------------------------------    standard end section
393 
394         pipe.println("quit");
395         log2("waiting for the debuggee to finish ...");
396         debuggee.waitFor();
397 
398         int status = debuggee.getStatus();
399         if (status != PASSED + PASS_BASE) {
400             log3("debuggee returned UNEXPECTED exit status: " +
401                     status + " != PASS_BASE");
402             testExitCode = FAILED;
403         } else {
404             log2("debuggee returned expected exit status: " +
405                     status + " == PASS_BASE");
406         }
407 
408         if (testExitCode != PASSED) {
409             logHandler.complain("TEST FAILED");
410         }
411         return testExitCode;
412     }
413 }
414