1 /* 2 * Copyright (c) 2006, 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 package nsk.share.jdi; 24 25 import java.io.PrintStream; 26 import java.lang.reflect.*; 27 import java.util.*; 28 29 import com.sun.jdi.*; 30 import com.sun.jdi.event.*; 31 import com.sun.jdi.request.*; 32 import nsk.share.TestBug; 33 34 /* 35 * Class is used as base debugger in tests for following events and event requests: 36 * - MonitorContendedEnterRequest / MonitorContendedEnterEvent 37 * - MonitorContendedEnteredRequest / MonitorContendedEnteredEvent 38 * - MonitorWaitRequest / MonitorWaitEvent 39 * - MonitorWaitedRequest / MonitorWaitedEvent 40 * 41 * In all these tests similar scenario is used: 42 * - debugger VM forces debuggee VM to create number of objects which should generate events during test 43 * - if any event filters are used each generating event object is checked is this object accepted by all filters, 44 * if object was accepted it should save information about all generated events and this information is available for debugger 45 * - debuggee performs event generation and stop at breakpoint 46 * - debugger reads data saved by event generators and checks is only expected events was generated 47 */ 48 public class JDIEventsDebugger extends TestDebuggerType2 { 49 // types of tested events 50 static public enum EventType { 51 MONITOR_CONTENTED_ENTER, 52 MONITOR_CONTENTED_ENTERED, 53 MONITOR_WAIT, 54 MONITOR_WAITED 55 } 56 57 /* 58 * Class contains information required for event testing 59 */ 60 static class TestedEventData { 61 // event class 62 public Class<?> eventClass; 63 64 // class representing event data on debuggee's side 65 public Class<?> eventDataMirrorClass; 66 67 // class representing event data on debugger's side 68 public Class<?> eventDataClass; 69 TestedEventData(Class<?> eventClass, Class<?> eventDataMirrorClass, Class<?> eventDataClass)70 public TestedEventData(Class<?> eventClass, Class<?> eventDataMirrorClass, Class<?> eventDataClass) { 71 this.eventClass = eventClass; 72 this.eventDataMirrorClass = eventDataMirrorClass; 73 this.eventDataClass = eventDataClass; 74 } 75 } 76 77 static public Map<EventType, TestedEventData> testedEventData = new HashMap<EventType, TestedEventData>(); 78 79 static { testedEventData.put(EventType.MONITOR_CONTENTED_ENTER, new TestedEventData(MonitorContendedEnterEvent.class, DebuggeeEventData.DebugMonitorEnterEventData.class, DebuggerEventData.DebugMonitorEnterEventData.class))80 testedEventData.put(EventType.MONITOR_CONTENTED_ENTER, new TestedEventData(MonitorContendedEnterEvent.class, 81 DebuggeeEventData.DebugMonitorEnterEventData.class, DebuggerEventData.DebugMonitorEnterEventData.class)); 82 testedEventData.put(EventType.MONITOR_CONTENTED_ENTERED, new TestedEventData(MonitorContendedEnteredEvent.class, DebuggeeEventData.DebugMonitorEnteredEventData.class, DebuggerEventData.DebugMonitorEnteredEventData.class))83 testedEventData.put(EventType.MONITOR_CONTENTED_ENTERED, new TestedEventData(MonitorContendedEnteredEvent.class, 84 DebuggeeEventData.DebugMonitorEnteredEventData.class, DebuggerEventData.DebugMonitorEnteredEventData.class)); 85 testedEventData.put(EventType.MONITOR_WAIT, new TestedEventData(MonitorWaitEvent.class, DebuggeeEventData.DebugMonitorWaitEventData.class, DebuggerEventData.DebugMonitorWaitEventData.class))86 testedEventData.put(EventType.MONITOR_WAIT, new TestedEventData(MonitorWaitEvent.class, DebuggeeEventData.DebugMonitorWaitEventData.class, 87 DebuggerEventData.DebugMonitorWaitEventData.class)); 88 testedEventData.put(EventType.MONITOR_WAITED, new TestedEventData(MonitorWaitedEvent.class, DebuggeeEventData.DebugMonitorWaitedEventData.class, DebuggerEventData.DebugMonitorWaitedEventData.class))89 testedEventData.put(EventType.MONITOR_WAITED, new TestedEventData(MonitorWaitedEvent.class, 90 DebuggeeEventData.DebugMonitorWaitedEventData.class, DebuggerEventData.DebugMonitorWaitedEventData.class)); 91 } 92 eventDataByEventTypes(EventType[] eventTypes)93 static public TestedEventData[] eventDataByEventTypes(EventType[] eventTypes) { 94 TestedEventData[] result = new TestedEventData[eventTypes.length]; 95 96 int i = 0; 97 for (EventType eventType : eventTypes) { 98 TestedEventData eventData = testedEventData.get(eventType); 99 100 if (eventData == null) 101 throw new TestBug("Unsupported event type: " + eventType); 102 103 result[i++] = eventData; 104 } 105 106 return result; 107 } 108 109 /* 110 * Dummy event listener, just accepts all events 111 */ 112 public class DummyEventListener extends EventHandler.EventListener { 113 private volatile boolean breakpointEventReceived; 114 eventReceived(Event event)115 public boolean eventReceived(Event event) { 116 if (event instanceof BreakpointEvent) { 117 breakpointEventReceived = true; 118 vm.resume(); 119 } 120 121 return true; 122 } 123 waitBreakpoint()124 public void waitBreakpoint() { 125 while (!breakpointEventReceived) 126 Thread.yield(); 127 } 128 } 129 130 /* 131 * Parse common for event tests parameters 132 */ doInit(String[] args, PrintStream out)133 protected String[] doInit(String[] args, PrintStream out) { 134 args = super.doInit(args, out); 135 136 ArrayList<String> standardArgs = new ArrayList<String>(); 137 138 for (int i = 0; i < args.length; i++) { 139 if (args[i].equals("-allowExtraEvents")) { 140 extraEventClasses = createEventClassArray(args[i + 1]); 141 142 i++; 143 } else if (args[i].equals("-allowMissedEvents")) { 144 missedEventClasses = createEventClassArray(args[i + 1]); 145 146 i++; 147 } else 148 standardArgs.add(args[i]); 149 } 150 151 return standardArgs.toArray(new String[standardArgs.size()]); 152 } 153 154 // can't control some kinds of events (events from system libraries) and 155 // not all events should be saved for analysis 156 // (should be implemented in subclasses) shouldSaveEvent(Event event)157 protected boolean shouldSaveEvent(Event event) { 158 return true; 159 } 160 findEventDataClass(TestedEventData[] testedEventData, Event event)161 public Class<?> findEventDataClass(TestedEventData[] testedEventData, Event event) { 162 for (TestedEventData eventData : testedEventData) { 163 if (eventData.eventClass.isAssignableFrom(event.getClass())) 164 return eventData.eventClass; 165 } 166 167 return null; 168 } 169 170 /* 171 * This event listener stores received monitor events until BreakpointEvent 172 * is not received, after getting of BreakpointEvent checks only expected 173 * events were received 174 */ 175 public class EventListener extends EventHandler.EventListener { 176 177 private TestedEventData[] testedEventData; 178 EventListener(TestedEventData[] testedEventData)179 public EventListener(TestedEventData[] testedEventData) { 180 this.testedEventData = testedEventData; 181 } 182 shouldHandleEvent(Event event)183 private boolean shouldHandleEvent(Event event) { 184 return findEventDataClass(testedEventData, event) == null ? false : true; 185 } 186 187 volatile boolean breakpointWasReceived; 188 189 // execution was interrupted because of timeout 190 volatile boolean executionWasInterrupted; 191 eventReceived(Event event)192 public boolean eventReceived(Event event) { 193 if (shouldHandleEvent(event)) { 194 if (shouldSaveEvent(event)) { 195 196 Class<?> eventClass; 197 198 eventClass = findEventDataClass(testedEventData, event); 199 List<Event> events = allReceivedEvents.get(eventClass); 200 201 if (events == null) { 202 events = new LinkedList<Event>(); 203 allReceivedEvents.put(eventClass, events); 204 } 205 206 events.add(event); 207 } 208 209 return true; 210 } 211 // debuggee should stop at the end of test 212 else if (event instanceof BreakpointEvent) { 213 breakpointWasReceived = true; 214 215 try { 216 // if execution was interrupted because of timeout don't check received 217 // events because it can consume too much time 218 if (!executionWasInterrupted) { 219 // get data from debuggee about all generated events 220 initExpectedEvents(testedEventData); 221 222 checkEvents(); 223 } else 224 log.complain("WARNING: execution was interrupted because of timeout, test doesn't check received events"); 225 } catch (Throwable t) { 226 unexpectedException(t); 227 } 228 229 vm.resume(); 230 231 return true; 232 } 233 234 return false; 235 } 236 } 237 238 protected Class<?> extraEventClasses[]; 239 240 protected Class<?> missedEventClasses[]; 241 242 /* 243 * If test can't strictly control event generation it may allow generation 244 * of extra events and unexpected events aren't treated as error 245 * (subclasses should specify what kinds of extra events are allowed) 246 */ allowedExtraEvents()247 private Class<?>[] allowedExtraEvents() { 248 return extraEventClasses; 249 } 250 251 /* 252 * If test can't strictly control event generation case when debugger doesn't 253 * receive expected event may be not treated as failure 254 * (subclasses should specify what kinds of expected events can be not received) 255 */ allowedMissedEvents()256 private Class<?>[] allowedMissedEvents() { 257 return missedEventClasses; 258 } 259 isExtraEventAllowed(Class<?> eventClass)260 private boolean isExtraEventAllowed(Class<?> eventClass) { 261 return checkEvent(eventClass, allowedExtraEvents()); 262 } 263 isMissedEventAllowed(Class<?> eventClass)264 private boolean isMissedEventAllowed(Class<?> eventClass) { 265 return checkEvent(eventClass, allowedMissedEvents()); 266 } 267 checkEvent(Class<?> eventClass, Class<?> classes[])268 private boolean checkEvent(Class<?> eventClass, Class<?> classes[]) { 269 if (classes == null) 270 return false; 271 272 for (Class<?> klass : classes) { 273 if (klass.isAssignableFrom(eventClass)) 274 return true; 275 } 276 277 return false; 278 } 279 280 // flag is modified from the event listener thread 281 private volatile boolean eventsNotGenerated; 282 283 /* 284 * Method returns true if test expects event generation, but events weren't 285 * generated. If test can't strictly control event generation such case isn't 286 * necessarily treated as test failure (sublasses of JDIEventsDebugger can 287 * for example try to rerun test several times). 288 */ eventsNotGenerated()289 protected boolean eventsNotGenerated() { 290 return eventsNotGenerated; 291 } 292 293 /* 294 * Print debug information about expected and received events(this data 295 * should be stored in lists 'allExpectedEvents' and 'allReceivedEvents') 296 * and check that only expected events were received 297 */ checkEvents()298 private void checkEvents() { 299 if (getAllExpectedEvents().size() > 0 && getAllReceivedEvents().size() == 0 && allowedMissedEvents() != null) { 300 log.display("WARNING: didn't receive any event"); 301 eventsNotGenerated = true; 302 } 303 304 log.display("ALL RECEIVED EVENTS: "); 305 for (Event event : getAllReceivedEvents()) 306 log.display("received event: " + eventToString(event)); 307 308 log.display("ALL EXPECTED EVENTS: "); 309 for (DebuggerEventData.DebugEventData eventData : getAllExpectedEvents()) 310 log.display("expected event: " + eventData); 311 312 // try to find received event in the list of expected events, if this event 313 // was found remove data about events from both lists 314 for (Class<?> eventClass : allReceivedEvents.keySet()) { 315 List<Event> receivedEvents = allReceivedEvents.get(eventClass); 316 List<DebuggerEventData.DebugEventData> expectedEvents = allExpectedEvents.get(eventClass); 317 318 for (Iterator<Event> allReceivedEventsIterator = receivedEvents.iterator(); 319 allReceivedEventsIterator.hasNext();) { 320 321 Event event = allReceivedEventsIterator.next(); 322 323 for (Iterator<DebuggerEventData.DebugEventData> allExpectedEventsIterator = expectedEvents.iterator(); 324 allExpectedEventsIterator.hasNext();) { 325 326 DebuggerEventData.DebugEventData debugEventData = allExpectedEventsIterator.next(); 327 328 if (debugEventData.shouldCheckEvent(event)) { 329 if (debugEventData.checkEvent(event)) { 330 allExpectedEventsIterator.remove(); 331 allReceivedEventsIterator.remove(); 332 break; 333 } 334 } 335 } 336 } 337 } 338 339 List<Event> receivedEventsLeft = getAllReceivedEvents(); 340 341 // check is all received events were found in expected 342 if (receivedEventsLeft.size() > 0) { 343 // if allowExtraEvents = true extra events are not treated as error 344 for (Event event : receivedEventsLeft) { 345 if (!isExtraEventAllowed(event.getClass())) { 346 setSuccess(false); 347 log.complain("Unexpected event " + eventToString(event)); 348 } 349 } 350 } 351 352 List<DebuggerEventData.DebugEventData> expectedEventsLeft = getAllExpectedEvents(); 353 354 // check is all expected events were received 355 if (expectedEventsLeft.size() > 0) { 356 for (DebuggerEventData.DebugEventData eventData : expectedEventsLeft) { 357 if (!isMissedEventAllowed(eventData.eventClass)) { 358 setSuccess(false); 359 log.complain("Expected event was not generated: " + eventData); 360 } 361 } 362 } 363 } 364 eventToString(Event event)365 private String eventToString(Event event) { 366 try { 367 if (event instanceof MonitorContendedEnterEvent) 368 return event + ". Details(MonitorContendedEnterEvent):" + " Monitor: " + ((MonitorContendedEnterEvent) event).monitor() + " Thread: " 369 + ((MonitorContendedEnterEvent) event).thread(); 370 else if (event instanceof MonitorContendedEnteredEvent) 371 return event + ". Details(MonitorContendedEnteredEvent):" + " Monitor: " + ((MonitorContendedEnteredEvent) event).monitor() 372 + " Thread: " + ((MonitorContendedEnteredEvent) event).thread(); 373 else if (event instanceof MonitorWaitEvent) 374 return event + ". Details(MonitorWaitEvent):" + " Monitor: " + ((MonitorWaitEvent) event).monitor() + " Thread: " 375 + ((MonitorWaitEvent) event).thread() + " Timeout: " + ((MonitorWaitEvent) event).timeout(); 376 else if (event instanceof MonitorWaitedEvent) 377 return event + ". Details(MonitorWaitedEvent):" + " Monitor: " + ((MonitorWaitedEvent) event).monitor() + " Thread: " 378 + ((MonitorWaitedEvent) event).thread() + " Timedout: " + ((MonitorWaitedEvent) event).timedout(); 379 380 return event.toString(); 381 } 382 // this exception can occur when unexpected event was received 383 catch (ObjectCollectedException e) { 384 // allowExtraEvents=true extra events are not treated as error 385 if (!isExtraEventAllowed(event.getClass())) { 386 setSuccess(false); 387 e.printStackTrace(log.getOutStream()); 388 log.complain("Unexpected ObjectCollectedException was caught, possible unexpected event was received"); 389 } 390 391 return event.getClass().getName() + " [ Can't get full description, ObjectCollectedException was thrown ]"; 392 } 393 } 394 395 // events received during test execution are stored here 396 private Map<Class<?>, List<Event>> allReceivedEvents = new HashMap<Class<?>, List<Event>>(); 397 getAllReceivedEvents()398 private List<Event> getAllReceivedEvents() { 399 List<Event> result = new LinkedList<Event>(); 400 401 for (Class<?> eventClass : allReceivedEvents.keySet()) { 402 result.addAll(allReceivedEvents.get(eventClass)); 403 } 404 405 return result; 406 } 407 408 protected Map<Class<?>, List<DebuggerEventData.DebugEventData>> allExpectedEvents = new HashMap<Class<?>, List<DebuggerEventData.DebugEventData>>(); 409 getAllExpectedEvents()410 private List<DebuggerEventData.DebugEventData> getAllExpectedEvents() { 411 List<DebuggerEventData.DebugEventData> result = new LinkedList<DebuggerEventData.DebugEventData>(); 412 413 for (Class<?> eventClass : allExpectedEvents.keySet()) { 414 result.addAll(allExpectedEvents.get(eventClass)); 415 } 416 417 return result; 418 } 419 420 // find in debuggee VM and add to the list 'allExpectedEvents' instances 421 // of classes representing generated events initExpectedEvents(TestedEventData testedEventData[])422 protected void initExpectedEvents(TestedEventData testedEventData[]) { 423 List<DebuggerEventData.DebugEventData> events; 424 425 ReferenceType referenceType = debuggee.classByName(debuggeeClassNameWithoutArgs()); 426 427 ArrayReference generatedEvents = (ArrayReference) referenceType.getValue(referenceType.fieldByName("generatedEvents")); 428 429 for (TestedEventData eventData : testedEventData) { 430 events = new LinkedList<DebuggerEventData.DebugEventData>(); 431 allExpectedEvents.put(eventData.eventClass, events); 432 } 433 434 for (int i = 0; i < generatedEvents.length(); i++) { 435 ObjectReference debuggeeMirror = (ObjectReference) generatedEvents.getValue(i); 436 437 for (TestedEventData eventData : testedEventData) { 438 439 if (debuggeeMirror.referenceType().name().equals(eventData.eventDataMirrorClass.getName())) { 440 events = allExpectedEvents.get(eventData.eventClass); 441 442 /* 443 * Use reflection to create object representing generated 444 * event Event data class should has constructor with single 445 * parameter of type com.sun.jdi.ObjectReference 446 */ 447 Constructor<?> constructor; 448 449 try { 450 constructor = eventData.eventDataClass.getConstructor(new Class[] { ObjectReference.class }); 451 } catch (NoSuchMethodException e) { 452 TestBug testBug = new TestBug( 453 "Class representing debug event data should implement constructor with single parameter of type com.sun.jdi.ObjectReference"); 454 testBug.initCause(e); 455 throw testBug; 456 } 457 458 DebuggerEventData.DebugEventData expectedEvent; 459 460 try { 461 expectedEvent = (DebuggerEventData.DebugEventData) constructor.newInstance(new Object[] { debuggeeMirror }); 462 } catch (Exception e) { 463 TestBug testBug = new TestBug("Error when create debug event data: " + e); 464 testBug.initCause(e); 465 throw testBug; 466 } 467 events.add(expectedEvent); 468 } 469 } 470 } 471 } 472 printFiltersInfo()473 private void printFiltersInfo() { 474 if (eventFilters.size() > 0) { 475 log.display("Use following filters: "); 476 477 for (EventFilters.DebugEventFilter filter : eventFilters) 478 log.display("" + filter); 479 } else { 480 log.display("Don't use event filters"); 481 } 482 } 483 484 // filters used in test 485 protected List<EventFilters.DebugEventFilter> eventFilters = new LinkedList<EventFilters.DebugEventFilter>(); 486 487 // Check is object generating events matches all filters, 488 // if object was accepted by all filters set this object's field 489 // 'saveEventData' to 'true', otherwise to 'false', checkEventGenerator(ThreadReference eventThread, ObjectReference executor)490 private void checkEventGenerator(ThreadReference eventThread, ObjectReference executor) { 491 boolean acceptedByFilters = true; 492 493 for (EventFilters.DebugEventFilter eventFilter : eventFilters) { 494 if (!eventFilter.isObjectMatch(executor, eventThread)) { 495 acceptedByFilters = false; 496 break; 497 } 498 } 499 500 try { 501 executor.setValue(executor.referenceType().fieldByName("saveEventData"), vm.mirrorOf(acceptedByFilters)); 502 } catch (Exception e) { 503 throw new TestBug("Unexpected exception when change object field in debugee VM: " + e, e); 504 } 505 } 506 507 /* 508 * Find all event generating threads in debuggee VM (instances of 509 * nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread) all these 510 * threads have special field - 'executor', this is object which generates 511 * events. If event generating thread and event generating object was 512 * accepted by all filters generating object should store information about 513 * all generated events and this information will be available for debugger 514 */ initializeEventGenerators()515 protected void initializeEventGenerators() { 516 printFiltersInfo(); 517 518 List<ThreadReference> eventThreads = getEventThreads(); 519 520 for (ThreadReference eventThread : eventThreads) { 521 ObjectReference executor = (ObjectReference) eventThread.getValue(eventThread.referenceType().fieldByName("executor")); 522 checkEventGenerator(eventThread, executor); 523 } 524 525 // debuggee's main thread also can generate events, need to filter it in 526 // the same way as other threads 527 checkEventGenerator(debuggee.threadByName(JDIEventsDebuggee.MAIN_THREAD_NAME), findSingleObjectReference(debuggeeClassNameWithoutArgs())); 528 } 529 530 // find instances of nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread getEventThreads()531 protected List<ThreadReference> getEventThreads() { 532 ReferenceType referenceType = debuggee.classByName(JDIEventsDebuggee.EventActionsThread.class.getName()); 533 List<ObjectReference> debuggeeEventThreads = referenceType.instances(0); 534 535 List<ThreadReference> result = new LinkedList<ThreadReference>(); 536 for (ObjectReference threadReference : debuggeeEventThreads) 537 result.add((ThreadReference) threadReference); 538 539 return result; 540 } 541 542 // find instances of nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread, 543 // and get value of this object's field with name 'executor' getEventObjects()544 protected List<ObjectReference> getEventObjects() { 545 List<ObjectReference> eventObjects = new LinkedList<ObjectReference>(); 546 547 List<ThreadReference> eventThreads = getEventThreads(); 548 549 for (ThreadReference eventThread : eventThreads) { 550 eventObjects.add((ObjectReference) eventThread.getValue(eventThread.referenceType().fieldByName("executor"))); 551 } 552 553 return eventObjects; 554 } 555 556 // remove all filters, received and expected events clearTestData()557 private void clearTestData() { 558 allExpectedEvents.clear(); 559 allReceivedEvents.clear(); 560 eventFilters.clear(); 561 eventsNotGenerated = false; 562 } 563 isEventSupported(EventType eventType)564 private boolean isEventSupported(EventType eventType) { 565 switch (eventType) { 566 case MONITOR_CONTENTED_ENTER: 567 case MONITOR_CONTENTED_ENTERED: 568 case MONITOR_WAIT: 569 case MONITOR_WAITED: 570 return vm.canRequestMonitorEvents(); 571 572 default: 573 throw new TestBug("Invalid tested event type: " + eventType); 574 } 575 } 576 577 // create instance of EventRequest depending on given eventType createTestRequest(EventType eventType)578 private EventRequest createTestRequest(EventType eventType) { 579 switch (eventType) { 580 case MONITOR_CONTENTED_ENTER: 581 return debuggee.getEventRequestManager().createMonitorContendedEnterRequest(); 582 case MONITOR_CONTENTED_ENTERED: 583 return debuggee.getEventRequestManager().createMonitorContendedEnteredRequest(); 584 case MONITOR_WAIT: 585 return debuggee.getEventRequestManager().createMonitorWaitRequest(); 586 case MONITOR_WAITED: 587 return debuggee.getEventRequestManager().createMonitorWaitedRequest(); 588 589 default: 590 throw new TestBug("Invalid tested event type: " + eventType); 591 } 592 } 593 594 // create command depending on given eventType createCommand(EventType eventTypes[], int eventsNumber)595 private String createCommand(EventType eventTypes[], int eventsNumber) { 596 String command = JDIEventsDebuggee.COMMAND_CREATE_ACTIONS_EXECUTORS + ":" + eventsNumber + ":"; 597 598 for (EventType eventType : eventTypes) { 599 switch (eventType) { 600 case MONITOR_CONTENTED_ENTER: 601 case MONITOR_CONTENTED_ENTERED: 602 case MONITOR_WAIT: 603 case MONITOR_WAITED: 604 command += " " + eventType.name(); 605 break; 606 607 default: 608 throw new TestBug("Invalid tested event type: " + eventType); 609 } 610 } 611 612 return command; 613 } 614 615 // get list of event requests from EventRequestManager depending on the given eventType getEventRequestsFromManager(EventType eventType)616 private List<?> getEventRequestsFromManager(EventType eventType) { 617 switch (eventType) { 618 case MONITOR_CONTENTED_ENTER: 619 return debuggee.getEventRequestManager().monitorContendedEnterRequests(); 620 case MONITOR_CONTENTED_ENTERED: 621 return debuggee.getEventRequestManager().monitorContendedEnteredRequests(); 622 case MONITOR_WAIT: 623 return debuggee.getEventRequestManager().monitorWaitRequests(); 624 case MONITOR_WAITED: 625 return debuggee.getEventRequestManager().monitorWaitedRequests(); 626 627 default: 628 throw new TestBug("Invalid tested event type: " + eventType); 629 } 630 } 631 632 protected EventHandler eventHandler; 633 634 private EventListener eventListener; 635 636 // perform event generation before test begins to load all using classes 637 // and avoid unexpected events related to classloading prepareDebuggee(EventType[] eventTypes)638 protected void prepareDebuggee(EventType[] eventTypes) { 639 initDefaultBreakpoint(); 640 641 eventHandler = new EventHandler(debuggee, log); 642 eventHandler.startListening(); 643 644 // use event listener which just skip all received events 645 DummyEventListener dummyEventListener = new DummyEventListener(); 646 eventHandler.addListener(dummyEventListener); 647 648 EventRequest eventRequests[] = new EventRequest[eventTypes.length]; 649 650 for (int i = 0; i < eventRequests.length; i++) { 651 eventRequests[i] = createTestRequest(eventTypes[i]); 652 eventRequests[i].setSuspendPolicy(EventRequest.SUSPEND_NONE); 653 eventRequests[i].enable(); 654 } 655 656 // debuggee should create event generators 657 pipe.println(createCommand(eventTypes, 1)); 658 659 if (!isDebuggeeReady()) 660 return; 661 662 // start event generation 663 pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION); 664 665 if (!isDebuggeeReady()) 666 return; 667 668 for (int i = 0; i < eventRequests.length; i++) 669 eventRequests[i].disable(); 670 671 dummyEventListener.waitBreakpoint(); 672 673 eventHandler.removeListener(dummyEventListener); 674 675 pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION); 676 677 if (!isDebuggeeReady()) 678 return; 679 680 eventListener = new EventListener(eventDataByEventTypes(eventTypes)); 681 eventHandler.addListener(eventListener); 682 } 683 684 /* 685 * Method for stress testing, allows specify requests for several event 686 * types, number of events which should be generated during test and number 687 * of threads which simultaneously generate events 688 */ stressTestTemplate(EventType[] eventTypes, int eventsNumber, int threadsNumber)689 protected void stressTestTemplate(EventType[] eventTypes, int eventsNumber, int threadsNumber) { 690 for (EventType eventType : eventTypes) { 691 if (!isEventSupported(eventType)) { 692 log.complain("Can't test event because of it isn't supported: " + eventType); 693 return; 694 } 695 } 696 697 // Used framework is intended for testing event filters and debuggee 698 // creates 3 threads performing event generation and there is possibility 699 // to filter events from some threads 700 for (int i = 0; i < threadsNumber; i++) { 701 pipe.println(createCommand(eventTypes, eventsNumber)); 702 703 if (!isDebuggeeReady()) 704 return; 705 } 706 707 // clear data(if this method is executed several times) 708 clearTestData(); 709 710 initializeEventGenerators(); 711 712 EventRequest eventRequests[] = new EventRequest[eventTypes.length]; 713 714 // create event requests 715 for (int i = 0; i < eventTypes.length; i++) { 716 eventRequests[i] = createTestRequest(eventTypes[i]); 717 eventRequests[i].setSuspendPolicy(EventRequest.SUSPEND_NONE); 718 eventRequests[i].enable(); 719 720 log.display("Use following event request: " + eventRequests[i]); 721 } 722 723 // stressTestTemplate can control only execution time, so ignore iteration count 724 stresser.start(0); 725 try { 726 // start event generation 727 pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION); 728 729 if (!isDebuggeeReady()) 730 return; 731 732 // check is stressTime exceeded 733 while (stresser.continueExecution()) { 734 try { 735 Thread.sleep(100); 736 } catch (InterruptedException e) { 737 unexpectedException(e); 738 } 739 740 // periodically check is test completed 741 if (eventListener.breakpointWasReceived) 742 break; 743 } 744 } finally { 745 stresser.finish(); 746 } 747 748 // debugger should interrupt test because of timeout 749 if (!eventListener.breakpointWasReceived) { 750 751 eventListener.executionWasInterrupted = true; 752 753 log.complain("WARNING: time is exceeded, interrupt test"); 754 755 pipe.println(JDIEventsDebuggee.COMMAND_STOP_EXECUTION); 756 757 if (!isDebuggeeReady()) 758 return; 759 } 760 761 pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION); 762 763 if (!isDebuggeeReady()) 764 return; 765 766 for (int i = 0; i < eventRequests.length; i++) 767 eventRequests[i].disable(); 768 } 769 770 /* 771 * Hook method for subclasses implementing tests against event filters (it is called from eventFilterTestTemplate) 772 */ createTestFilters(int testedFilterIndex)773 protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) { 774 throw new TestBug("Not implemented"); 775 } 776 777 /* 778 * Test event request with filter 779 * 780 * Also this method check following: 781 * - InvalidRequestStateException is thrown if add filter for deleted or enabled request 782 * - EventRequestManager.xxxRequests() returns created event request 783 */ eventFilterTestTemplate(EventType eventType, int testedFilterIndex)784 protected void eventFilterTestTemplate(EventType eventType, int testedFilterIndex) { 785 if (!isEventSupported(eventType)) { 786 log.complain("Can't test event because of it isn't supported: " + eventType); 787 return; 788 } 789 790 // debuggee create event generators 791 pipe.println(createCommand(new EventType[] { eventType }, 1)); 792 793 if (!isDebuggeeReady()) 794 return; 795 796 clearTestData(); 797 798 EventFilters.DebugEventFilter[] filters = createTestFilters(testedFilterIndex); 799 800 for (EventFilters.DebugEventFilter filter : filters) { 801 if (filter.isSupported(vm)) 802 eventFilters.add(filter); 803 else { 804 log.complain("Can't test filter because of it isn't supported: " + filter); 805 return; 806 } 807 } 808 809 initializeEventGenerators(); 810 811 // create event request 812 EventRequest request = createTestRequest(eventType); 813 request.setSuspendPolicy(EventRequest.SUSPEND_NONE); 814 815 // try add filter to enabled request, expect 816 // 'InvalidRequestStateException' 817 request.enable(); 818 try { 819 for (EventFilters.DebugEventFilter filter : filters) 820 filter.addFilter(request); 821 822 setSuccess(false); 823 log.complain("Expected 'InvalidRequestStateException' was not thrown"); 824 } catch (InvalidRequestStateException e) { 825 // expected exception 826 } catch (Throwable e) { 827 setSuccess(false); 828 log.complain("Unexpected exception: " + e); 829 e.printStackTrace(log.getOutStream()); 830 } 831 832 // add event filter 833 request.disable(); 834 835 for (EventFilters.DebugEventFilter filter : filters) 836 addFilter(filter, request); 837 838 request.enable(); 839 840 log.display("Use following event request: " + request); 841 842 // start event generation 843 pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION); 844 845 if (!isDebuggeeReady()) 846 return; 847 848 // wait execution completion 849 pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION); 850 851 if (!isDebuggeeReady()) 852 return; 853 854 // check that method EventRequestManager.xxxRequests() return created 855 // request 856 if (!getEventRequestsFromManager(eventType).contains(request)) { 857 setSuccess(false); 858 log.complain("EventRequestManager doesn't return request: " + request); 859 } 860 861 // delete event request 862 debuggee.getEventRequestManager().deleteEventRequest(request); 863 864 // try add filter to removed request, expect 865 // 'InvalidRequestStateException' 866 try { 867 for (EventFilters.DebugEventFilter filter : filters) 868 filter.addFilter(request); 869 setSuccess(false); 870 log.complain("Expected 'InvalidRequestStateException' was not thrown"); 871 } catch (InvalidRequestStateException e) { 872 // expected exception 873 } catch (Throwable t) { 874 unexpectedException(t); 875 } 876 } 877 addFilter(EventFilters.DebugEventFilter filter, EventRequest request)878 private void addFilter(EventFilters.DebugEventFilter filter, EventRequest request) { 879 try { 880 filter.addFilter(request); 881 } catch (Throwable t) { 882 unexpectedException(t); 883 } 884 } 885 886 // used to parse parameters -allowExtraEvents and -allowMissedEvents createEventClassArray(String string)887 private Class<?>[] createEventClassArray(String string) { 888 String eventTypesNames[] = string.split(":"); 889 EventType eventTypes[] = new EventType[eventTypesNames.length]; 890 try { 891 for (int i = 0; i < eventTypesNames.length; i++) { 892 eventTypes[i] = EventType.valueOf(eventTypesNames[i]); 893 } 894 } catch (IllegalArgumentException e) { 895 throw new TestBug("Invalid event type", e); 896 } 897 898 if (eventTypesNames.length == 0) 899 throw new TestBug("Event types weren't specified"); 900 901 Class<?>[] result = new Class[eventTypesNames.length]; 902 903 for (int i = 0; i < result.length; i++) 904 result[i] = testedEventData.get(eventTypes[i]).eventClass; 905 906 return result; 907 } 908 909 } 910