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