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.ModificationWatchpointEvent.valueToBe;
25 
26 import com.sun.jdi.*;
27 import com.sun.jdi.event.*;
28 import com.sun.jdi.request.*;
29 
30 import java.io.*;
31 import java.util.Iterator;
32 import java.util.List;
33 
34 import nsk.share.*;
35 import nsk.share.jpda.*;
36 import nsk.share.jdi.*;
37 
38 
39 // This class is the debugger in the test
40 
41 public class valuetobe002 {
42     static final int PASSED = 0;
43     static final int FAILED = 2;
44     static final int JCK_STATUS_BASE = 95;
45 
46     static final int TIMEOUT_DELTA = 1000; // milliseconds
47 
48     static final String COMMAND_READY = "ready";
49     static final String COMMAND_QUIT  = "quit";
50     static final String COMMAND_GO    = "go";
51     static final String COMMAND_DONE  = "done";
52 
53     static final String DEBUGEE_NAME  = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002a";
54     static final String CHECKED_CLASS_NAME = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002aCheckedClass";
55 
56     static private Debugee debuggee;
57     static private VirtualMachine vm;
58     static private IOPipe pipe;
59     static private Log log;
60     static private ArgumentHandler argHandler;
61     static private EventSet eventSet;
62 
63     static private ReferenceType rType;
64     static private ModificationWatchpointRequest wpRequest;
65     static private List fieldsList;
66 
67     static private volatile boolean testFailed;
68     static private volatile boolean done;
69     static private volatile int requestsCount, mwpEventsCount;
70 
main(String args[])71     public static void main (String args[]) {
72           System.exit(run(args, System.out) + JCK_STATUS_BASE);
73     }
74 
run(final String args[], final PrintStream out)75     public static int run(final String args[], final PrintStream out) {
76 
77         testFailed = false;
78         requestsCount = 0;
79         mwpEventsCount = 0;
80 
81         argHandler = new ArgumentHandler(args);
82         log = new Log(out, argHandler);
83 
84         // launch debuggee
85         Binder binder = new Binder(argHandler, log);
86         log.display("Connecting to debuggee");
87         debuggee = binder.bindToDebugee(DEBUGEE_NAME);
88         debuggee.redirectStderr(log, "valuetobe001a >");
89 
90         // resume debuggee
91         log.display("Resuming debuggee");
92         debuggee.resume();
93 
94         pipe = debuggee.createIOPipe();
95         vm = debuggee.VM();
96 
97         // check for debuggee's capabilities
98         if (!debuggee.VM().canWatchFieldModification()) {
99               log.display("TEST WARNING: test passed because JDI implementation does not support " +
100                  "watchpoints for field modification");
101               pipe.println(COMMAND_QUIT);
102               debuggee.waitFor();
103               return PASSED;
104         }
105 
106         try {
107 
108             // wait for debuggee started
109             log.display("Waiting for command: " + COMMAND_READY);
110             String command = pipe.readln();
111             if (!command.equals(COMMAND_READY)) {
112                 throw new Failure("TEST BUG: unexpected debuggee's command: " + command);
113             }
114 
115             // get mirrors
116             if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) {
117                 throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME);
118             }
119 
120             // create events requests
121             log.display("Creating requests for WatchpointEvent");
122             EventRequestManager erManager = debuggee.VM().eventRequestManager();
123             Iterator fieldsIter;
124             try {
125                 fieldsList = rType.fields();
126                 fieldsIter = fieldsList.iterator();
127             } catch (ClassNotPreparedException e) {
128                 throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared");
129             }
130             while (fieldsIter.hasNext()) {
131                 Field refField = (Field)fieldsIter.next();
132                 if ((wpRequest = erManager.createModificationWatchpointRequest(refField)) == null) {
133                     throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest");
134                 } else {
135                     log.display("ModificationWatchpointRequest for field " +  refField.name() + " created");
136                     wpRequest.enable();
137                 }
138                 requestsCount++;
139             }
140             log.display("Created total " + requestsCount + " ModificationWatchpointRequests");
141 
142             // define separate thread for handling events
143             class EventHandler extends Thread {
144                   public void run() {
145                        eventSet = null;
146                        try {
147                             // handle events until all events generated and received
148                             while (mwpEventsCount < requestsCount) {
149                                  eventSet = null;
150                                  eventSet = vm.eventQueue().remove(TIMEOUT_DELTA);
151 
152                                  if (eventSet == null)
153                                      continue;
154 
155                                  EventIterator eventIterator = eventSet.eventIterator();
156                                  while (eventIterator.hasNext()) {
157 
158                                      Event event = eventIterator.nextEvent();
159 
160                                      // handle ModificationWatchpointEvent
161                                      if (event instanceof ModificationWatchpointEvent) {
162                                          mwpEventsCount++;
163                                          ModificationWatchpointEvent castedEvent = (ModificationWatchpointEvent)event;
164                                          Value evValue = castedEvent.valueToBe();
165                                          Field evField = castedEvent.field();
166                                          log.display("ModificationWatchpointEvent received for " + evField.name());
167                                          if (evValue == null) {
168                                                log.complain("FAILURE 3: ModificationWatchpointEvent.valueToBe() returns null for " + evField.name());
169                                                testFailed = true;
170                                          } else {
171                                                int ind = fieldsList.indexOf(evField);
172                                                if (ind == -1) {
173                                                     log.complain("FAILURE 2: ModificationWatchpoint.field() returns unknown field");
174                                                     testFailed = true;
175                                                } else {
176                                                     Value valueNew = castedEvent.valueToBe();
177                                                     Value valueNew1= castedEvent.valueToBe();
178 
179                                                     if (!valueNew.equals(valueNew1)) {
180                                                         log.complain("FAILURE 3: method valueToBe() returns inconsistent results for " +
181                                                             evField.name() + "\nvalueNew: " + valueNew + " ; valueNew1: " + valueNew1);
182                                                         testFailed = true;
183                                                     }
184 
185                                                     Value valueFld = castedEvent.valueCurrent();
186 
187                                                     if (!valueFld.equals(valueNew)) {
188                                                         log.complain("FAILURE 4: method valueToBe() returns incorrect equal value for " +
189                                                             evField.name() + "\nvaluetoBe(): " + valueNew + " ; valueCurrent(): " + valueFld);
190                                                         testFailed = true;
191                                                     } else {
192                                                         log.display(evField.name() + " is assigned to " + castedEvent.valueToBe().toString());
193                                                     }
194                                                }
195                                           }
196                                      }
197                                 }
198                                 // resume each handled event set
199                                 eventSet.resume();
200                             }
201                        } catch (InterruptedException e) {
202                              log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event");
203                              testFailed = true;
204                        } catch (VMDisconnectedException e) {
205                              log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event");
206                              testFailed = true;
207                        }
208                        log.display("eventHandler completed");
209                   }
210             }
211 
212             // start event handling thread
213             EventHandler eventHandler = new EventHandler();
214             log.display("Starting eventHandler");
215             eventHandler.start();
216 
217             // force debuggee to generate events
218             log.display("Sending command: " + COMMAND_GO);
219             pipe.println(COMMAND_GO);
220 
221             // wait for confirmation from debugee
222             log.display("Waiting for command: " + COMMAND_DONE);
223             command = pipe.readln();
224             if (command == null || !command.equals(COMMAND_DONE)) {
225                 throw new Failure("TEST BUG: unexpected debuggee's command: " + command);
226             }
227 
228             // notify EventHandler that all events generated
229             done = true;
230 
231             // wait for all expected events received
232             log.display("Waiting for all expected events received");
233             try {
234                 eventHandler.join(argHandler.getWaitTime()*60000);
235                 if (eventHandler.isAlive()) {
236                     log.complain("FAILURE 20: Timeout for waiting of event was exceeded");
237                     eventHandler.interrupt();
238                     testFailed = true;
239                 }
240             } catch (InterruptedException e) {
241                 log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death");
242                 testFailed = true;
243             }
244         } catch (Failure e) {
245             log.complain("TEST FAILURE: " + e.getMessage());
246             testFailed = true;
247         } catch (Exception e) {
248             log.complain("Unexpected exception: " + e);
249             e.printStackTrace(out);
250             testFailed = true;
251         } finally {
252 
253             log.display("");
254 
255             // force debugee to exit
256             log.display("Sending command: " + COMMAND_QUIT);
257             pipe.println(COMMAND_QUIT);
258 
259             // wait for debuggee exits and analize its exit code
260             log.display("Waiting for debuggee terminating");
261             int debuggeeStatus = debuggee.endDebugee();
262             if (debuggeeStatus == PASSED + JCK_STATUS_BASE) {
263                 log.display("Debuggee PASSED with exit code: " + debuggeeStatus);
264             } else {
265                 log.complain("Debuggee FAILED with exit code: " + debuggeeStatus);
266                 testFailed = true;
267             }
268         }
269 
270         // check test results
271         if (testFailed) {
272             log.complain("TEST FAILED");
273             return FAILED;
274         }
275 
276         log.display("TEST PASSED");
277         return PASSED;
278     }
279 }
280