1 /*
2  * Copyright (c) 2001, 2019, 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.ThreadReference.suspendCount;
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 import com.sun.jdi.event.*;
35 import com.sun.jdi.request.*;
36 
37 /**
38  * The test for the implementation of an object of the type     <BR>
39  * ThreadReference.                                             <BR>
40  *                                                              <BR>
41  * The test checks up that results of the method                <BR>
42  * <code>com.sun.jdi.ThreadReference.suspendCount()</code>      <BR>
43  * complies with its spec.                                      <BR>
44  * <BR>
45  * The cases for testing are as follows.                                <BR>
46  * After being started up,                                              <BR>
47  * a debuggee creates a 'lockingObject' for synchronizing threads,      <BR>
48  * enters a synchronized block in which it creates new thread, thread2, <BR>
49  * informs a debugger of the thread2 creation, and is waiting for reply.<BR>
50  * Since the thread2 uses the same locking object in its 'run' method   <BR>
51  * it is locked up until the debuggee leaves the synchronized block.    <BR>
52  * Upon the receiption a message from the debuggee, the debugger        <BR>
53  * calls methods ThreadReference.suspend() and .resume(), and           <BR>
54  * VirualMachine.suspend() and .resume() in a number of combinations,   <BR>
55  * and checks up that each combination results in the expected value    <BR>
56  * returned by the method suspendCount().                               <BR>
57  * At the end the debugger instructs the debuggee to unlock the thread2.<BR>
58  * <BR>
59  */
60 
61 public class suspendcount001 {
62 
63     //----------------------------------------------------- templete section
64     static final int PASSED = 0;
65     static final int FAILED = 2;
66     static final int PASS_BASE = 95;
67 
68     //----------------------------------------------------- templete parameters
69     static final String
70     sHeader1 = "\n==> nsk/jdi/ThreadReference/suspendCount/suspendcount001  ",
71     sHeader2 = "--> debugger: ",
72     sHeader3 = "##> debugger: ";
73 
74     //----------------------------------------------------- main method
75 
main(String argv[])76     public static void main (String argv[]) {
77         int result = run(argv, System.out);
78         System.exit(result + PASS_BASE);
79     }
80 
run(String argv[], PrintStream out)81     public static int run (String argv[], PrintStream out) {
82         return new suspendcount001().runThis(argv, out);
83     }
84 
85     //--------------------------------------------------   log procedures
86 
87     private static Log  logHandler;
88 
log1(String message)89     private static void log1(String message) {
90         logHandler.display(sHeader1 + message);
91     }
log2(String message)92     private static void log2(String message) {
93         logHandler.display(sHeader2 + message);
94     }
log3(String message)95     private static void log3(String message) {
96         logHandler.complain(sHeader3 + message);
97     }
98 
99     //  ************************************************    test parameters
100 
101     private String debuggeeName =
102         "nsk.jdi.ThreadReference.suspendCount.suspendcount001a";
103 
104     private String testedClassName =
105         "nsk.jdi.ThreadReference.suspendCount.Threadsuspendcount001a";
106 
107     //String mName = "nsk.jdi.ThreadReference.suspendCount";
108 
109     //====================================================== test program
110     //------------------------------------------------------ common section
111 
112     static ArgumentHandler      argsHandler;
113 
114     static int waitTime;
115 
116     static VirtualMachine      vm            = null;
117     static EventRequestManager eventRManager = null;
118     static EventQueue          eventQueue    = null;
119     static EventSet            eventSet      = 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(debuggeeName + " 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 
192             eventRManager = vm.eventRequestManager();
193             eventQueue    = vm.eventQueue();
194 
195             String threadName = "testedThread";
196 
197             //String breakpointMethod1 = "runt1";
198             //String breakpointMethod2 = "runt2";
199 
200             //String bpLine1 = "breakpointLineNumber1";
201             //String bpLine2 = "breakpointLineNumber2";
202             //String bpLine3 = "breakpointLineNumber3";
203 
204 
205             List            allThreads   = null;
206             ListIterator    listIterator = null;
207             List            classes      = null;
208 
209             //BreakpointRequest breakpRequest1 = null;
210             //BreakpointRequest breakpRequest2 = null;
211             //BreakpointRequest breakpRequest3 = null;
212 
213 
214             label0: {
215 
216                 log2("getting ThreadReference objects and setting up breakponts");
217                 try {
218                     allThreads  = vm.allThreads();
219                     classes     = vm.classesByName(testedClassName);
220                     testedclass = (ReferenceType) classes.get(0);
221                 } catch ( Exception e) {
222                     log3("ERROR: Exception at very beginning !? : " + e);
223                     expresult = returnCode1;
224                     break label0;
225                 }
226 
227                 listIterator = allThreads.listIterator();
228                 for (;;) {
229                     try {
230                         thread2 = (ThreadReference) listIterator.next();
231                         if (thread2.name().equals(threadName))
232                             break ;
233                     } catch ( NoSuchElementException e ) {
234                         log3("ERROR: NoSuchElementException for listIterator.next()");
235                         log3("ERROR: NO THREAD2 ?????????!!!!!!!");
236                         expresult = returnCode1;
237                         break label0;
238                     }
239                 }
240             }
241 
242             label1: {
243                 if (expresult != returnCode0)
244                     break label1;
245 
246 
247                 int suspCount;
248 
249                 log2("         check #1: the beginning: suspCount == 0 ");
250                 suspCount = thread2.suspendCount();
251                 if (suspCount != 0) {
252                     log3("ERROR: 1: suspCount != 0 : " + suspCount);
253                     expresult = returnCode1;
254                 }
255 
256 
257                 log2("        suspending thread2 with: thread2.suspend(); ");
258                 thread2.suspend();
259 
260                 log2("         check #2:  suspCount == 1 ");
261                 suspCount = thread2.suspendCount();
262                 if (suspCount != 1) {
263                     log3("ERROR: 2: suspCount != 1 : " + suspCount);
264                     expresult = returnCode1;
265                 }
266 
267 
268                 log2("        suspending thread2 with: thread2.suspend(); ");
269                 thread2.suspend();
270 
271                 log2("         check #3:  suspCount == 2 ");
272                 suspCount = thread2.suspendCount();
273                 if (suspCount != 2) {
274                     log3("ERROR: 3: suspCount != 2 : " + suspCount);
275                     expresult = returnCode1;;
276                 }
277 
278 
279                 log2("        resuming thread2 with: thread2.resume(); ");
280                 thread2.resume();
281 
282                 log2("         check #4:  suspCount == 1 ");
283                 suspCount = thread2.suspendCount();
284                 if (suspCount != 1) {
285                     log3("ERROR: 4: suspCount != 1 : " + suspCount);
286                     expresult = returnCode1;
287                 }
288 
289 
290                 log2("        resuming thread2 with: thread2.resume(); ");
291                 thread2.resume();
292 
293                 log2("         check #5:  suspCount == 0 ");
294                 suspCount = thread2.suspendCount();
295                 if (suspCount != 0) {
296                     log3("ERROR: 5: suspCount != 0 : " + suspCount);
297                     expresult = returnCode1;
298                 }
299 
300 
301                 log2("        resuming NON-SUSPENDED thread2 with: thread2.resume(); ");
302                 thread2.resume();
303 
304                 log2("         check #6:  suspCount == 0 ");
305                 suspCount = thread2.suspendCount();
306                 if (suspCount != 0) {
307                     log3("ERROR: 6: suspCount != 0 : " + suspCount);
308                     expresult = returnCode1;
309                 }
310 
311 
312                 log2("        suspending thread2 with: thread2.suspend(); ");
313                 thread2.suspend();
314 
315                 log2("         check #7:  suspCount == 1 ");
316                 suspCount = thread2.suspendCount();
317                 if (suspCount != 1) {
318                     log3("ERROR: 7: suspCount != 1 : " + suspCount);
319                     expresult = returnCode1;
320                 }
321 
322 
323                 log2("       suspending VirtualMachine with vm.suspend(); ");
324                 vm.suspend();
325 
326                 log2("         check #8:  suspCount == 2 ");
327                 suspCount = thread2.suspendCount();
328                 if (suspCount != 2) {
329                     log3("ERROR: 8: suspCount != 2 : " + suspCount);
330                     expresult = returnCode1;
331                 }
332 
333 
334                 log2("       9: resuming only thread2 with double thread2.resume(); ");
335                 thread2.resume();
336                 thread2.resume();
337 
338                 log2("         check #9:  suspCount == 0 ");
339                 suspCount = thread2.suspendCount();
340                 if (suspCount != 0) {
341                     log3("ERROR: 9: suspCount != 0 : " + suspCount);
342                     expresult = returnCode1;
343                 }
344 
345 
346                 log2("       10: suspending VirtualMachine with double vm.suspend(); ");
347                 vm.suspend();
348                 vm.suspend();
349 
350                 log2("         check #10:  suspCount == 2 ");
351                 suspCount = thread2.suspendCount();
352                 if (suspCount != 2) {
353                     log3("ERROR: 10: suspCount != 2 : " + suspCount);
354                     expresult = returnCode1;
355                 }
356 
357 
358                 log2("       11: resuming with thread2.resume(); and vm.resume(); ");
359                 thread2.resume();
360                 vm.resume();
361 
362                 log2("         check #11:  suspCount == 0 ");
363                 suspCount = thread2.suspendCount();
364                 if (suspCount != 0) {
365                     log3("ERROR: 11: suspCount != 0 : " + suspCount);
366                     expresult = returnCode1;
367                 }
368 
369                 vm.resume();
370                 vm.resume();
371 
372 
373                 log2("       forcing the main thread to leave synchronized block");
374                 pipe.println("continue");
375                 line = pipe.readln();
376                 if (!line.equals("docontinue")) {
377                     log3("ERROR: returned string is not 'docontinue'");
378                     expresult = returnCode4;
379                 }
380 
381             }
382 
383             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
384             log2("     the end of testing");
385             if (expresult != returnCode0)
386                 testExitCode = FAILED;
387         }
388         log1("      TESTING ENDS");
389 
390     //--------------------------------------------------   test summary section
391     //-------------------------------------------------    standard end section
392 
393         pipe.println("quit");
394         log2("waiting for the debuggee to finish ...");
395         debuggee.waitFor();
396 
397         int status = debuggee.getStatus();
398         if (status != PASSED + PASS_BASE) {
399             log3("debuggee returned UNEXPECTED exit status: " +
400                     status + " != PASS_BASE");
401             testExitCode = FAILED;
402         } else {
403             log2("debuggee returned expected exit status: " +
404                     status + " == PASS_BASE");
405         }
406 
407         if (testExitCode != PASSED) {
408             logHandler.complain("TEST FAILED");
409         }
410         return testExitCode;
411     }
412 
413 
414    /*
415     * private BreakpointRequest settingBreakpoint(String, String, String)
416     *
417     * It sets up a breakpoint within a given method at given line number
418     * for the thread2 only.
419     * Third parameter is required for any case in future debugging, as if.
420     *
421     * Return codes:
422     *  = BreakpointRequest object  in case of success
423     *  = null   in case of an Exception thrown within the method
424     */
425 /*
426     private BreakpointRequest settingBreakpoint ( String methodName,
427                                                   String bpLine,
428                                                   String property) {
429 
430         log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine );
431 
432         List              alllineLocations = null;
433         Location          lineLocation     = null;
434         BreakpointRequest breakpRequest    = null;
435 
436         try {
437             Method  method  = (Method) testedclass.methodsByName(methodName).get(0);
438 
439             alllineLocations = method.allLineLocations();
440 
441             int n =
442                 ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value();
443             if (n > alllineLocations.size()) {
444                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
445             } else {
446                 lineLocation = (Location) alllineLocations.get(n);
447                 try {
448                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
449                     breakpRequest.putProperty("number", property);
450                     breakpRequest.addThreadFilter(thread2);
451                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
452                 } catch ( Exception e1 ) {
453                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
454                     breakpRequest    = null;
455                 }
456             }
457         } catch ( Exception e2 ) {
458             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
459             breakpRequest    = null;
460         }
461 
462         if (breakpRequest == null)
463             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
464         else
465             log2("      a breakpoint has been set up");
466 
467         return breakpRequest;
468     }
469 */
470 
471     /*
472      * private int breakpoint ()
473      *
474      * It removes events from EventQueue until gets first BreakpointEvent.
475      * To get next EventSet value, it uses the method
476      *    EventQueue.remove(int timeout)
477      * The timeout argument passed to the method, is "waitTime*60000".
478      * Note: the value of waitTime is set up with
479      *       the method ArgumentHandler.getWaitTime() at the beginning of the test.
480      *
481      * Return codes:
482      *  = returnCode0 - success;
483      *  = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed
484      *  = returnCode3 - default case when loop of processing an event, that is,
485      *                  an unspecified event was taken from the EventQueue
486      */
487 /*
488     private int breakpoint () {
489 
490         int returnCode = returnCode0;
491 
492         log2("       waiting for BreakpointEvent");
493 
494         labelBP:
495             for (;;) {
496 
497                 log2("       new:  eventSet = eventQueue.remove();");
498                 try {
499                     eventSet = eventQueue.remove(waitTime*60000);
500                     if (eventSet == null) {
501                         log3("ERROR:  timeout for waiting for a BreakpintEvent");
502                         returnCode = returnCode3;
503                         break labelBP;
504                     }
505                 } catch ( Exception e ) {
506                     log3("ERROR: Exception for  eventSet = eventQueue.remove(); : " + e);
507                     returnCode = 1;
508                     break labelBP;
509                 }
510 
511                 if (eventSet != null) {
512 
513                     log2("     :  eventSet != null;  size == " + eventSet.size());
514 
515                     EventIterator eIter = eventSet.eventIterator();
516                     Event         ev    = null;
517 
518                     for (; eIter.hasNext(); ) {
519 
520                         if (returnCode != returnCode0)
521                             break;
522 
523                         ev = eIter.nextEvent();
524 
525                     ll: for (int ifor =0;  ; ifor++) {
526 
527                         try {
528                           switch (ifor) {
529 
530                           case 0:  AccessWatchpointEvent awe = (AccessWatchpointEvent) ev;
531                                    log2("      AccessWatchpointEvent removed");
532                                    break ll;
533                           case 1:  BreakpointEvent be = (BreakpointEvent) ev;
534                                    log2("      BreakpointEvent removed");
535                                    break labelBP;
536                           case 2:  ClassPrepareEvent cpe = (ClassPrepareEvent) ev;
537                                    log2("      ClassPreparEvent removed");
538                                    break ll;
539                           case 3:  ClassUnloadEvent cue = (ClassUnloadEvent) ev;
540                                    log2("      ClassUnloadEvent removed");
541                                    break ll;
542                           case 4:  ExceptionEvent ee = (ExceptionEvent) ev;
543                                    log2("      ExceptionEvent removed");
544                                    break ll;
545                           case 5:  MethodEntryEvent mene = (MethodEntryEvent) ev;
546                                    log2("      MethodEntryEvent removed");
547                                    break ll;
548                           case 6:  MethodExitEvent mexe = (MethodExitEvent) ev;
549                                    log2("      MethodExiEvent removed");
550                                    break ll;
551                           case 7:  ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev;
552                                    log2("      ModificationWatchpointEvent removed");
553                                    break ll;
554                           case 8:  StepEvent se = (StepEvent) ev;
555                                    log2("      StepEvent removed");
556                                    break ll;
557                           case 9:  ThreadDeathEvent tde = (ThreadDeathEvent) ev;
558                                    log2("      ThreadDeathEvent removed");
559                                    break ll;
560                           case 10: ThreadStartEvent tse = (ThreadStartEvent) ev;
561                                    log2("      ThreadStartEvent removed");
562                                    break ll;
563                           case 11: VMDeathEvent vmde = (VMDeathEvent) ev;
564                                    log2("      VMDeathEvent removed");
565                                    break ll;
566                           case 12: VMStartEvent vmse = (VMStartEvent) ev;
567                                    log2("      VMStartEvent removed");
568                                    break ll;
569                           case 13: WatchpointEvent we = (WatchpointEvent) ev;
570                                    log2("      WatchpointEvent removed");
571                                    break ll;
572 
573                           default: log3("ERROR:  default case for casting event");
574                                    returnCode = returnCode3;
575                                    break ll;
576                           } // switch
577                         } catch ( ClassCastException e ) {
578                         }   // try
579                     }       // ll: for (int ifor =0;  ; ifor++)
580                 }           // for (; ev.hasNext(); )
581             }
582         }
583         if (returnCode == returnCode0)
584             log2("     :  eventSet == null:  EventQueue is empty");
585 
586         return returnCode;
587     }
588 */
589 }
590