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.WatchpointEvent.valueCurrent; 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 valuecur001 { 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 DEBUGGEE_NAME = "nsk.jdi.WatchpointEvent.valueCurrent.valuecur001a"; 54 static final String CHECKED_CLASS_NAME = "nsk.jdi.WatchpointEvent.valueCurrent.CheckedClass"; 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 WatchpointRequest checkedRequest; 65 static private List fieldsList; 66 67 static private volatile boolean testFailed; 68 static private volatile boolean done; 69 static private volatile int requestsCount, awpEventsCount, 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 awpEventsCount = 0; 80 mwpEventsCount = 0; 81 82 argHandler = new ArgumentHandler(args); 83 log = new Log(out, argHandler); 84 85 // launch debuggee 86 Binder binder = new Binder(argHandler, log); 87 log.display("Connecting to debuggee"); 88 debuggee = binder.bindToDebugee(DEBUGGEE_NAME); 89 debuggee.redirectStderr(log, "valuecur001a >"); 90 pipe = debuggee.createIOPipe(); 91 vm = debuggee.VM(); 92 93 // resume debuggee 94 log.display("Resuming debuggee"); 95 debuggee.resume(); 96 97 // check debuggee's capabilities 98 if (!debuggee.VM().canWatchFieldAccess()) { 99 log.display("TEST WARNING: test passed because JDI implementation does not support " + 100 "watchpoints for field access"); 101 pipe.println(COMMAND_QUIT); 102 debuggee.waitFor(); 103 return PASSED; 104 } 105 106 if (!debuggee.VM().canWatchFieldModification()) { 107 log.display("TEST WARNING: test passed because JDI implementation does not support " + 108 "watchpoints for field modification"); 109 pipe.println(COMMAND_QUIT); 110 debuggee.waitFor(); 111 return PASSED; 112 } 113 114 try { 115 116 // wait for debuggee started 117 log.display("Waiting for command: " + COMMAND_READY); 118 String command = pipe.readln(); 119 if (!command.equals(COMMAND_READY)) { 120 throw new Failure("TEST BUG: unexpected debuggee's command: " + command); 121 } 122 123 // get mirrors 124 if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { 125 throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); 126 } 127 128 // create events requests 129 log.display("Creating requests for WatchpointEvent"); 130 EventRequestManager erManager = debuggee.VM().eventRequestManager(); 131 Iterator fieldsIter; 132 try { 133 fieldsList = rType.fields(); 134 fieldsIter = fieldsList.iterator(); 135 } catch (ClassNotPreparedException e) { 136 throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared"); 137 } 138 while (fieldsIter.hasNext()) { 139 Field refField = (Field)fieldsIter.next(); 140 if ((checkedRequest = erManager.createAccessWatchpointRequest(refField)) == null) { 141 throw new Failure("TEST BUG: unable to create AccessWatchpointRequest"); 142 } else { 143 log.display("AccessWatchpointRequest for field " + refField.name() + " created"); 144 checkedRequest.enable(); 145 } 146 if ((checkedRequest = erManager.createModificationWatchpointRequest(refField)) == null) { 147 throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); 148 } else { 149 log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); 150 checkedRequest.enable(); 151 } 152 requestsCount++; 153 } 154 log.display("Created total " + requestsCount + " WatchpointRequests"); 155 156 // define separate thread for handling events 157 class EventHandler extends Thread { 158 public void run() { 159 eventSet = null; 160 try { 161 // handle events until all events generated and received 162 while ( awpEventsCount < requestsCount 163 || mwpEventsCount < requestsCount ) { 164 165 eventSet = null; 166 eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); 167 168 if (eventSet == null) 169 continue; 170 171 EventIterator eventIterator = eventSet.eventIterator(); 172 while (eventIterator.hasNext()) { 173 174 Event event = eventIterator.nextEvent(); 175 176 // handle WatchpointEvent 177 if (event instanceof WatchpointEvent) { 178 WatchpointEvent castedEvent = (WatchpointEvent)event; 179 Value evValue = castedEvent.valueCurrent(); 180 Field evField = castedEvent.field(); 181 182 if (event instanceof AccessWatchpointEvent) { 183 awpEventsCount++; 184 log.display("AccessWatchpointEvent received for " + evField.name()); 185 } else if (event instanceof ModificationWatchpointEvent) { 186 mwpEventsCount++; 187 log.display("ModificationWatchpointEvent received for " + evField.name()); 188 } 189 190 if (evValue == null) { 191 log.complain("FAILURE 1: WatchpointEvent.valueCurrent() returns null for " + evField.name()); 192 testFailed = true; 193 } else { 194 int ind = fieldsList.indexOf(evField); 195 if (ind == -1) { 196 log.complain("FAILURE 2: Watchpoint.field() returns unknown field"); 197 testFailed = true; 198 } else { 199 Value valueCur = castedEvent.valueCurrent(); 200 Value valueFld; 201 try { 202 valueFld = castedEvent.object().getValue(evField); 203 } catch (NullPointerException e) { 204 // field is static 205 valueFld = rType.getValue(evField); 206 } 207 if (!valueFld.equals(valueCur)) { 208 log.complain("FAILURE 3: Watchpoint.valueCurrent() returns incorrect value for " + 209 evField.name() + "\nvalueCurrent(): " + valueCur + " ; getValue(): " + valueFld); 210 testFailed = true; 211 } else { 212 valuecur001.log.display(evField.name() + " equals to " + castedEvent.valueCurrent().toString()); 213 } 214 } 215 } 216 } 217 } 218 eventSet.resume(); 219 } 220 } catch (InterruptedException e) { 221 log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); 222 testFailed = true; 223 } catch (VMDisconnectedException e) { 224 log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); 225 testFailed = true; 226 } 227 log.display("eventHandler completed"); 228 } 229 } 230 231 // start event handling thread 232 EventHandler eventHandler = new EventHandler(); 233 log.display("Starting eventHandler"); 234 eventHandler.start(); 235 236 // force debuggee to generate events 237 log.display("Sending command: " + COMMAND_GO); 238 pipe.println(COMMAND_GO); 239 240 // wait for confirmation from debugee 241 log.display("Waiting for command: " + COMMAND_DONE); 242 command = pipe.readln(); 243 if (command == null || !command.equals(COMMAND_DONE)) { 244 throw new Failure("TEST BUG: unexpected debuggee's command: " + command); 245 } 246 247 // notify EventHandler that all events generated 248 done = true; 249 250 // wait for all expected events received 251 log.display("Waiting for all expected events received"); 252 try { 253 eventHandler.join(argHandler.getWaitTime()*60000); 254 if (eventHandler.isAlive()) { 255 log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); 256 eventHandler.interrupt(); 257 testFailed = true; 258 } 259 } catch (InterruptedException e) { 260 log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); 261 testFailed = true; 262 } 263 } catch (Failure e) { 264 log.complain("TEST FAILURE: " + e.getMessage()); 265 testFailed = true; 266 } catch (Exception e) { 267 log.complain("Unexpected exception: " + e); 268 e.printStackTrace(out); 269 testFailed = true; 270 } finally { 271 272 log.display(""); 273 274 // force debugee to exit 275 log.display("Sending command: " + COMMAND_QUIT); 276 pipe.println(COMMAND_QUIT); 277 278 // wait for debuggee exits and analize its exit code 279 log.display("Waiting for debuggee terminating"); 280 int debuggeeStatus = debuggee.endDebugee(); 281 if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { 282 log.display("Debuggee PASSED with exit code: " + debuggeeStatus); 283 } else { 284 log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); 285 testFailed = true; 286 } 287 } 288 289 // check test results 290 if (testFailed) { 291 log.complain("TEST FAILED"); 292 return FAILED; 293 } 294 295 log.display("TEST PASSED"); 296 return PASSED; 297 } 298 } 299