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