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.isSuspended;
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.isSuspended()</code>       <BR>
43  * complies with its spec.                                      <BR>
44  * The test checks up the following case:                                       <BR>
45  * - a debuggee with two threads is suspended with VirtualMachine.suspend();    <BR>
46  * - then one thread is resumed with ThreadReference.resume().                  <BR>
47  * <BR>
48  * After being started up, the debuggee :                               <BR>
49  * - creates a 'lockingObject'for synchronizing threads;                <BR>
50  * - enters into the synchronized block                                 <BR>
51  *   in which it creates new thread, thread2;                           <BR>
52  * - informs a debugger of the thread creation, and is waiting for reply.<BR>
53  * Since the thread2 uses the same lockingObject in its 'run' method    <BR>
54  * it is locked up until the main thread leaves the synchronized block. <BR>
55  * Upon the receiption a message from the debuggee, the debugger        <BR>
56  * - sets up a breakpoint for the thread2;                              <BR>
57  * - suspends the thread2 with ThreadReference.suspend();               <BR>
58  * - instructs the main thread to leave the synchronized block,         <BR>
59  *   after what the thread is waiting for                               <BR>
60  *   new instruction from the debugger again;                           <BR>
61  * - totally suspends the debuggee with VirtualMahcine.suspend();       <BR>
62  * - resumes only the thread2 with double ThreadReference.resume()      <BR>
63  *   that results in thread2's suspendCount == 0;                       <BR>
64  * - checks up that the thread2 is suspended at the breakpoint;         <BR>
65  * - resumes the debuggee with VirtualMachine.resume().                 <BR>
66  * <BR>
67  */
68 
69 public class issuspended002 {
70 
71     //----------------------------------------------------- templete section
72     static final int PASSED = 0;
73     static final int FAILED = 2;
74     static final int PASS_BASE = 95;
75 
76     //----------------------------------------------------- templete parameters
77     static final String
78     sHeader1 = "\n==> nsk/jdi/ThreadReference/isSuspended/issuspended002  ",
79     sHeader2 = "--> debugger: ",
80     sHeader3 = "##> debugger: ";
81 
82     //----------------------------------------------------- main method
83 
main(String argv[])84     public static void main (String argv[]) {
85         int result = run(argv, System.out);
86         System.exit(result + PASS_BASE);
87     }
88 
run(String argv[], PrintStream out)89     public static int run (String argv[], PrintStream out) {
90         return new issuspended002().runThis(argv, out);
91     }
92 
93     //--------------------------------------------------   log procedures
94 
95     private static Log  logHandler;
96 
log1(String message)97     private static void log1(String message) {
98         logHandler.display(sHeader1 + message);
99     }
log2(String message)100     private static void log2(String message) {
101         logHandler.display(sHeader2 + message);
102     }
log3(String message)103     private static void log3(String message) {
104         logHandler.complain(sHeader3 + message);
105     }
106 
107     //  ************************************************    test parameters
108 
109     private String debuggeeName =
110         "nsk.jdi.ThreadReference.isSuspended.issuspended002a";
111 
112     private String testedClassName =
113         "nsk.jdi.ThreadReference.isSuspended.Threadissuspended002a";
114 
115     //String mName = "nsk.jdi.ThreadReference.isSuspended";
116 
117     //====================================================== test program
118     //------------------------------------------------------ common section
119     static ArgumentHandler      argsHandler;
120 
121     static int waitTime;
122 
123     static VirtualMachine      vm            = null;
124     static EventRequestManager eventRManager = null;
125     static EventQueue          eventQueue    = null;
126     static EventSet            eventSet      = null;
127 
128     ReferenceType     testedclass  = null;
129     ThreadReference   thread2      = null;
130     ThreadReference   mainThread   = null;
131 
132     static int  testExitCode = PASSED;
133 
134     static final int returnCode0 = 0;
135     static final int returnCode1 = 1;
136     static final int returnCode2 = 2;
137     static final int returnCode3 = 3;
138     static final int returnCode4 = 4;
139 
140     //------------------------------------------------------ methods
141 
runThis(String argv[], PrintStream out)142     private int runThis (String argv[], PrintStream out) {
143 
144         Debugee debuggee;
145 
146         argsHandler     = new ArgumentHandler(argv);
147         logHandler      = new Log(out, argsHandler);
148         Binder binder   = new Binder(argsHandler, logHandler);
149 
150         if (argsHandler.verbose()) {
151             debuggee = binder.bindToDebugee(debuggeeName + " -vbs");
152         } else {
153             debuggee = binder.bindToDebugee(debuggeeName);
154         }
155 
156         waitTime = argsHandler.getWaitTime();
157 
158 
159         IOPipe pipe     = new IOPipe(debuggee);
160 
161         debuggee.redirectStderr(out);
162         log2(debuggeeName + " debuggee launched");
163         debuggee.resume();
164 
165         String line = pipe.readln();
166         if ((line == null) || !line.equals("ready")) {
167             log3("signal received is not 'ready' but: " + line);
168             return FAILED;
169         } else {
170             log2("'ready' recieved");
171         }
172 
173         vm = debuggee.VM();
174 
175     //------------------------------------------------------  testing section
176         log1("      TESTING BEGINS");
177 
178         for (int i = 0; ; i++) {
179 
180             pipe.println("newcheck");
181             line = pipe.readln();
182 
183             if (line.equals("checkend")) {
184                 log2("     : returned string is 'checkend'");
185                 break ;
186             } else if (!line.equals("checkready")) {
187                 log3("ERROR: returned string is not 'checkready'");
188                 testExitCode = FAILED;
189                 break ;
190             }
191 
192             log1("new checkready: #" + i);
193 
194             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part
195 
196             int expresult = returnCode0;
197 
198 
199             eventRManager = vm.eventRequestManager();
200             eventQueue    = vm.eventQueue();
201 
202             String threadName = "testedThread";
203 
204             String breakpointMethod1 = "runt1";
205             //String breakpointMethod2 = "runt2";
206 
207             String bpLine1 = "breakpointLineNumber1";
208             //String bpLine2 = "breakpointLineNumber2";
209             //String bpLine3 = "breakpointLineNumber3";
210 
211 
212             List            allThreads   = null;
213             ListIterator    listIterator = null;
214             List            classes      = null;
215 
216             BreakpointRequest breakpRequest1 = null;
217             //BreakpointRequest breakpRequest2 = null;
218             //BreakpointRequest breakpRequest3 = null;
219 
220             int suspCount = 0;
221             int frameCount;
222 
223 
224             label0: {
225 
226                 log2("getting ThreadReference objects and setting up breakponts");
227                 try {
228                     allThreads  = vm.allThreads();
229                     classes     = vm.classesByName(testedClassName);
230                     testedclass = (ReferenceType) classes.get(0);
231                 } catch ( Exception e) {
232                     log3("ERROR: Exception at very beginning !? : " + e);
233                     expresult = returnCode1;
234                     break label0;
235                 }
236 
237                 listIterator = allThreads.listIterator();
238                 for (;;) {
239                     try {
240                         thread2 = (ThreadReference) listIterator.next();
241                         if (thread2.name().equals(threadName))
242                             break ;
243                     } catch ( NoSuchElementException e ) {
244                         log3("ERROR: NoSuchElementException for listIterator.next()");
245                         log3("ERROR: NO THREAD2 ?????????!!!!!!!");
246                         expresult = returnCode1;
247                         break label0;
248                     }
249                 }
250 
251                 log2("getting ThreadReference objects for main thread");
252                 listIterator = allThreads.listIterator();
253                 for (;;) {
254                     try {
255                         mainThread = (ThreadReference) listIterator.next();
256                         if (mainThread.name().equals("main"))
257                             break ;
258                     } catch ( NoSuchElementException e ) {
259                         log3("ERROR: NoSuchElementException for listIterator.next() for 'mainThread'");
260                         log3("ERROR: NO MAIN THREAD ?????????!!!!!!!");
261                         expresult = returnCode1;
262                         break label0;
263                     }
264                 }
265 
266                 log2("setting up breakpoints");
267 
268                 breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one");
269                 if (breakpRequest1 == null) {
270                     expresult = returnCode1;
271                     break label0;
272                 }
273             }
274 
275             label1: {
276                 if (expresult != returnCode0)
277                     break label1;
278 
279                 log2("     checking up before to begin testing the thread2");
280                 log2("         thread2.suspendCount() == " + thread2.suspendCount());
281                 if (!thread2.isSuspended()) {
282                     log2("     :  !thread2.isSuspended()");
283                 } else {
284                     log3("ERROR:  thread2.isSuspended()");
285                     expresult = returnCode1;
286                 }
287                 log2("         mainThread.suspendCount() == " + mainThread.suspendCount());
288                 if (!mainThread.isSuspended()) {
289                     log2("     :  !mainThread.isSuspended()");
290                 } else {
291                     log3("ERROR:  mainThread.isSuspended()");
292                     expresult = returnCode1;
293                 }
294 
295 
296                 log2("     suspending thread2 with thread2.suspend();");
297                 thread2.suspend();
298 
299                 log2("         thread2.suspendCount() == " + thread2.suspendCount());
300                 if (thread2.isSuspended()) {
301                     log2("     :  thread2.isSuspended()");
302                 } else {
303                     log3("ERROR:  !thread2.isSuspended()");
304                     expresult = returnCode1;
305                 }
306                 log2("         mainThread.suspendCount() == " + mainThread.suspendCount());
307                 if (!mainThread.isSuspended()) {
308                     log2("     :  !mainThread.isSuspended()");
309                 } else {
310                     log3("ERROR:  mainThread.isSuspended() ????????!!!");
311                     expresult = returnCode1;
312                 }
313 
314                 log2("       forcing the main thread to leave synchronized block");
315                 pipe.println("continue");
316                 line = pipe.readln();
317                 if (!line.equals("docontinue")) {
318                     log3("ERROR: returned string is not 'docontinue'");
319                     expresult = returnCode4;
320                 }
321 
322                 if (expresult != returnCode0)
323                     break label1;
324 
325 
326                 log2("      suspending VM with vm.suspend();");
327                 vm.suspend();
328 
329                 suspCount = thread2.suspendCount();
330                 if (suspCount != 2) {
331                     log3("ERROR:   thread2.suspendCount() != 2 : " + suspCount);
332                     expresult = returnCode1;
333                 } else {
334                     log2("         thread2.suspendCount() == 2");
335                 }
336                 if (thread2.isSuspended()) {
337                     log2("     :   thread2.isSuspended()");
338                 } else {
339                     log3("ERROR:  !thread2.isSuspended()");
340                     expresult = returnCode1;
341                 }
342                 suspCount = mainThread.suspendCount();
343                 if (suspCount != 1) {
344                     log3("ERROR:   mainThread.suspendCount() != 1 : " + suspCount);
345                     expresult = returnCode1;
346                 } else {
347                     log2("         mainThread.suspendCount() == 1");
348                 }
349                 if (mainThread.isSuspended()) {
350                     log2("     :   mainThread.isSuspended()");
351                 } else {
352                     log3("ERROR:  !mainThread.isSuspended()");
353                     expresult = returnCode1;
354                 }
355 
356 
357                 log2("      double resuming thread2 with thread2.resume();");
358 
359                 thread2.resume();
360 
361                 suspCount = thread2.suspendCount();
362                 log2("         thread2.suspendCount() == " + suspCount);
363                 if (thread2.isSuspended()) {
364                     log2("     :   thread2.isSuspended()");
365                 } else {
366                     log3("ERROR:  !thread2.isSuspended()");
367                     expresult = returnCode1;
368                 }
369 
370                 if (expresult == returnCode0) {
371                     log2("     enabling breakpRequest1");
372                     breakpRequest1.enable();
373                 }
374 
375                 thread2.resume();
376 
377                 suspCount = thread2.suspendCount();
378                 log2("         thread2.suspendCount() == " + suspCount);
379                 if ( thread2.isAtBreakpoint() ) {
380                     log2("     :   thread2.isAtBreakpoint() before call to breakpoint()");
381                 } else {
382                     log2("     :  !thread2.isAtBreakpoint() before call to breakpoint()");
383                 }
384             }
385 
386             label2: {
387 
388                 if (expresult == returnCode0)
389                     expresult = breakpoint();
390                 if (expresult != returnCode0)
391                     break label2;
392 
393                 log2("      the thread2 is at the breakpoint");
394 
395                 log2("      the check that the thread2 is suspended at the breakpoint");
396                 log2("         thread2.suspendCount() == " + thread2.suspendCount());
397                 if ( thread2.isAtBreakpoint() ) {
398                     log2("     :   thread2.isAtBreakpoint()");
399                 } else {
400                     log3("ERROR:  !thread2.isAtBreakpoint()");
401                     expresult = returnCode1;
402                 }
403                 if ( thread2.isSuspended() ) {
404                     log2("     :   thread2.isSuspended()");
405                 } else {
406                     log3("ERROR:  !thread2.isSuspended()");
407                     expresult = returnCode1;
408                 }
409                 if (mainThread.isSuspended()) {
410                     log2("     :  mainThread.isSuspended()");
411                 } else {
412                     log3("ERROR:  !mainThread.isSuspended()");
413                     expresult = returnCode1;
414                 }
415             }
416 
417             log2("      resuming both second and main thread");
418 
419             vm.resume();
420 
421             if (expresult == returnCode0) {
422                 if ( !thread2.isSuspended() ) {
423                      log2("     :  !thread2.isSuspended()");
424                 } else {
425                      log3("ERROR:   thread2.isSuspended()");
426                      expresult = returnCode1;
427                 }
428                 if ( !mainThread.isSuspended() ) {
429                      log2("     :  !mainThread.isSuspended()");
430                 } else {
431                      log3("ERROR:   mainThread.isSuspended()");
432                      expresult = returnCode2;
433                 }
434             }
435 
436             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
437             log2("     the end of testing");
438             if (expresult != returnCode0)
439                 testExitCode = FAILED;
440         }
441         log1("      TESTING ENDS");
442 
443     //--------------------------------------------------   test summary section
444     //-------------------------------------------------    standard end section
445 
446         pipe.println("quit");
447         log2("waiting for the debuggee to finish ...");
448         debuggee.waitFor();
449 
450         int status = debuggee.getStatus();
451         if (status != PASSED + PASS_BASE) {
452             log3("debuggee returned UNEXPECTED exit status: " +
453                     status + " != PASS_BASE");
454             testExitCode = FAILED;
455         } else {
456             log2("debuggee returned expected exit status: " +
457                     status + " == PASS_BASE");
458         }
459 
460         if (testExitCode != PASSED) {
461             logHandler.complain("TEST FAILED");
462         }
463         return testExitCode;
464     }
465 
466 
467 
468    /*
469     * private BreakpointRequest settingBreakpoint(String, String, String)
470     *
471     * It sets up a breakpoint within a given method at given line number
472     * for the thread2 only.
473     * Third parameter is required for any case in future debugging, as if.
474     *
475     * Return codes:
476     *  = BreakpointRequest object  in case of success
477     *  = null   in case of an Exception thrown within the method
478     */
479 
settingBreakpoint( String methodName, String bpLine, String property)480     private BreakpointRequest settingBreakpoint ( String methodName,
481                                                   String bpLine,
482                                                   String property) {
483 
484         log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine );
485 
486         List              alllineLocations = null;
487         Location          lineLocation     = null;
488         BreakpointRequest breakpRequest    = null;
489 
490         try {
491             Method  method  = (Method) testedclass.methodsByName(methodName).get(0);
492 
493             alllineLocations = method.allLineLocations();
494 
495             int n =
496                 ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value();
497             if (n > alllineLocations.size()) {
498                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
499             } else {
500                 lineLocation = (Location) alllineLocations.get(n);
501                 try {
502                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
503                     breakpRequest.putProperty("number", property);
504                     breakpRequest.addThreadFilter(thread2);
505                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
506                 } catch ( Exception e1 ) {
507                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
508                     breakpRequest    = null;
509                 }
510             }
511         } catch ( Exception e2 ) {
512             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
513             breakpRequest    = null;
514         }
515 
516         if (breakpRequest == null)
517             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
518         else
519             log2("      a breakpoint has been set up");
520 
521         return breakpRequest;
522     }
523 
524 
525     /*
526      * private int breakpoint ()
527      *
528      * It removes events from EventQueue until gets first BreakpointEvent.
529      * To get next EventSet value, it uses the method
530      *    EventQueue.remove(int timeout)
531      * The timeout argument passed to the method, is "waitTime*60000".
532      * Note: the value of waitTime is set up with
533      *       the method ArgumentHandler.getWaitTime() at the beginning of the test.
534      *
535      * Return codes:
536      *  = returnCode0 - success;
537      *  = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed
538      *  = returnCode3 - default case when loop of processing an event, that is,
539      *                  an unspecified event was taken from the EventQueue
540      */
541 
breakpoint()542     private int breakpoint () {
543 
544         int returnCode = returnCode0;
545 
546         log2("       waiting for BreakpointEvent");
547 
548         labelBP:
549             for (;;) {
550 
551                 log2("       new:  eventSet = eventQueue.remove();");
552                 try {
553                     eventSet = eventQueue.remove(waitTime*60000);
554                     if (eventSet == null) {
555                         log3("ERROR:  timeout for waiting for a BreakpintEvent");
556                         returnCode = returnCode3;
557                         break labelBP;
558                     }
559                 } catch ( Exception e ) {
560                     log3("ERROR: Exception for  eventSet = eventQueue.remove(); : " + e);
561                     returnCode = 1;
562                     break labelBP;
563                 }
564 
565                 if (eventSet != null) {
566 
567                     log2("     :  eventSet != null;  size == " + eventSet.size());
568 
569                     EventIterator eIter = eventSet.eventIterator();
570                     Event         ev    = null;
571 
572                     for (; eIter.hasNext(); ) {
573 
574                         if (returnCode != returnCode0)
575                             break;
576 
577                         ev = eIter.nextEvent();
578 
579                     ll: for (int ifor =0;  ; ifor++) {
580 
581                         try {
582                           switch (ifor) {
583 
584                           case 0:  AccessWatchpointEvent awe = (AccessWatchpointEvent) ev;
585                                    log2("      AccessWatchpointEvent removed");
586                                    break ll;
587                           case 1:  BreakpointEvent be = (BreakpointEvent) ev;
588                                    log2("      BreakpointEvent removed");
589                                    break labelBP;
590                           case 2:  ClassPrepareEvent cpe = (ClassPrepareEvent) ev;
591                                    log2("      ClassPreparEvent removed");
592                                    break ll;
593                           case 3:  ClassUnloadEvent cue = (ClassUnloadEvent) ev;
594                                    log2("      ClassUnloadEvent removed");
595                                    break ll;
596                           case 4:  ExceptionEvent ee = (ExceptionEvent) ev;
597                                    log2("      ExceptionEvent removed");
598                                    break ll;
599                           case 5:  MethodEntryEvent mene = (MethodEntryEvent) ev;
600                                    log2("      MethodEntryEvent removed");
601                                    break ll;
602                           case 6:  MethodExitEvent mexe = (MethodExitEvent) ev;
603                                    log2("      MethodExiEvent removed");
604                                    break ll;
605                           case 7:  ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev;
606                                    log2("      ModificationWatchpointEvent removed");
607                                    break ll;
608                           case 8:  StepEvent se = (StepEvent) ev;
609                                    log2("      StepEvent removed");
610                                    break ll;
611                           case 9:  ThreadDeathEvent tde = (ThreadDeathEvent) ev;
612                                    log2("      ThreadDeathEvent removed");
613                                    break ll;
614                           case 10: ThreadStartEvent tse = (ThreadStartEvent) ev;
615                                    log2("      ThreadStartEvent removed");
616                                    break ll;
617                           case 11: VMDeathEvent vmde = (VMDeathEvent) ev;
618                                    log2("      VMDeathEvent removed");
619                                    break ll;
620                           case 12: VMStartEvent vmse = (VMStartEvent) ev;
621                                    log2("      VMStartEvent removed");
622                                    break ll;
623                           case 13: WatchpointEvent we = (WatchpointEvent) ev;
624                                    log2("      WatchpointEvent removed");
625                                    break ll;
626 
627                           default: log3("ERROR:  default case for casting event");
628                                    returnCode = returnCode3;
629                                    break ll;
630                           } // switch
631                         } catch ( ClassCastException e ) {
632                         }   // try
633                     }       // ll: for (int ifor =0;  ; ifor++)
634                 }           // for (; ev.hasNext(); )
635             }
636         }
637         if (returnCode == returnCode0)
638             log2("     :  eventSet == null:  EventQueue is empty");
639 
640         return returnCode;
641     }
642 
643 }
644