Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIEventsDebuggee.java
41161 views
/*1* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package nsk.share.jdi;2324import java.io.*;25import java.util.*;26import nsk.share.TestBug;2728/*29* Subclasses of this class generate events and if needed30* save debug information about generated events31*/32abstract class EventActionsExecutor {33// should this event generator save information about generated events34public boolean saveEventData;3536// information about generated events(this data available for debugger)37public List<DebuggeeEventData.DebugEventData> debugEventDataList = new ArrayList<DebuggeeEventData.DebugEventData>();3839public abstract void doEventAction();4041protected void addEventData(DebuggeeEventData.DebugEventData eventData) {42if (saveEventData)43debugEventDataList.add(eventData);44}4546public void clearDebugData() {47debugEventDataList.clear();48}49}5051/*52* Class handles commands for running given number of threads which generate53* given events. Objects which generate events save information about generated54* events and this data available for debugger55*56* Class was written to test monitor evens(MonitorWaitEvent, MonitorWaitedEvent,57* MonitorContendedEnterEvent, MonitorContendedEnteredEvent), possible it can be58* used in tests for other events59*/60abstract public class JDIEventsDebuggee extends AbstractJDIDebuggee {61protected String[] doInit(String[] args) {62Thread.currentThread().setName(MAIN_THREAD_NAME);63return super.doInit(args);64}6566public static final String MAIN_THREAD_NAME = "JDIEventsDebuggee_MainThread";6768// command:events_count:event types69public static final String COMMAND_CREATE_ACTIONS_EXECUTORS = "createActionsExecutors";7071// command72public static final String COMMAND_START_EXECUTION = "startExecution";7374// command75public static final String COMMAND_WAIT_EXECUTION_COMPLETION = "waitExecutionCompletion";7677// command78public static final String COMMAND_STOP_EXECUTION = "stopExecution";7980protected List<EventActionsThread> eventActionsExecutorsPool = new ArrayList<EventActionsThread>();8182// initialize with empty array83public static DebuggeeEventData.DebugEventData generatedEvents[] = new DebuggeeEventData.DebugEventData[0];8485// debuggee's main thread also can generate events and information about86// this events should be saved (like for event generators)87protected boolean saveEventData;8889public boolean parseCommand(String command) {90if (super.parseCommand(command))91return true;9293StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(94command));95tokenizer.whitespaceChars(':', ':');96tokenizer.wordChars('_', '_');97tokenizer.wordChars(' ', ' ');9899try {100if (command.startsWith(COMMAND_CREATE_ACTIONS_EXECUTORS)) {101tokenizer.nextToken();102103if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)104throw new TestBug("Invalid command format: " + command);105106int eventsCount = (int) tokenizer.nval;107108if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)109throw new TestBug("Invalid command format: " + command);110111// pass to the createActionsExecutors() string describing types112// of tested events113createActionsExecutors(tokenizer.sval, eventsCount);114115return true;116} else if (command.equals(COMMAND_START_EXECUTION)) {117startExecution();118119return true;120} else if (command.equals(COMMAND_WAIT_EXECUTION_COMPLETION)) {121if (executionControllingThread == null)122throw new TestBug("executionControllingThread wasn't started");123124try {125executionControllingThread.join();126executionControllingThread = null;127} catch (InterruptedException e) {128unexpectedException(e);129}130131return true;132} else if (command.equals(COMMAND_STOP_EXECUTION)) {133if (executionControllingThread == null)134throw new TestBug("executionControllingThread wasn't started");135136for (EventActionsThread thread : eventActionsExecutorsPool) {137thread.stopExecution();138}139140return true;141}142143} catch (IOException e) {144throw new TestBug("Invalid command format: " + command);145}146147return false;148}149150// debugee waits completion of test threads in separate thread to free thread listening commands151protected Thread executionControllingThread;152153protected void startExecution() {154if (eventActionsExecutorsPool.size() == 0) {155throw new TestBug("ActionsExecutors were not created");156}157158for (EventActionsThread thread : eventActionsExecutorsPool) {159thread.startExecution();160}161162// debugee waits completion of test threads in separate thread to free thread listening commands163executionControllingThread = new Thread(164new Runnable() {165public void run() {166for (EventActionsThread thread : eventActionsExecutorsPool) {167try {168thread.join();169} catch (InterruptedException e) {170unexpectedException(e);171}172}173174completeExecution();175}176});177178executionControllingThread.start();179}180181protected void completeExecution() {182// save information about all generated events in array 'generatedEvents'183List<DebuggeeEventData.DebugEventData> generatedEventsList = new ArrayList<DebuggeeEventData.DebugEventData>();184185for (EventActionsThread thread : eventActionsExecutorsPool)186generatedEventsList.addAll(thread.executor.debugEventDataList);187188generatedEvents = generatedEventsList.toArray(new DebuggeeEventData.DebugEventData[]{});189190// stop at breakpoint when all events was generated191breakpointMethod();192193// clear data about generated events to allow execute command194// several times195clearResults();196}197198// clear data about generated events to allow execute test several times199protected void clearResults() {200for (EventActionsThread thread : eventActionsExecutorsPool)201thread.executor.clearDebugData();202203eventActionsExecutorsPool.clear();204205generatedEvents = new DebuggeeEventData.DebugEventData[0];206}207208// create threads generating events209abstract protected void createActionsExecutors(String description,210int eventsCount);211212/*213* Thread generating events, call in loop214* EventActionsExecutor.doEventAction()215*/216static class EventActionsThread extends Thread {217// how many times call executor.doMonitorAction()218private int actionsNumber;219220// object generating events221public EventActionsExecutor executor;222223public EventActionsThread(EventActionsExecutor executor,224int actionsNumber) {225this.actionsNumber = actionsNumber;226this.executor = executor;227}228229private volatile boolean startExecution;230private volatile boolean stopExecution;231232public void run() {233while (!startExecution)234Thread.yield();235236for (int i = 0; (i < actionsNumber) && !stopExecution; i++)237executor.doEventAction();238}239240public void startExecution() {241startExecution = true;242}243244public void stopExecution() {245stopExecution = true;246}247}248249}250251252