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.StackFrame.thread;
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  * StackFrame.                                                  <BR>
40  *                                                              <BR>
41  * The test checks up that results of the method                <BR>
42  * <code>com.sun.jdi.StackFrame.thread()</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 as main one           <BR>
50  * it is locked up until the main thread leaves the synchronized block. <BR>
51  * Upon the receiption a message from the debuggee, the debugger        <BR>
52  * performs the following.                                              <BR>
53  * 1) After getting a thread2 suspended but before to resume it,        <BR>
54  *    the name of the thread2 got with StackFrame.thread() is equal to  <BR>
55  *    its name used for suspending the thread2.                         <BR>
56  *    Since the thread2 is not resumed yet,                             <BR>
57  *    InvalidStackFrameException must not be thrown.                    <BR>
58  * 2) After resuming the thread2, the tested method is invoked          <BR>
59  *    second time and InvalidStackFrameException must be thrown.        <BR>
60  *  <BR>
61  */
62 
63 public class thread001 {
64 
65     //----------------------------------------------------- templete section
66     static final int PASSED = 0;
67     static final int FAILED = 2;
68     static final int PASS_BASE = 95;
69 
70     //----------------------------------------------------- templete parameters
71     static final String
72     sHeader1 = "\n==> nsk/jdi/StackFrame/thread/thread001  ",
73     sHeader2 = "--> debugger: ",
74     sHeader3 = "##> debugger: ";
75 
76     //----------------------------------------------------- main method
77 
main(String argv[])78     public static void main (String argv[]) {
79         int result = run(argv, System.out);
80         System.exit(result + PASS_BASE);
81     }
82 
run(String argv[], PrintStream out)83     public static int run (String argv[], PrintStream out) {
84         return new thread001().runThis(argv, out);
85     }
86 
87     //--------------------------------------------------   log procedures
88 
89     private static Log  logHandler;
90 
log1(String message)91     private static void log1(String message) {
92         logHandler.display(sHeader1 + message);
93     }
log2(String message)94     private static void log2(String message) {
95         logHandler.display(sHeader2 + message);
96     }
log3(String message)97     private static void log3(String message) {
98         logHandler.complain(sHeader3 + message);
99     }
100 
101     //  ************************************************    test parameters
102 
103     private String debuggeeName =
104         "nsk.jdi.StackFrame.thread.thread001a";
105 
106     private String testedClassName =
107         "nsk.jdi.StackFrame.thread.Threadthread001a";
108 
109     //String mName = "nsk.jdi.StackFrame.thread";
110 
111     //====================================================== test program
112     //------------------------------------------------------ common section
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 
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 
144         if (argsHandler.verbose()) {
145             debuggee = binder.bindToDebugee(debuggeeName + " -vbs");  // *** tp
146         } else {
147             debuggee = binder.bindToDebugee(debuggeeName);            // *** tp
148         }
149 
150         waitTime = argsHandler.getWaitTime();
151 
152 
153         IOPipe pipe     = new IOPipe(debuggee);
154 
155         debuggee.redirectStderr(out);
156         log2("location001a 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         VirtualMachine vm = debuggee.VM();
168 
169     //------------------------------------------------------  testing section
170         log1("      TESTING BEGINS");
171 
172         for (int i = 0; ; i++) {
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 check: #" + 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             int suspCount = 0;
214             int frameCount;
215 
216             StackFrame    stackFrame = null;
217             LocalVariable locvar1    = null;
218             LocalVariable locvar2    = null;
219 
220             label0: {
221 
222                 log2("getting ThreadReference object");
223                 try {
224                     allThreads  = vm.allThreads();
225                     classes     = vm.classesByName(testedClassName);
226                     testedclass = (ReferenceType) classes.get(0);
227                 } catch ( Exception e) {
228                     log3("ERROR: Exception at very beginning !? : " + e);
229                     expresult = returnCode1;
230                     break label0;
231                 }
232 
233                 thread2 = debuggee.threadByName(threadName);
234 
235                 log2("setting up a breakpoint");
236 
237                 breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one");
238                 if (breakpRequest1 == null) {
239                     expresult = returnCode1;
240                     break label0;
241                 }
242             }
243 
244             label1: {
245 
246                 if (expresult != returnCode0)
247                        break label1;
248 
249                 log2("     enabling breakpRequest1");
250                 breakpRequest1.enable();
251 
252                 log2("       forcing the main thread to leave synchronized block");
253                 pipe.println("continue");
254                 line = pipe.readln();
255                 if (!line.equals("docontinue")) {
256                     log3("ERROR: returned string is not 'docontinue'");
257                     expresult = returnCode4;
258                     break label1;
259                 }
260 
261                 log2("      getting BreakpointEvent");
262                 expresult = breakpoint();
263                 if (expresult != returnCode0)
264                     break label1;
265                 log2("      thread2 is at breakpoint");
266 
267                 log2("      getting StackFrame");
268                 try {
269                     stackFrame = thread2.frame(0);
270                 } catch ( Exception e ) {
271                     log3("ERROR: Exception for stackFrame = thread2.frame(0)    :" + e);
272                     expresult = returnCode1;
273                     break label1;
274                 }
275 
276                 log2("      checking up that thread2's two names are equal");
277                 try {
278                     if (!stackFrame.thread().name().equals(threadName) ) {
279                         log3("ERROR:  !stackFrame.thread().name().equals(threadName)");
280                         expresult = returnCode1;
281                         break label1;
282                     }
283                 } catch ( InvalidStackFrameException e ) {
284                     log3("ERROR:  InvalidStackFrameException before the thread2 is resumed");
285                     expresult = returnCode1;
286                     break label1;
287                 }
288 
289                 log2("     resuming the thread2 and ");
290                 eventSet.resume();
291 
292                 log2("       checking up throwing InvalidStackFrameException");
293                 try {
294                     ThreadReference t = stackFrame.thread();
295                     expresult = 1;
296                     log3("ERROR:  no InvalidStackFrameExceprtion after the thread2 is resumed");
297                 } catch ( InvalidStackFrameException e ) {
298                 }
299             }
300             eventSet.resume(); // for case if thread2 was not resumed because of error in a check
301 
302             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
303             log2("     the end of testing");
304             if (expresult != returnCode0)
305                 testExitCode = FAILED;
306         }
307         log1("      TESTING ENDS");
308 
309     //--------------------------------------------------   test summary section
310     //-------------------------------------------------    standard end section
311 
312         pipe.println("quit");
313         log2("waiting for the debuggee to finish ...");
314         debuggee.waitFor();
315 
316         int status = debuggee.getStatus();
317         if (status != PASSED + PASS_BASE) {
318             log3("debuggee returned UNEXPECTED exit status: " +
319                     status + " != PASS_BASE");
320             testExitCode = FAILED;
321         } else {
322             log2("debuggee returned expected exit status: " +
323                     status + " == PASS_BASE");
324         }
325 
326         if (testExitCode != PASSED) {
327             logHandler.complain("TEST FAILED");
328         }
329         return testExitCode;
330     }
331 
332 
333    /*
334     * private BreakpointRequest settingBreakpoint(String, String, String)
335     *
336     * It sets up a breakpoint within a given method at given line number
337     * for the thread2 only.
338     * Third parameter is required for any case in future debugging, as if.
339     *
340     * Return codes:
341     *  = BreakpointRequest object  in case of success
342     *  = null   in case of an Exception thrown within the method
343     */
344 
settingBreakpoint( String methodName, String bpLine, String property)345     private BreakpointRequest settingBreakpoint ( String methodName,
346                                                   String bpLine,
347                                                   String property) {
348 
349         log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine );
350 
351         List              alllineLocations = null;
352         Location          lineLocation     = null;
353         BreakpointRequest breakpRequest    = null;
354 
355         try {
356             Method  method  = (Method) testedclass.methodsByName(methodName).get(0);
357 
358             alllineLocations = method.allLineLocations();
359 
360             int n =
361                 ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value();
362             if (n > alllineLocations.size()) {
363                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
364             } else {
365                 lineLocation = (Location) alllineLocations.get(n);
366                 try {
367                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
368                     breakpRequest.putProperty("number", property);
369                     breakpRequest.addThreadFilter(thread2);
370                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
371                 } catch ( Exception e1 ) {
372                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
373                     breakpRequest    = null;
374                 }
375             }
376         } catch ( Exception e2 ) {
377             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
378             breakpRequest    = null;
379         }
380 
381         if (breakpRequest == null)
382             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
383         else
384             log2("      a breakpoint has been set up");
385 
386         return breakpRequest;
387     }
388 
389 
390     /*
391      * private int breakpoint ()
392      *
393      * It removes events from EventQueue until gets first BreakpointEvent.
394      * To get next EventSet value, it uses the method
395      *    EventQueue.remove(int timeout)
396      * The timeout argument passed to the method, is "waitTime*60000".
397      * Note: the value of waitTime is set up with
398      *       the method ArgumentHandler.getWaitTime() at the beginning of the test.
399      *
400      * Return codes:
401      *  = returnCode0 - success;
402      *  = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed
403      *  = returnCode3 - default case when loop of processing an event, that is,
404      *                  an unspecified event was taken from the EventQueue
405      */
406 
breakpoint()407     private int breakpoint () {
408 
409         int returnCode = returnCode0;
410 
411         log2("       waiting for BreakpointEvent");
412 
413         labelBP:
414             for (;;) {
415 
416                 log2("       new:  eventSet = eventQueue.remove();");
417                 try {
418                     eventSet = eventQueue.remove(waitTime*60000);
419                     if (eventSet == null) {
420                         log3("ERROR:  timeout for waiting for a BreakpintEvent");
421                         returnCode = returnCode3;
422                         break labelBP;
423                     }
424                 } catch ( Exception e ) {
425                     log3("ERROR: Exception for  eventSet = eventQueue.remove(); : " + e);
426                     returnCode = 1;
427                     break labelBP;
428                 }
429 
430                 if (eventSet != null) {
431 
432                     log2("     :  eventSet != null;  size == " + eventSet.size());
433 
434                     EventIterator eIter = eventSet.eventIterator();
435                     Event         ev    = null;
436 
437                     for (; eIter.hasNext(); ) {
438 
439                         if (returnCode != returnCode0)
440                             break;
441 
442                         ev = eIter.nextEvent();
443 
444                     ll: for (int ifor =0;  ; ifor++) {
445 
446                         try {
447                           switch (ifor) {
448 
449                           case 0:  AccessWatchpointEvent awe = (AccessWatchpointEvent) ev;
450                                    log2("      AccessWatchpointEvent removed");
451                                    break ll;
452                           case 1:  BreakpointEvent be = (BreakpointEvent) ev;
453                                    log2("      BreakpointEvent removed");
454                                    break labelBP;
455                           case 2:  ClassPrepareEvent cpe = (ClassPrepareEvent) ev;
456                                    log2("      ClassPreparEvent removed");
457                                    break ll;
458                           case 3:  ClassUnloadEvent cue = (ClassUnloadEvent) ev;
459                                    log2("      ClassUnloadEvent removed");
460                                    break ll;
461                           case 4:  ExceptionEvent ee = (ExceptionEvent) ev;
462                                    log2("      ExceptionEvent removed");
463                                    break ll;
464                           case 5:  MethodEntryEvent mene = (MethodEntryEvent) ev;
465                                    log2("      MethodEntryEvent removed");
466                                    break ll;
467                           case 6:  MethodExitEvent mexe = (MethodExitEvent) ev;
468                                    log2("      MethodExiEvent removed");
469                                    break ll;
470                           case 7:  ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev;
471                                    log2("      ModificationWatchpointEvent removed");
472                                    break ll;
473                           case 8:  StepEvent se = (StepEvent) ev;
474                                    log2("      StepEvent removed");
475                                    break ll;
476                           case 9:  ThreadDeathEvent tde = (ThreadDeathEvent) ev;
477                                    log2("      ThreadDeathEvent removed");
478                                    break ll;
479                           case 10: ThreadStartEvent tse = (ThreadStartEvent) ev;
480                                    log2("      ThreadStartEvent removed");
481                                    break ll;
482                           case 11: VMDeathEvent vmde = (VMDeathEvent) ev;
483                                    log2("      VMDeathEvent removed");
484                                    break ll;
485                           case 12: VMStartEvent vmse = (VMStartEvent) ev;
486                                    log2("      VMStartEvent removed");
487                                    break ll;
488                           case 13: WatchpointEvent we = (WatchpointEvent) ev;
489                                    log2("      WatchpointEvent removed");
490                                    break ll;
491 
492                           default: log3("ERROR:  default case for casting event");
493                                    returnCode = returnCode3;
494                                    break ll;
495                           } // switch
496                         } catch ( ClassCastException e ) {
497                         }   // try
498                     }       // ll: for (int ifor =0;  ; ifor++)
499                 }           // for (; ev.hasNext(); )
500             }
501         }
502         if (returnCode == returnCode0)
503             log2("     :  eventSet == null:  EventQueue is empty");
504 
505         return returnCode;
506     }
507 }
508