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.LocalVariable.isVisible;
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  * LocalVariable.                                               <BR>
40  *                                                              <BR>
41  * The test checks up that results of the method                <BR>
42  * <code>com.sun.jdi.LocalVariable.isVisible()</code>           <BR>
43  * complies with its spec in case when a tested program         <BR>
44  * is prepared with full information,                           <BR>
45  * hence, AbsentInformationException is not expected to happen. <BR>
46  * <BR>
47  * The cases for testing are as follows.                        <BR>
48  * After being started up,                                              <BR>
49  * a debuggee creates a 'lockingObject' for synchronizing threads,      <BR>
50  * enters a synchronized block in which it creates new thread, thread2, <BR>
51  * informs a debugger of the thread2 creation, and is waiting for reply.<BR>
52  * Since the thread2 uses the same locking object as main one           <BR>
53  * it is locked up until the main thread leaves the synchronized block. <BR>
54  * Upon the receiption a message from the debuggee, the debugger        <BR>
55  * sets up a breakpoint, instructs the debuggee to leave synchronized   <BR>
56  * block, and after getting the thread2 suspended at breakpoint,        <BR>
57  * StackFrame.variablesByName() is used to form LocalVariable           <BR>
58  * objects for the following method variables:                          <BR>
59  *  - visible i0 and invisible i2 within the method run                 <BR>
60  *    whose StackFrame # = 1;                                           <BR>
61  *  - visible i2 and invisible i3 within the method runt                <BR>
62  *    whose StackFrame # = 0.                                           <BR>
63  * Then a debugger checks up whether the LocalVariable objects          <BR>
64  * are visible or not for corresponding StackFrames.                    <BR>
65  * <BR>
66  */
67 
68 public class isvisible001 {
69 
70     //----------------------------------------------------- templete section
71     static final int PASSED = 0;
72     static final int FAILED = 2;
73     static final int PASS_BASE = 95;
74 
75     //----------------------------------------------------- templete parameters
76     static final String
77     sHeader1 = "\n==> nsk/jdi/LocalVariable/isVisible/isvisible001  ",
78     sHeader2 = "--> debugger: ",
79     sHeader3 = "##> debugger: ";
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 isvisible001().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.LocalVariable.isVisible.isvisible001a";
111 
112     private String testedClassName =
113         "nsk.jdi.LocalVariable.isVisible.Threadisvisible001a";
114 
115     String mName = "nsk.jdi.LocalVariable.isVisible";
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");  // *** tp
152         } else {
153             debuggee = binder.bindToDebugee(debuggeeName);            // *** tp
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         VirtualMachine vm = debuggee.VM();
174 
175     //------------------------------------------------------  testing section
176         log1("      TESTING BEGINS");
177 
178         for (int i = 0; ; i++) {
179         pipe.println("newcheck");
180             line = pipe.readln();
181 
182             if (line.equals("checkend")) {
183                 log2("     : returned string is 'checkend'");
184                 break ;
185             } else if (!line.equals("checkready")) {
186                 log3("ERROR: returned string is not 'checkready'");
187                 testExitCode = FAILED;
188                 break ;
189             }
190 
191             log1("new check: #" + i);
192 
193             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part
194 
195             eventRManager = vm.eventRequestManager();
196             eventQueue    = vm.eventQueue();
197 
198             String threadName = "Thread2";
199 
200             String breakpointMethod1 = "runt1";
201             String bpLine1          = "breakpointLineNumber1";
202 
203             BreakpointRequest breakpRequest1 = null;
204 
205             List            allThreads   = null;
206             ListIterator    listIterator = null;
207             List            classes      = null;
208 
209             StackFrame stackFrame  = null;
210             StackFrame stackFrame1 = null;
211 
212             List methods = null;
213 
214             Method runmethod   = null;
215             Method runt1method = null;
216 
217             List lVars = null;
218 
219             LocalVariable l_i0 = null;
220             LocalVariable l_i1 = null;
221             LocalVariable l_i2 = null;
222             LocalVariable l_i3 = null;
223 
224             int expresult = returnCode0;
225 
226 
227             label0: {
228 
229                 log2("getting ThreadReference object");
230                 try {
231                     allThreads  = vm.allThreads();
232                     classes     = vm.classesByName(testedClassName);
233                     testedclass = (ReferenceType) classes.get(0);
234                 } catch ( Exception e) {
235                     log3("ERROR: Exception at very beginning !? : " + e);
236                     expresult = returnCode1;
237                     break label0;
238                 }
239 
240                 listIterator = allThreads.listIterator();
241                 for (;;) {
242                     try {
243                         thread2 = (ThreadReference) listIterator.next();
244                         if (thread2.name().equals(threadName))
245                             break ;
246                     } catch ( NoSuchElementException e ) {
247                         log3("ERROR: NoSuchElementException for listIterator.next()");
248                         log3("ERROR: NO THREAD2 ?????????!!!!!!!");
249                         expresult = returnCode1;
250                         break label0;
251                     }
252                 }
253 
254                 log2("setting up breakpoint");
255 
256                 breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one");
257                 if (breakpRequest1 == null) {
258                     expresult = returnCode1;
259                     break label0;
260                 }
261 
262             }
263 
264             label1: {
265 
266                 if (expresult != returnCode0)
267                        break label1;
268 
269                 log2("     enabling breakpRequest1");
270                 breakpRequest1.enable();
271 
272                 log2("       forcing the main thread to leave synchronized block");
273                 pipe.println("continue");
274                 line = pipe.readln();
275                 if (!line.equals("docontinue")) {
276                     log3("ERROR: returned string is not 'docontinue'");
277                     expresult = returnCode4;
278                     break label1;
279                 }
280 
281                 log2("      getting a breakpoint event");
282                 expresult = breakpoint();
283                 if (expresult != returnCode0)
284                     break label1;
285 
286                 log2("      getting StackFrame");
287                 try {
288                     stackFrame = thread2.frame(0);
289                     stackFrame1 = thread2.frame(1);
290                 } catch ( Exception e ) {
291                     log3("ERROR: Exception for stackFrame = thread2.frame(0)    :" + e);
292                     expresult = returnCode1;
293                     break label1;
294                 }
295 
296             }
297 
298             label2: {
299 
300                 if (expresult != returnCode0)
301                        break label2;
302 
303                 methods = ((ReferenceType) classes.get(0)).methodsByName("run");
304                 runmethod = (Method) methods.get(0);
305 
306                 methods = ((ReferenceType) classes.get(0)).methodsByName("runt1");
307                 runt1method = (Method) methods.get(0);
308 
309                 try {
310                     log2("      lVars = runmethod.variablesByName('i0');");
311                     lVars = runmethod.variablesByName("i0");
312                     if (lVars.size() != 1) {
313                         log3("ERROR: lVars.size() != 1");
314                         expresult = returnCode1;
315                     }
316                     l_i0 = (LocalVariable) lVars.get(0);
317 
318                     log2("      lVars = runmethod.variablesByName('i1');");
319                     lVars = runmethod.variablesByName("i1");
320                     if (lVars.size() != 1) {
321                         log3("ERROR: lVars.size() != 1");
322                         expresult = returnCode1;
323                     }
324                     l_i1 = (LocalVariable) lVars.get(0);
325 
326                     log2("      lVars = runmethod.variablesByName('i2');");
327                     lVars = runt1method.variablesByName("i2");
328                     if (lVars.size() != 1) {
329                         log3("ERROR: lVars.size() != 1");
330                         expresult = returnCode1;
331                     }
332                     l_i2 = (LocalVariable) lVars.get(0);
333 
334                     log2("      lVars = runmethod.variablesByName('i3');");
335                     lVars = runt1method.variablesByName("i3");
336                     if (lVars.size() != 1) {
337                         log3("ERROR: lVars.size() != 1");
338                         expresult = returnCode1;
339                     }
340                     l_i3 = (LocalVariable) lVars.get(0);
341                 } catch ( AbsentInformationException e ) {
342                     log3("ERROR: AbsentInformationException");
343                     expresult = returnCode1;
344                 }
345                 if (expresult != returnCode0)
346                        break label2;
347 
348 
349                 log2("      checkin up: l_i0.isVisible(stackFrame1);   expected: true");
350                 try {
351                     if (!l_i0.isVisible(stackFrame1)) {
352                         log3("ERROR: !l_i0.isVisible(stackFrame1)");
353                         expresult = returnCode1;
354                     }
355                 } catch ( IllegalArgumentException e ) {
356                     log3("ERROR:  IllegalArgumentException");
357                     expresult = returnCode1;
358                 }
359 
360                 log2("      checkin up: l_i1.isVisible(stackFrame1);   expected: false");
361                 try {
362                     if (l_i1.isVisible(stackFrame1)) {
363                         log3("ERROR: l_i1.isVisible(stackFrame1)");
364                         expresult = returnCode1;
365                     }
366                 } catch ( IllegalArgumentException e ) {
367                     log3("ERROR:  IllegalArgumentException");
368                     expresult = returnCode1;
369                 }
370 
371                 log2("      checkin up: l_i2.isVisible(stackFrame1);   expected: IllegalArgumentException");
372                 try {
373                     if (l_i2.isVisible(stackFrame1)) {
374                         log3("ERROR: no IllegalArgumentException");
375                         expresult = returnCode1;
376                     }
377                 } catch ( IllegalArgumentException e ) {
378                     log2("     :  IllegalArgumentException");
379                 }
380 
381                 log2("      checkin up: l_i3.isVisible(stackFrame1);   expected: IllegalArgumentException");
382                 try {
383                     if (l_i3.isVisible(stackFrame1)) {
384                         log3("ERROR: no IllegalArgumentException");
385                         expresult = returnCode1;
386                     }
387                 } catch ( IllegalArgumentException e ) {
388                     log2("     :  IllegalArgumentException");
389                 }
390 
391                 log2("      checkin up: l_i1.isVisible(stackFrame);   expected: IllegalArgumentException");
392                 try {
393                     if (l_i1.isVisible(stackFrame)) {
394                         log3("ERROR: no IllegalArgumentException");
395                         expresult = returnCode1;
396                     }
397                 } catch ( IllegalArgumentException e ) {
398                     log2("     :  IllegalArgumentException");
399                 }
400 
401                 log2("      checkin up: l_i2.isVisible(stackFrame);   expected: true");
402                 try {
403                     if (!l_i2.isVisible(stackFrame)) {
404                         log3("ERROR: !l_i2.isVisible(stackFrame)");
405                         expresult = returnCode1;
406                     }
407                 } catch ( IllegalArgumentException e ) {
408                     log3("ERROR:  IllegalArgumentException for i2 in stackFrame");
409                     expresult = returnCode1;
410                 }
411                 log2("      checkin up: l_i3.isVisible(stackFrame);   expected: false");
412                 try {
413                     if (l_i3.isVisible(stackFrame)) {
414                         log3("ERROR: l_i3.isVisible(stackFrame)");
415                         expresult = returnCode1;
416                     }
417                 } catch ( IllegalArgumentException e ) {
418                     log3("ERROR:  IllegalArgumentException for i3 in stackFrame");;
419                     expresult = returnCode1;
420                 }
421             }
422 
423             log2("      resuming the thread2 for case it was suspended but not resumed yet");
424             eventSet.resume();
425 
426             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
427             log2("     the end of testing");
428             if (expresult != returnCode0)
429                 testExitCode = FAILED;
430         }
431         log1("      TESTING ENDS");
432 
433     //--------------------------------------------------   test summary section
434     //-------------------------------------------------    standard end section
435 
436         pipe.println("quit");
437         log2("waiting for the debuggee to finish ...");
438         debuggee.waitFor();
439 
440         int status = debuggee.getStatus();
441         if (status != PASSED + PASS_BASE) {
442             log3("debuggee returned UNEXPECTED exit status: " +
443                     status + " != PASS_BASE");
444             testExitCode = FAILED;
445         } else {
446             log2("debuggee returned expected exit status: " +
447                     status + " == PASS_BASE");
448         }
449 
450         if (testExitCode != PASSED) {
451             logHandler.complain("TEST FAILED");
452         }
453         return testExitCode;
454     }
455 
456 
457    /*
458     * private BreakpointRequest settingBreakpoint(String, String, String)
459     *
460     * It sets up a breakpoint within a given method at given line number
461     * for the thread2 only.
462     * Third parameter is required for any case in future debugging, as if.
463     *
464     * Return codes:
465     *  = BreakpointRequest object  in case of success
466     *  = null   in case of an Exception thrown within the method
467     */
468 
settingBreakpoint( String methodName, String bpLine, String property)469     private BreakpointRequest settingBreakpoint ( String methodName,
470                                                   String bpLine,
471                                                   String property) {
472 
473         log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine );
474 
475         List              alllineLocations = null;
476         Location          lineLocation     = null;
477         BreakpointRequest breakpRequest    = null;
478 
479         try {
480             Method  method  = (Method) testedclass.methodsByName(methodName).get(0);
481 
482             alllineLocations = method.allLineLocations();
483 
484             int n =
485                 ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value();
486             if (n > alllineLocations.size()) {
487                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
488             } else {
489                 lineLocation = (Location) alllineLocations.get(n);
490                 try {
491                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
492                     breakpRequest.putProperty("number", property);
493                     breakpRequest.addThreadFilter(thread2);
494                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
495                 } catch ( Exception e1 ) {
496                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
497                     breakpRequest    = null;
498                 }
499             }
500         } catch ( Exception e2 ) {
501             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
502             breakpRequest    = null;
503         }
504 
505         if (breakpRequest == null)
506             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
507         else
508             log2("      a breakpoint has been set up");
509 
510         return breakpRequest;
511     }
512 
513 
514     /*
515      * private int breakpoint ()
516      *
517      * It removes events from EventQueue until gets first BreakpointEvent.
518      * To get next EventSet value, it uses the method
519      *    EventQueue.remove(int timeout)
520      * The timeout argument passed to the method, is "waitTime*60000".
521      * Note: the value of waitTime is set up with
522      *       the method ArgumentHandler.getWaitTime() at the beginning of the test.
523      *
524      * Return codes:
525      *  = returnCode0 - success;
526      *  = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed
527      *  = returnCode3 - default case when loop of processing an event, that is,
528      *                  an unspecified event was taken from the EventQueue
529      */
530 
breakpoint()531     private int breakpoint () {
532 
533         int returnCode = returnCode0;
534 
535         log2("       waiting for BreakpointEvent");
536 
537         labelBP:
538             for (;;) {
539 
540                 log2("       new:  eventSet = eventQueue.remove();");
541                 try {
542                     eventSet = eventQueue.remove(waitTime*60000);
543                     if (eventSet == null) {
544                         log3("ERROR:  timeout for waiting for a BreakpintEvent");
545                         returnCode = returnCode3;
546                         break labelBP;
547                     }
548                 } catch ( Exception e ) {
549                     log3("ERROR: Exception for  eventSet = eventQueue.remove(); : " + e);
550                     returnCode = 1;
551                     break labelBP;
552                 }
553 
554                 if (eventSet != null) {
555 
556                     log2("     :  eventSet != null;  size == " + eventSet.size());
557 
558                     EventIterator eIter = eventSet.eventIterator();
559                     Event         ev    = null;
560 
561                     for (; eIter.hasNext(); ) {
562 
563                         if (returnCode != returnCode0)
564                             break;
565 
566                         ev = eIter.nextEvent();
567 
568                     ll: for (int ifor =0;  ; ifor++) {
569 
570                         try {
571                           switch (ifor) {
572 
573                           case 0:  AccessWatchpointEvent awe = (AccessWatchpointEvent) ev;
574                                    log2("      AccessWatchpointEvent removed");
575                                    break ll;
576                           case 1:  BreakpointEvent be = (BreakpointEvent) ev;
577                                    log2("      BreakpointEvent removed");
578                                    break labelBP;
579                           case 2:  ClassPrepareEvent cpe = (ClassPrepareEvent) ev;
580                                    log2("      ClassPreparEvent removed");
581                                    break ll;
582                           case 3:  ClassUnloadEvent cue = (ClassUnloadEvent) ev;
583                                    log2("      ClassUnloadEvent removed");
584                                    break ll;
585                           case 4:  ExceptionEvent ee = (ExceptionEvent) ev;
586                                    log2("      ExceptionEvent removed");
587                                    break ll;
588                           case 5:  MethodEntryEvent mene = (MethodEntryEvent) ev;
589                                    log2("      MethodEntryEvent removed");
590                                    break ll;
591                           case 6:  MethodExitEvent mexe = (MethodExitEvent) ev;
592                                    log2("      MethodExiEvent removed");
593                                    break ll;
594                           case 7:  ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev;
595                                    log2("      ModificationWatchpointEvent removed");
596                                    break ll;
597                           case 8:  StepEvent se = (StepEvent) ev;
598                                    log2("      StepEvent removed");
599                                    break ll;
600                           case 9:  ThreadDeathEvent tde = (ThreadDeathEvent) ev;
601                                    log2("      ThreadDeathEvent removed");
602                                    break ll;
603                           case 10: ThreadStartEvent tse = (ThreadStartEvent) ev;
604                                    log2("      ThreadStartEvent removed");
605                                    break ll;
606                           case 11: VMDeathEvent vmde = (VMDeathEvent) ev;
607                                    log2("      VMDeathEvent removed");
608                                    break ll;
609                           case 12: VMStartEvent vmse = (VMStartEvent) ev;
610                                    log2("      VMStartEvent removed");
611                                    break ll;
612                           case 13: WatchpointEvent we = (WatchpointEvent) ev;
613                                    log2("      WatchpointEvent removed");
614                                    break ll;
615 
616                           default: log3("ERROR:  default case for casting event");
617                                    returnCode = returnCode3;
618                                    break ll;
619                           } // switch
620                         } catch ( ClassCastException e ) {
621                         }   // try
622                     }       // ll: for (int ifor =0;  ; ifor++)
623                 }           // for (; ev.hasNext(); )
624             }
625         }
626         if (returnCode == returnCode0)
627             log2("     :  eventSet == null:  EventQueue is empty");
628 
629         return returnCode;
630     }
631 
632 }
633