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.WatchpointRequest.field;
25 
26 import nsk.share.*;
27 import nsk.share.jpda.*;
28 import nsk.share.jdi.*;
29 
30 import com.sun.jdi.*;
31 import com.sun.jdi.event.*;
32 import com.sun.jdi.request.*;
33 
34 import java.util.*;
35 import java.io.*;
36 
37 /**
38  * The test for the implementation of an object of the type     <BR>
39  * WatchpointRequest.                                           <BR>
40  *                                                              <BR>
41  * The test checks that results of the method                   <BR>
42  * <code>com.sun.jdi.WatchpointRequest.field()</code>           <BR>
43  * complies with its spec.                                              <BR>
44  * <BR>
45  *  The case to test include AccessWatchpointRequest.                   <BR>
46  *  The test checks if a Field object, an argument of the method        <BR>
47  *     EventRequestManager.createAccessWatchpointRequest(Field),        <BR>
48  *  is equal to one returned by the method WatchpointRequest.field()    <BR>
49  * <BR>
50  * The test has three phases and works as follows.                      <BR>
51  * <BR>
52  * In first phase,                                                      <BR>
53  * upon launching debuggee's VM which will be suspended,                <BR>
54  * a debugger waits for the VMStartEvent within a predefined            <BR>
55  * time interval. If no the VMStartEvent received, the test is FAILED.  <BR>
56  * Upon getting the VMStartEvent, it makes the request for debuggee's   <BR>
57  * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,         <BR>
58  * and waits for the event within the predefined time interval.         <BR>
59  * If no the ClassPrepareEvent received, the test is FAILED.            <BR>
60  * Upon getting the ClassPrepareEvent,                                  <BR>
61  * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD        <BR>
62  * within debuggee's special methodForCommunication().                  <BR>
63  * <BR>
64  * In second phase to check the assertion,                              <BR>
65  * the debugger and the debuggee perform the following.                 <BR>
66  * - The debugger resumes the debuggee and waits for the BreakpointEvent.<BR>
67  * - The debuggee invokes the methodForCommunication to be suspended    <BR>
68  *   and to inform the debugger with the event.                         <BR>
69  * - Upon getting the BreakpointEvent, the debugger                     <BR>
70  *   - creates an AccessWatchpointRequest and gets Field object filed1, <BR>
71  *   - gets Field object field2 with the method WatchpointRequest.field(),<BR>
72  *   - compares the Filed objects.                                      <BR>
73  * <BR>
74  * In third phase, at the end of the test, the debuggee changes         <BR>
75  * the value of the "instruction" which the debugger and debuggee       <BR>
76  * use to inform each other of needed actions,  and both end.           <BR>
77  * <BR>
78  */
79 
80 public class field001 {
81 
82     //----------------------------------------------------- templete section
83     static final int PASSED = 0;
84     static final int FAILED = 2;
85     static final int PASS_BASE = 95;
86 
87     //----------------------------------------------------- templete parameters
88     static final String
89     sHeader1 = "\n==> nsk/jdi/WatchpointRequest/field/field001 ",
90     sHeader2 = "--> debugger: ",
91     sHeader3 = "##> debugger: ";
92 
93     //----------------------------------------------------- main method
94 
main(String argv[])95     public static void main (String argv[]) {
96 
97         int result = run(argv, System.out);
98 
99         System.exit(result + PASS_BASE);
100     }
101 
run(String argv[], PrintStream out)102     public static int run (String argv[], PrintStream out) {
103 
104         int exitCode = new field001().runThis(argv, out);
105 
106         if (exitCode != PASSED) {
107             System.out.println("TEST FAILED");
108         }
109         return testExitCode;
110     }
111 
112     //--------------------------------------------------   log procedures
113 
114     private static Log  logHandler;
115 
log1(String message)116     private static void log1(String message) {
117         logHandler.display(sHeader1 + message);
118     }
log2(String message)119     private static void log2(String message) {
120         logHandler.display(sHeader2 + message);
121     }
log3(String message)122     private static void log3(String message) {
123         logHandler.complain(sHeader3 + message);
124     }
125 
126     //  ************************************************    test parameters
127 
128     private String debuggeeName =
129         "nsk.jdi.WatchpointRequest.field.field001a";
130 
131     private String testedClassName1 =
132       "nsk.jdi.WatchpointRequest.field.TestClass10";
133 
134     Field field1 = null;
135     Field field2 = null;
136 
137     //====================================================== test program
138     //------------------------------------------------------ common section
139 
140     static Debugee          debuggee;
141     static ArgumentHandler  argsHandler;
142 
143     static int waitTime;
144 
145     static VirtualMachine      vm            = null;
146     static EventRequestManager eventRManager = null;
147     static EventQueue          eventQueue    = null;
148     static EventSet            eventSet      = null;
149     static EventIterator       eventIterator = null;
150 
151     static ReferenceType       debuggeeClass = null;
152 
153     static int  testExitCode = PASSED;
154 
155 
156     class JDITestRuntimeException extends RuntimeException {
JDITestRuntimeException(String str)157         JDITestRuntimeException(String str) {
158             super("JDITestRuntimeException : " + str);
159         }
160     }
161 
162     //------------------------------------------------------ methods
163 
runThis(String argv[], PrintStream out)164     private int runThis (String argv[], PrintStream out) {
165 
166         argsHandler     = new ArgumentHandler(argv);
167         logHandler      = new Log(out, argsHandler);
168         Binder binder   = new Binder(argsHandler, logHandler);
169 
170         waitTime        = argsHandler.getWaitTime() * 60000;
171 
172         try {
173             log2("launching a debuggee :");
174             log2("       " + debuggeeName);
175             if (argsHandler.verbose()) {
176                 debuggee = binder.bindToDebugee(debuggeeName + " -vbs");
177             } else {
178                 debuggee = binder.bindToDebugee(debuggeeName);
179             }
180             if (debuggee == null) {
181                 log3("ERROR: no debuggee launched");
182                 return FAILED;
183             }
184             log2("debuggee launched");
185         } catch ( Exception e ) {
186             log3("ERROR: Exception : " + e);
187             log2("       test cancelled");
188             return FAILED;
189         }
190 
191         debuggee.redirectOutput(logHandler);
192 
193         vm = debuggee.VM();
194 
195         eventQueue = vm.eventQueue();
196         if (eventQueue == null) {
197             log3("ERROR: eventQueue == null : TEST ABORTED");
198             vm.exit(PASS_BASE);
199             return FAILED;
200         }
201 
202         log2("invocation of the method runTest()");
203         switch (runTest()) {
204 
205             case 0 :  log2("test phase has finished normally");
206                       log2("   waiting for the debuggee to finish ...");
207                       debuggee.waitFor();
208 
209                       log2("......getting the debuggee's exit status");
210                       int status = debuggee.getStatus();
211                       if (status != PASS_BASE) {
212                           log3("ERROR: debuggee returned UNEXPECTED exit status: " +
213                               status + " != PASS_BASE");
214                           testExitCode = FAILED;
215                       } else {
216                           log2("......debuggee returned expected exit status: " +
217                               status + " == PASS_BASE");
218                       }
219                       break;
220 
221             default : log3("ERROR: runTest() returned unexpected value");
222 
223             case 1 :  log3("test phase has not finished normally: debuggee is still alive");
224                       log2("......forcing: vm.exit();");
225                       testExitCode = FAILED;
226                       try {
227                           vm.exit(PASS_BASE);
228                       } catch ( Exception e ) {
229                           log3("ERROR: Exception : " + e);
230                       }
231                       break;
232 
233             case 2 :  log3("test cancelled due to VMDisconnectedException");
234                       log2("......trying: vm.process().destroy();");
235                       testExitCode = FAILED;
236                       try {
237                           Process vmProcess = vm.process();
238                           if (vmProcess != null) {
239                               vmProcess.destroy();
240                           }
241                       } catch ( Exception e ) {
242                           log3("ERROR: Exception : " + e);
243                       }
244                       break;
245             }
246 
247         return testExitCode;
248     }
249 
250 
251    /*
252     * Return value: 0 - normal end of the test
253     *               1 - ubnormal end of the test
254     *               2 - VMDisconnectedException while test phase
255     */
256 
runTest()257     private int runTest() {
258 
259         try {
260             testRun();
261 
262             log2("waiting for VMDeathEvent");
263             getEventSet();
264             if (eventIterator.nextEvent() instanceof VMDeathEvent)
265                 return 0;
266 
267             log3("ERROR: last event is not the VMDeathEvent");
268             return 1;
269         } catch ( VMDisconnectedException e ) {
270             log3("ERROR: VMDisconnectedException : " + e);
271             return 2;
272         } catch ( Exception e ) {
273             log3("ERROR: Exception : " + e);
274             return 1;
275         }
276 
277     }
278 
testRun()279     private void testRun()
280                  throws JDITestRuntimeException, Exception {
281 
282         eventRManager = vm.eventRequestManager();
283 
284         ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest();
285         cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
286         cpRequest.addClassFilter(debuggeeName);
287 
288         cpRequest.enable();
289         vm.resume();
290         getEventSet();
291         cpRequest.disable();
292 
293         ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next();
294         debuggeeClass = event.referenceType();
295 
296         if (!debuggeeClass.name().equals(debuggeeName))
297            throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **");
298 
299         log2("      received: ClassPrepareEvent for debuggeeClass");
300 
301         String bPointMethod = "methodForCommunication";
302         String lineForComm  = "lineForComm";
303 
304         ThreadReference   mainThread = threadByName("main");
305 
306         BreakpointRequest bpRequest = settingBreakpoint(mainThread,
307                                              debuggeeClass,
308                                             bPointMethod, lineForComm, "zero");
309         bpRequest.enable();
310 
311     //------------------------------------------------------  testing section
312 
313         log1("     TESTING BEGINS");
314 
315         EventRequest  eventRequest1 = null;
316         String        property1     = "AccessWatchpointRequest1";
317         String        fieldName1    = "var101";
318 
319         ReferenceType testClassReference = null;
320 
321 
322         for (int i = 0; ; i++) {
323 
324             vm.resume();
325             breakpointForCommunication();
326 
327             int instruction = ((IntegerValue)
328                                (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value();
329 
330             if (instruction == 0) {
331                 vm.resume();
332                 break;
333             }
334 
335 
336             log1(":::::: case: # " + i);
337 
338             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part
339 
340             switch (i) {
341 
342               case 0:
343                      testClassReference =
344                            (ReferenceType) vm.classesByName(testedClassName1).get(0);
345 
346                      log2("......setting up AccessWatchpointRequest and getting Field object field1");
347                      eventRequest1 = setting21AccessWatchpointRequest (null,
348                                              testClassReference, fieldName1,
349                                              EventRequest.SUSPEND_NONE, property1);
350 
351                      log2("......getting: field2 = ((WatchpointRequest) eventRequest1).field();");
352                      field2 = ((WatchpointRequest) eventRequest1).field();
353 
354                      log2("      checking up on equality of field1 and field2");
355                      if ( !field1.equals(field2) ) {
356                          testExitCode = FAILED;
357                          log3("ERROR: Field objects are not equal");
358                      }
359 
360                       break;
361 
362               default:
363                       throw new JDITestRuntimeException("** default case 2 **");
364             }
365 
366             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367         }
368         log1("    TESTING ENDS");
369         return;
370     }
371 
threadByName(String name)372     private ThreadReference threadByName(String name)
373                  throws JDITestRuntimeException {
374 
375         List         all = vm.allThreads();
376         ListIterator li  = all.listIterator();
377 
378         for (; li.hasNext(); ) {
379             ThreadReference thread = (ThreadReference) li.next();
380             if (thread.name().equals(name))
381                 return thread;
382         }
383         throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name);
384     }
385 
386    /*
387     * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType,
388     *                                             String, String, String)
389     *
390     * It sets up a breakpoint at given line number within a given method in a given class
391     * for a given thread.
392     *
393     * Return value: BreakpointRequest object  in case of success
394     *
395     * JDITestRuntimeException   in case of an Exception thrown within the method
396     */
397 
settingBreakpoint( ThreadReference thread, ReferenceType testedClass, String methodName, String bpLine, String property)398     private BreakpointRequest settingBreakpoint ( ThreadReference thread,
399                                                   ReferenceType testedClass,
400                                                   String methodName,
401                                                   String bpLine,
402                                                   String property)
403             throws JDITestRuntimeException {
404 
405         log2("......setting up a breakpoint:");
406         log2("       thread: " + thread + "; class: " + testedClass +
407                         "; method: " + methodName + "; line: " + bpLine);
408 
409         List              alllineLocations = null;
410         Location          lineLocation     = null;
411         BreakpointRequest breakpRequest    = null;
412 
413         try {
414             Method  method  = (Method) testedClass.methodsByName(methodName).get(0);
415 
416             alllineLocations = method.allLineLocations();
417 
418             int n =
419                 ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value();
420             if (n > alllineLocations.size()) {
421                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
422             } else {
423                 lineLocation = (Location) alllineLocations.get(n);
424                 try {
425                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
426                     breakpRequest.putProperty("number", property);
427                     breakpRequest.addThreadFilter(thread);
428                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
429                 } catch ( Exception e1 ) {
430                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
431                     breakpRequest    = null;
432                 }
433             }
434         } catch ( Exception e2 ) {
435             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
436             breakpRequest    = null;
437         }
438 
439         if (breakpRequest == null) {
440             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
441             throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**");
442         }
443 
444         log2("      a breakpoint has been set up");
445         return breakpRequest;
446     }
447 
448 
getEventSet()449     private void getEventSet()
450                  throws JDITestRuntimeException {
451         try {
452 //            log2("       eventSet = eventQueue.remove(waitTime);");
453             eventSet = eventQueue.remove(waitTime);
454             if (eventSet == null) {
455                 throw new JDITestRuntimeException("** TIMEOUT while waiting for event **");
456             }
457 //            log2("       eventIterator = eventSet.eventIterator;");
458             eventIterator = eventSet.eventIterator();
459         } catch ( Exception e ) {
460             throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e);
461         }
462     }
463 
464 
breakpointForCommunication()465     private void breakpointForCommunication()
466                  throws JDITestRuntimeException {
467 
468         log2("breakpointForCommunication");
469         getEventSet();
470 
471         if (eventIterator.nextEvent() instanceof BreakpointEvent)
472             return;
473 
474         throw new JDITestRuntimeException("** event IS NOT a breakpoint **");
475     }
476 
477     // ============================== test's additional methods
478 
setting21AccessWatchpointRequest( ThreadReference thread, ReferenceType fieldClass, String fieldName, int suspendPolicy, String property )479     private AccessWatchpointRequest setting21AccessWatchpointRequest (
480                                                   ThreadReference thread,
481                                                   ReferenceType   fieldClass,
482                                                   String          fieldName,
483                                                   int             suspendPolicy,
484                                                   String          property        )
485             throws JDITestRuntimeException {
486         try {
487             log2("......setting up AccessWatchpointRequest:");
488             log2("       thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName);
489             Field field = fieldClass.fieldByName(fieldName);
490 
491             field1 = field;
492 
493             AccessWatchpointRequest
494             awr = eventRManager.createAccessWatchpointRequest(field);
495             awr.putProperty("number", property);
496 
497             if (thread != null)
498                 awr.addThreadFilter(thread);
499             awr.setSuspendPolicy(suspendPolicy);
500 
501             log2("      AccessWatchpointRequest has been set up");
502             return awr;
503         } catch ( Exception e ) {
504             log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e);
505             log3("       AccessWatchpointRequest HAS NOT BEEN SET UP");
506             throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **");
507         }
508     }
509 
510 }
511