From efe3dd4be6ab048411a623112dcae093d78fd329 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 24 Apr 2012 22:58:22 -0400 Subject: [PATCH] Bug 330974: If the user selects multiple nodes in the debug view most debug commands are disabled Change-Id: I51d15347fd28ee550e9bd2b75c61e904e75b4c8b Reviewed-on: https://git.eclipse.org/r/5650 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../dsf/gdb/service/GDBRunControl_7_0_NS.java | 299 +- .../dsf/gdb/service/GDBRunControl_7_2_NS.java | 4 +- .../data/launch/src/MultiThreadRunControl.cc | 76 + .../dsf/gdb/framework/ServiceEventWaitor.java | 29 +- .../cdt/tests/dsf/gdb/framework/SyncUtil.java | 23 +- .../GDBMultiNonStopRunControlTest_7_0.java | 4022 +++++++++++++++++ .../dsf/gdb/tests/tests_7_0/Suite_7_0.java | 1 + .../gdb/tests/tests_7_0/Suite_Remote_7_0.java | 1 + .../GDBMultiNonStopRunControlTest_7_1.java | 30 + .../dsf/gdb/tests/tests_7_1/Suite_7_1.java | 1 + .../gdb/tests/tests_7_1/Suite_Remote_7_1.java | 1 + .../GDBMultiNonStopRunControlTest_7_2.java | 30 + .../dsf/gdb/tests/tests_7_2/Suite_7_2.java | 1 + .../gdb/tests/tests_7_2/Suite_Remote_7_2.java | 1 + .../GDBMultiNonStopRunControlTest_7_3.java | 30 + .../dsf/gdb/tests/tests_7_3/Suite_7_3.java | 1 + .../gdb/tests/tests_7_3/Suite_Remote_7_3.java | 1 + .../GDBMultiNonStopRunControlTest_7_4.java | 30 + .../dsf/gdb/tests/tests_7_4/Suite_7_4.java | 1 + .../gdb/tests/tests_7_4/Suite_Remote_7_4.java | 1 + .../debug/ui/actions/DsfCommandRunnable.java | 61 +- .../debug/ui/actions/DsfResumeCommand.java | 66 +- .../debug/ui/actions/DsfSuspendCommand.java | 68 +- .../dsf/debug/service/IMultiRunControl.java | 134 + 24 files changed, 4844 insertions(+), 68 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java create mode 100644 dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 60eb549a3e8..d8eb3adaac6 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -9,14 +9,18 @@ * Wind River Systems - initial API and implementation * Ericsson AB - Modified for handling of multiple threads * Indel AG - [369622] fixed moveToLine using MinGW + * Marc Khouzam (Ericsson) - Support for operations on multiple execution contexts (bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -42,6 +46,7 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent; import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; @@ -104,7 +109,7 @@ import org.osgi.framework.BundleContext; * sync with the service state. * @since 1.1 */ -public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService +public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, IMultiRunControl, ICachingService { @Immutable private static class ExecutionData implements IExecutionDMData2 { @@ -396,7 +401,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo private void doInitialize(final RequestMonitor rm) { register(new String[]{ IRunControl.class.getName(), IRunControl2.class.getName(), - IMIRunControl.class.getName()}, + IMIRunControl.class.getName(), + IMultiRunControl.class.getName() }, new Hashtable()); fConnection = getServicesTracker().getService(ICommandControlService.class); fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); @@ -1878,4 +1884,293 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo } return result; } + + /////////////////////////////////////////////////////////////////////////// + // IMultiRunControl implementation + /////////////////////////////////////////////////////////////////////////// + + // Although multi-process in only supported for GDB >= 7.2, it is simpler + // to code for the multi-process case all the time, since it is a superset + // of the single-process case. + + /////////////////////////////////////////////////////////////////////////// + // Multi-resume implementation: + // + // If one or more more threads of one or many processes are selected, we want to + // resume each thread (once). + // + // If one or more more processes are selected, we want to resume each process (once). + // + // If a process is selected along with one or more threads of that same process, + // what does the user want us to do? Selecting the process will resume all its + // threads, but what do we do with the selected threads? Why are they + // selected? In an attempt to be user friendly, lets assume that the user + // wants to resume the entire process, so we ignore the selected threads part of that + // process since they will be resumed anyway. + // + // The same logic applies to multi-suspend. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToResumeList = extractContextsForOperation(contexts); + + // If any of the threads or processes can be resumed, we allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (doCanResume(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that could be resumed. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToResumeList = extractContextsForOperation(contexts); + + // If any of the threads or processes cannot be resumed, we don't allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (!doCanResume(execDmc)) { + rm.done(false); + return; + } + } + + // Everything can be resumed + rm.done(true); + } + + /** + * {@inheritDoc} + * + * For GDB, a separate resume command will be sent, one for each context + * that can be resumed. + * @since 4.1 + */ + @Override + public void resume(IExecutionDMContext[] contexts, RequestMonitor rm) { + assert contexts != null; + + List execDmcToResumeList = extractContextsForOperation(contexts); + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + int count = 0; + + // Perform resume operation on each thread or process that can be resumed + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (doCanResume(execDmc)) { + count++; + resume(execDmc, crm); + } + } + + crm.setDoneCount(count); + } + + /////////////////////////////////////////////////////////////////////////// + // Multi-suspend implementation: + // see details of the multi-resume implementation above. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + // If any of the threads or processes can be suspended, we allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (doCanSuspend(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that could be suspended. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + // If any of the threads or processes cannot be suspended, we don't allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (!doCanSuspend(execDmc)) { + rm.done(false); + return; + } + } + + // Everything can be suspended + rm.done(true); + } + + /** @since 4.1 */ + @Override + public void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + List execDmcSuspendedList = extractContextsForOperation(contexts); + + // Look for any thread or process that is suspended + for (IExecutionDMContext execDmc : execDmcSuspendedList) { + if (isSuspended(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that was suspended. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + List execDmcSuspendedList = extractContextsForOperation(contexts); + + // Look for any thread or process that is not suspended + for (IExecutionDMContext execDmc : execDmcSuspendedList) { + if (!isSuspended(execDmc)) { + rm.done(false); + return; + } + } + + // Everything is suspended. + rm.done(true); + } + + /** + * {@inheritDoc} + * + * For GDB, a separate suspend command will be sent, one for each context + * that can be suspended. + * @since 4.1 + */ + @Override + public void suspend(IExecutionDMContext[] contexts, RequestMonitor rm) { + assert contexts != null; + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + int count = 0; + + // Perform resume operation on each thread or process that can be resumed + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (doCanSuspend(execDmc)) { + count++; + suspend(execDmc, crm); + } + } + + crm.setDoneCount(count); + } + + /////////////////////////////////////////////////////////////////////////// + // Multi-step implementation. Not implemented yet. See bug 330974. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** + * Removes duplicates from the list of execution contexts, in case the same thread + * or process is present more than once. + * + * Also, remove any thread that is part of a process that is also present. This is + * because an operation on the process will affect all its threads anyway. + */ + private List extractContextsForOperation(IExecutionDMContext[] contexts) { + // Remove duplicate contexts by using a set + Set specifiedExedDmcSet = new HashSet(Arrays.asList(contexts)); + + // A list that ignores threads for which the process is also present + List execDmcForOperationList = new ArrayList(specifiedExedDmcSet.size()); + + // Check for the case of a process selected along with some of its threads + for (IExecutionDMContext execDmc : specifiedExedDmcSet) { + if (execDmc instanceof IContainerDMContext) { + // This is a process: it is automatically part of our list + execDmcForOperationList.add(execDmc); + } else { + // Get the process for this thread + IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class); + // Check if that process is also present + if (specifiedExedDmcSet.contains(containerDmc) == false) { + // This thread does not belong to a process that is selected, so we keep it. + execDmcForOperationList.add(execDmc); + } + } + } + return execDmcForOperationList; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java index 97d14197095..faabbe0d4b2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Ericsson and others. + * Copyright (c) 2011, 2012 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl2; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; @@ -72,6 +73,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS register(new String[]{ IRunControl.class.getName(), IRunControl2.class.getName(), IMIRunControl.class.getName(), + IMultiRunControl.class.getName(), GDBRunControl_7_0_NS.class.getName(), GDBRunControl_7_2_NS.class.getName(), }, diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc new file mode 100644 index 00000000000..f30714744ea --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc @@ -0,0 +1,76 @@ +#ifdef __MINGW32__ + #include // MinGW has no POSIX support; use MSVC runtime +#else + #include +#endif +#include +#include +#include "Sleep.h" + +#ifdef __MINGW32__ +typedef unsigned int TID; +#else +typedef pthread_t TID; +#endif + +// Set a breakpoint here so that both threads stop. +void firstBreakpoint(int id) +{ + printf("First breakpoint method from thread %d\n", id); +} + + +#ifdef __MINGW32__ +unsigned int __stdcall PrintHello(void *threadid) +#else +void *PrintHello(void *threadId) +#endif +{ + int tId = (int)threadId; + firstBreakpoint(tId); // Stop a first time + + SLEEP(1); // Keep state running a little + + firstBreakpoint(tId); // Stop a second time + + SLEEP(3); // Resuming past this will give us a running thread + +#ifdef __MINGW32__ + return 0; +#else + pthread_exit(NULL); +#endif +} + + +int main(int argc, char *argv[]) +{ + TID thread; + int tId = 1; // Break at main will stop here: we have a single thread stopped + + SLEEP(1); // When resuming past here, we have a single thread running + +#ifdef __MINGW32__ + uintptr_t rc = _beginthreadex(NULL, 0, PrintHello, (void*)tId, 0, &thread); + if (rc == 0) + { + printf("ERROR; _beginthreadex() failed. errno = %d\n", errno); + exit(-1); + } +#else + int rc = pthread_create(&thread, NULL, PrintHello, (void *)tId); + if (rc) + { + printf("ERROR; return code from pthread_create() is %d\n", rc); + exit(-1); + } +#endif + + firstBreakpoint(0); + + SLEEP(1); // Resuming past this will make this thread run, while we stop the second thread + + SLEEP(3); // Resuming past this will make this thread run, while we also run the second thread + + return 0; +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java index 379679aadba..be375f9c9c1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Ericsson and others. + * Copyright (c) 2007, 2012 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,9 +7,13 @@ * * Contributors: * Ericsson - Initial Implementation + * Marc Khouzam (Ericsson) - Add support to receive multiple events *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.framework; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.ExecutionException; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; @@ -17,7 +21,7 @@ import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; import org.eclipse.core.runtime.Platform; -/* +/** * This class provides a way to wait for an asynchronous ServerEvent * to occur. The user of this class specifies which event is of * interest . waitForEvent() can then be called to block until the event occurs or @@ -40,7 +44,9 @@ public class ServiceEventWaitor { /* The type of event to wait for */ private Class fEventTypeClass; private DsfSession fSession; - private V fEvent; + + // Queue of events. This allows to receive multiple events and keep them. + private List fEventQueue = Collections.synchronizedList(new LinkedList()); /** * Trace option for wait metrics @@ -59,7 +65,6 @@ public class ServiceEventWaitor { assert eventClass != null; fSession = session; fEventTypeClass = eventClass; - fEvent = null; Runnable runnable = new Runnable() { @Override public void run() { @@ -102,10 +107,9 @@ public class ServiceEventWaitor { long startMs = System.currentTimeMillis(); - // The event might have already been received - if (fEvent == null) { + if (fEventQueue.isEmpty()) { wait(timeout); - if (fEvent == null) { + if (fEventQueue.isEmpty()) { throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName()); } } @@ -159,14 +163,7 @@ public class ServiceEventWaitor { } } - // Mark that we have consumed the event. - // This will allow to wait for the next similar event. - // For example, for a restart, there could be more than one - // stopped event, and we need to wait for the second one. - V event = fEvent; - fEvent = null; - - return event; + return fEventQueue.remove(0); } /* @@ -177,7 +174,7 @@ public class ServiceEventWaitor { public void eventDispatched(V event) { if (fEventTypeClass.isAssignableFrom(event.getClass())) { synchronized(this) { - fEvent = event; + fEventQueue.add(event); notifyAll(); } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java index e7173ceb179..fb078685198 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java @@ -593,17 +593,17 @@ public class SyncUtil { } /** - * Utility method to return the execution DM context. + * Utility method to return all thread execution contexts. */ @ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()") - public static IMIExecutionDMContext getExecutionContext(final int threadIndex) throws InterruptedException { + public static IMIExecutionDMContext[] getExecutionContexts() throws InterruptedException { assert !fProcessesService.getExecutor().isInExecutorThread(); final IContainerDMContext containerDmc = SyncUtil.getContainerContext(); - Query query = new Query() { + Query query = new Query() { @Override - protected void execute(final DataRequestMonitor rm) { + protected void execute(final DataRequestMonitor rm) { fProcessesService.getProcessesBeingDebugged( containerDmc, new ImmediateDataRequestMonitor() { @@ -612,10 +612,7 @@ public class SyncUtil { if (isSuccess()) { IDMContext[] threads = getData(); Assert.assertNotNull("invalid return value from service", threads); - Assert.assertTrue("unexpected number of threads", threadIndex < threads.length); - IDMContext thread = threads[threadIndex]; - Assert.assertNotNull("unexpected thread context type ", thread); - rm.setData((IMIExecutionDMContext)thread); + rm.setData((IMIExecutionDMContext[])threads); } else { rm.setStatus(getStatus()); } @@ -633,6 +630,16 @@ public class SyncUtil { } return null; } + /** + * Utility method to return a specific execution DM context. + */ + @ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()") + public static IMIExecutionDMContext getExecutionContext(int threadIndex) throws InterruptedException { + IMIExecutionDMContext[] threads = getExecutionContexts(); + Assert.assertTrue("unexpected number of threads", threadIndex < threads.length); + Assert.assertNotNull("unexpected thread context type ", threads[threadIndex]); + return threads[threadIndex]; + } /** * Check if the restart operation is supported diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java new file mode 100644 index 00000000000..466aa3c776b --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java @@ -0,0 +1,4022 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; +import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; +import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor; +import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; +import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_0 extends BaseTestCase { + + private DsfServicesTracker fServicesTracker; + + private IMultiRunControl fMultiRun; + + /* + * Path to executable + */ + private static final String EXEC_PATH = "data/launch/bin/"; + /* + * Name of the executable + */ + private static final String EXEC_NAME = "MultiThreadRunControl.exe"; + + @Before + public void init() throws Exception { + final DsfSession session = getGDBLaunch().getSession(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + fServicesTracker = + new DsfServicesTracker(TestsPlugin.getBundleContext(), + session.getId()); + fMultiRun = fServicesTracker.getService(IMultiRunControl.class); + } + }; + session.getExecutor().submit(runnable).get(); + } + + + @After + public void tearDown() { + fServicesTracker.dispose(); + } + + @BeforeClass + public static void beforeClassMethod() { + setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, + EXEC_PATH + EXEC_NAME); + + // Multi run control only makes sense for non-stop mode + setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, true); + } + + private abstract class AsyncRunnable { + public abstract void run(DataRequestMonitor drm); + }; + + private V runAsyncCall(final AsyncRunnable runnable) { + return runAsyncCall(runnable, false); + } + + private V runAsyncCall(final AsyncRunnable runnable, boolean expectExecutionException) { + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + runnable.run(rm); + } + }; + + V result = null; + try { + fMultiRun.getExecutor().execute(query); + result = query.get(500, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + fail(e.getMessage()); + } catch (ExecutionException e) { + if (expectExecutionException) { + return null; + } + fail(e.getCause().getMessage()); + } catch (TimeoutException e) { + fail(e.getMessage()); + } + + if (expectExecutionException) { + fail("Didn't get the expected execution exception"); + } + + return result; + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with one thread which is stopped. + */ + @Test + public void testStateOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with one thread which is running. + */ + @Test + public void testStateOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads which are both stopped. + */ + @Test + public void testStateTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads, one of which is stopped and the other running. + */ + @Test + public void testStateTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected to not be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that not all threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads which are both running. + */ + @Test + public void testStateTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the resume operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + */ + @Test + public void testResumeOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with one thread which is running. + */ + @Test + public void testResumeOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + */ + @Test + public void testResumeTwoThreadsStoppedResumeOne() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads[0], drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + + // Also confirm that only one threads is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected some threads to be suspended, but found none", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected not to find all threads suspended, but did", result); + + // Make sure no other running event arrives + try { + eventWaitorRunning.waitForEvent(500); + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two stopped threads. Both threads + * are resumed. + */ + @Test + public void testResumeTwoThreadsStoppedResumeTwo() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation first thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation second thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testResumeTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + */ + @Test + public void testResumeTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + */ + @Test + public void testSuspendOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with one thread which is running. + */ + @Test + public void testSuspendOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + */ + @Test + public void testSuspendTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testSuspendTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Only one + * thread will be suspended. + */ + @Test + public void testSuspendTwoThreadsRunningSuspendOne() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads[0], drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + + // Also confirm that some but not all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected some threads to be suspended, but found none", result); + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that not all threads are suspended, but they are", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no other stopped event arrives + fail("Got an unexpected stopped event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * will be suspended + */ + @Test + public void testSuspendTwoThreadsRunningSuspendTwo() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + */ + @Test + public void testStepNotImplemented() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(threads, type, drm); + } + }, true /* Not implemented yet*/); + } + + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process. + // This should be done with multi-process but we are not quite setup for it. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is stopped. + */ + @Test + public void testStateProcessOneThreadStopped() throws Throwable { + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected to find all processes suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is running. + */ + @Test + public void testStateProcessOneThreadRunning() throws Throwable { + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + */ + @Test + public void testStateProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + */ + @Test + public void testStateProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but can't", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + */ + @Test + public void testStateProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process and a thread. + // Because the thread is part of the process, it should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is stopped. + * We also select the thread. + */ + @Test + public void testStateProcessThreadOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all processes suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is running. + * We also select the thread. + */ + @Test + public void testStateProcessThreadOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + * We also select the thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select the first thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select the second thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + * We also select both threads + */ + @Test + public void testStateProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process and both threads. + // Because the threads are part of the process, they should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + * We also select both threads. + */ + @Test + public void testStateProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select both threads. + */ + @Test + public void testStateProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + * We also select both threads + */ + @Test + public void testStateProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the multi resume operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + */ + @Test + public void testResumeProcessOneThreadStopped() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation process resumed + + // Also confirm that process is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with one thread which is running. + */ + @Test + public void testResumeProcessOneThreadRunning() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + // No error should be thrown, the call should ignore running processes + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + */ + @Test + public void testResumeProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testResumeProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + */ + @Test + public void testResumeProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + */ + @Test + public void testSuspendProcessOneThreadStopped() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended processes should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); +} + + /** + * Test suspend of multiple contexts with one thread which is running. + */ + @Test + public void testSuspendProcessOneThreadRunning() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + */ + @Test + public void testSuspendProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testSuspendProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + */ + @Test + public void testSuspendProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + */ + @Test + public void testStepProcessNotImplemented() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(processes, type, drm); + } + }, true /* Not implemented yet*/); + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the different operations on the process and a thread. + // Because the thread is part of the process, it should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadOneThreadStopped() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation process resumed + + // Also confirm that process is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with one thread which is running. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadOneThreadRunning() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running processes + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the second thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadOneThreadStopped() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended processes should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with one thread which is running. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadOneThreadRunning() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the second thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + * We select the process and the first thread. + */ + @Test + public void testStepProcessThreadNotImplemented() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the different operations on the process and both threads. + // Because the threads are part of the process, they should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with two stopped threads. + * We select the process and both threads. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and both threads. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java index 68d0e6843f1..faadc9de1c0 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_0.class, PostMortemCoreTest_7_0.class, CommandTimeoutTest_7_0.class, + GDBMultiNonStopRunControlTest_7_0.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java index d267a011a74..b53eeecdc91 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class, CommandTimeoutTest_7_0.class, + GDBMultiNonStopRunControlTest_7_0.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java new file mode 100644 index 00000000000..d93090b1102 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1; + + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0.GDBMultiNonStopRunControlTest_7_0; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_1 extends GDBMultiNonStopRunControlTest_7_0 { + @BeforeClass + public static void beforeClassMethod_7_1() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_1); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java index 75b9b161c61..b6dcace2a34 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_1.class, PostMortemCoreTest_7_1.class, CommandTimeoutTest_7_1.class, + GDBMultiNonStopRunControlTest_7_1.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java index 980446d4e95..f35a838208f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class, CommandTimeoutTest_7_1.class, + GDBMultiNonStopRunControlTest_7_1.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java new file mode 100644 index 00000000000..ce6fb15c1ef --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2; + + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1.GDBMultiNonStopRunControlTest_7_1; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_2 extends GDBMultiNonStopRunControlTest_7_1 { + @BeforeClass + public static void beforeClassMethod_7_2() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_2); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java index 800fe29a252..890f25c7b0f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_2.class, PostMortemCoreTest_7_2.class, CommandTimeoutTest_7_2.class, + GDBMultiNonStopRunControlTest_7_2.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java index 32f2a1e7b89..f53d3f2721f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class, CommandTimeoutTest_7_2.class, + GDBMultiNonStopRunControlTest_7_2.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java new file mode 100644 index 00000000000..aaeb4fe0f3a --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3; + + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2.GDBMultiNonStopRunControlTest_7_2; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_3 extends GDBMultiNonStopRunControlTest_7_2 { + @BeforeClass + public static void beforeClassMethod_7_3() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_3); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java index 65e39402046..c4101852bce 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_3.class, PostMortemCoreTest_7_3.class, CommandTimeoutTest_7_3.class, + GDBMultiNonStopRunControlTest_7_3.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java index 63e9e39e29a..7db9786fd57 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class, CommandTimeoutTest_7_3.class, + GDBMultiNonStopRunControlTest_7_3.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java new file mode 100644 index 00000000000..1e74a7546e5 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4; + + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3.GDBMultiNonStopRunControlTest_7_3; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_4 extends GDBMultiNonStopRunControlTest_7_3 { + @BeforeClass + public static void beforeClassMethod_7_4() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java index d2c7ea43ec1..b00aa75337c 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_4.class, PostMortemCoreTest_7_4.class, CommandTimeoutTest_7_4.class, + GDBMultiNonStopRunControlTest_7_4.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java index f76a836d040..0467dd4b46f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class, CommandTimeoutTest_7_4.class, + GDBMultiNonStopRunControlTest_7_4.class, Suite_Sessionless_Tests.class /* Add your test class here */ }) diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java index a79fa6e4f5e..7b1426fee03 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,9 +7,13 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multiple selection (bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -29,11 +33,18 @@ import org.eclipse.debug.core.commands.IDebugCommandRequest; */ @Immutable public abstract class DsfCommandRunnable extends DsfRunnable { - private final IExecutionDMContext fContext; + private final IExecutionDMContext[] fContexts; private final DsfServicesTracker fTracker; private final IDebugCommandRequest fRequest; - public IExecutionDMContext getContext() { return fContext; } + // For backwards compatibility, keep this method that returns the first selection. This method + // is meaningful when we only support a single selection. + public IExecutionDMContext getContext() { return (fContexts != null && fContexts.length > 0) ? fContexts[0] : null; } + /** + * Return all selected contexts. + * @since 2.3 + */ + public IExecutionDMContext[] getContexts() { return fContexts; } public IRunControl getRunControl() { return fTracker.getService(IRunControl.class); } @@ -42,8 +53,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable { * @since 1.1 */ public SteppingController getSteppingController() { - if (fContext != null) { - return (SteppingController) fContext.getAdapter(SteppingController.class); + if (fContexts != null && fContexts.length > 0) { + return (SteppingController) fContexts[0].getAdapter(SteppingController.class); } return null; } @@ -56,15 +67,33 @@ public abstract class DsfCommandRunnable extends DsfRunnable { } public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) { - fTracker = servicesTracker; - if (element instanceof IDMVMContext) { - IDMVMContext vmc = (IDMVMContext)element; - fContext = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class); - } else { - fContext = null; - } - - fRequest = request; + this(servicesTracker, new Object[] { element }, request); + } + + /** @since 2.3 */ + public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object[] elements, IDebugCommandRequest request) { + fTracker = servicesTracker; + fRequest = request; + + // Extract all selected execution contexts, using a set to avoid duplicates. Duplicates will + // happen if multiple stack frames of the same thread are selected. + Set execDmcSet = new HashSet(request.getElements().length); + for (Object element : request.getElements()) { + if (element instanceof IDMVMContext) { + IDMVMContext vmc = (IDMVMContext)element; + IExecutionDMContext execDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class); + if (execDmc != null) { + // We have a thread or a process + execDmcSet.add(execDmc); + } + } + } + + if (execDmcSet.size() == 0) { + fContexts = null; + } else { + fContexts = execDmcSet.toArray(new IExecutionDMContext[execDmcSet.size()]); + } } @Override @@ -73,8 +102,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable { fRequest.done(); return; } - if (getContext() == null) { - fRequest.setStatus(makeError("Selected object does not support run control.", null)); //$NON-NLS-1$ + if (getContexts() == null || getContexts().length == 0) { + fRequest.setStatus(makeError("Selected objects do not support run control.", null)); //$NON-NLS-1$ } else if (getRunControl() == null || getSteppingController() == null) { fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$ } else { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java index 10e7c464039..44f089339ca 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,16 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -43,17 +45,42 @@ public class DsfResumeCommand implements IResumeHandler { @Override public void canExecute(final IEnabledStateRequest request) { - if (request.getElements().length != 1) { - request.setEnabled(false); - request.done(); + if (request.getElements().length == 1) { + canExecuteSingle(request); return; } + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.setEnabled(false); + request.done(); + return; + } + + // Check if some of the selections can be resumed + multiRun.canResumeSome( + getContexts(), + new ImmediateDataRequestMonitor() { + @Override + protected void handleCompleted() { + request.setEnabled(isSuccess() && getData()); + request.done(); + } + }); + } + }); + } + + private void canExecuteSingle(final IEnabledStateRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().canResume( getContext(), - new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { + new ImmediateDataRequestMonitor() { @Override protected void handleCompleted() { request.setEnabled(isSuccess() && getData()); @@ -66,17 +93,32 @@ public class DsfResumeCommand implements IResumeHandler { @Override public boolean execute(final IDebugCommandRequest request) { - if (request.getElements().length != 1) { - request.done(); - return false; + if (request.getElements().length == 1) { + executeSingle(request); + return false; } + + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.done(); + return; + } + multiRun.resume(getContexts(), new ImmediateRequestMonitor()); + } + }); + return false; + } + + private void executeSingle(IDebugCommandRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().resume(getContext(), new RequestMonitor(fExecutor, null)); } }); - return false; } - } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java index ebc32610586..30a9f538e4e 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,16 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -42,17 +44,42 @@ public class DsfSuspendCommand implements ISuspendHandler { @Override public void canExecute(final IEnabledStateRequest request) { - if (request.getElements().length != 1) { - request.setEnabled(false); - request.done(); + if (request.getElements().length == 1) { + canExecuteSingle(request); return; } + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.setEnabled(false); + request.done(); + return; + } + + // Check if some of the selections can be suspended + multiRun.canSuspendSome( + getContexts(), + new ImmediateDataRequestMonitor() { + @Override + protected void handleCompleted() { + request.setEnabled(isSuccess() && getData()); + request.done(); + } + }); + } + }); + } + + private void canExecuteSingle(final IEnabledStateRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().canSuspend( getContext(), - new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { + new ImmediateDataRequestMonitor() { @Override protected void handleCompleted() { request.setEnabled(isSuccess() && getData()); @@ -65,17 +92,32 @@ public class DsfSuspendCommand implements ISuspendHandler { @Override public boolean execute(final IDebugCommandRequest request) { - if (request.getElements().length != 1) { - request.done(); - return false; + if (request.getElements().length == 1) { + executeSingle(request); + return false; } - + + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.done(); + return; + } + + multiRun.suspend(getContexts(), new ImmediateRequestMonitor()); + } + }); + return false; + } + + private void executeSingle(IDebugCommandRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().suspend(getContext(), new RequestMonitor(fExecutor, null)); } }); - return false; } - } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java new file mode 100644 index 00000000000..ed3f9359a8b --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.service; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; + +/** + * This interface provides the ability to perform run control operations on multiple contexts. + * + * @see org.eclipse.cdt.dsf.debug.service.IRunControl + * + * @since 2.3 + */ +public interface IMultiRunControl extends IRunControl +{ + /** + * Check if at least one of the specified contexts can be resumed + * @param context List of execution contexts that want to be resumed + * @param rm Request monitor returning: + * true if at least one of the specified contexts can be resumed + * false if none of the specified contexts can be resumed + */ + void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be resumed + * @param context List of execution contexts that want to be resumed + * @param rm Request monitor returning: + * true if all of the specified contexts can be resumed + * false if any of the specified contexts cannot be resumed + */ + void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if at least one of the specified contexts can be suspended + * @param context List of execution contexts that want to be suspended + * @param rm Request monitor returning: + * true if at least one of the specified contexts can be suspended + * false if none of the specified contexts can be suspended + */ + void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be suspended + * @param context List of execution contexts that want to be suspended + * @param rm Request monitor returning: + * true if all of the specified contexts can be suspended + * false if any of the specified contexts cannot be suspended + */ + void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts is suspended. + * @param context List of execution contexts that are to be checked for being suspended + * @param rm Request monitor returning: + * true if any of the specified contexts is suspended, false otherwise + */ + void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts are suspended. + * @param context List of execution contexts that are to be checked for being suspended + * @param rm Request monitor returning: + * true if all of the specified contexts are suspended, false otherwise + */ + void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts can be stepped using stepType + * @param context List of execution contexts that want to be stepped + * @param stepStype The type of step to be used. + * @param rm Request monitor returning: + * true if any of the specified contexts can be stepped + * false if none of the specified contexts can be stepped + */ + void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be stepped using stepType + * @param context List of execution contexts that want to be stepped + * @param stepStype The type of step to be used. + * @param rm Request monitor returning: + * true if all of the specified contexts can be stepped + * false if any of the specified contexts cannot be stepped + */ + void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts is currently stepping. + * @param context List of execution contexts that are to be checked for stepping + * @param rm Request monitor returning: + * true if any of the specified contexts is stepping, false otherwise + */ + void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts are currently stepping. + * @param context List of execution contexts that are to be checked for stepping + * @param rm Request monitor returning: + * true if all of the specified contexts are stepping, false otherwise + */ + void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Request that all specified contexts be resumed. Only contexts that are in a + * state that can be resumed will be affected, others will be ignored. + * @param context List of execution contexts that are to be resumed + */ + void resume(IExecutionDMContext[] contexts, RequestMonitor rm); + + /** + * Request that all specified contexts be suspended. Only contexts that are in a + * state that can be suspended will be affected, others will be ignored. + * @param context List of execution contexts that are to be suspended + */ + void suspend(IExecutionDMContext[] contexts, RequestMonitor rm); + + /** + * Request that all specified context be stepped using stepType. Only contexts + * that are in a state that can be stepped will be affected, others will be ignored. + * @param context List of execution contexts that are to be stepped + * @param stepStype The type of step to be used. + */ + void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm); +} \ No newline at end of file