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