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