From 40aca4d51da0df17c0b9f9fc49f8474376cc6fcd Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Mon, 13 Feb 2017 10:02:30 -0500 Subject: [PATCH] Bug 511243 - Tests validating program-interrupt using CLI or MI The tests validate the use of CLI (i.e. Ctrl-C) or MI (i.e. -exec-interrupt) to interrupt the target program. The MI command is used when the target is running in async mode, which is mandatory when using the Full CLI console. At the time of writing, async mode is not supported for Windows and MAC, therefore these tests rely on a new mechanism to override specific DSF-GDB services. Change-Id: Ie4ab30f07640d112fff9aec2b4f348a27bfe188b --- .../framework/BaseParametrizedTestCase.java | 16 + .../tests/dsf/gdb/framework/BaseTestCase.java | 14 +- .../framework/ServiceFactoriesManager.java | 50 +++ .../dsf/gdb/launching/TestLaunchDelegate.java | 21 ++ .../dsf/gdb/tests/MIModifiedServicesTest.java | 343 ++++++++++++++++++ .../tests/dsf/gdb/tests/MIRunControlTest.java | 22 +- .../cdt/tests/dsf/gdb/tests/SuiteGdb.java | 1 + 7 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceFactoriesManager.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIModifiedServicesTest.java diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseParametrizedTestCase.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseParametrizedTestCase.java index 2a78f0a1a53..7c4da86abd4 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseParametrizedTestCase.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseParametrizedTestCase.java @@ -127,6 +127,22 @@ public abstract class BaseParametrizedTestCase extends BaseTestCase { return getGdbVersion(gdbPath); } + public boolean isGdbVersionAtLeast(String checkVersion) { + String gdbVersion = getGdbVersion(); + if (gdbVersion == GDB_NOT_FOUND) { + return false; + } + + if (checkVersion == null || checkVersion.isEmpty() || checkVersion.equals("default")) + return false; + + if (checkVersion.equals(gdbVersion)) + return true; + + // return if it has to be same of higher + return LaunchUtils.compareVersions(checkVersion, gdbVersion) <= 0; + } + public void assumeGdbVersionAtLeast(String checkVersion) { String gdbVersion = getGdbVersion(); if (gdbVersion == GDB_NOT_FOUND) { diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java index 47c45b92880..850459b6628 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java @@ -134,6 +134,10 @@ public class BaseTestCase { private HashMap fTagLocations = new HashMap<>(); + // Provides the possibility to override the Debug Services factory and + // override specific service(s) + private static ServiceFactoriesManager fTestDebugServiceFactoriesMgr = new ServiceFactoriesManager(); + /** * Return the launch created when {@link #doLaunch()} was called. */ @@ -740,5 +744,13 @@ public class BaseTestCase { protected void waitUntil(String message, Callable callable) throws Exception { waitUntil(message, callable, TestsPlugin.massageTimeout(2000)); } - + + /** + * @return A Test Debug Service Factories manager which allow individual tests to register + * a specific service factory which can then provide mocked/extended instances of Test Services + */ + public static ServiceFactoriesManager getServiceFactoriesManager() { + return fTestDebugServiceFactoriesMgr; + } + } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceFactoriesManager.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceFactoriesManager.java new file mode 100644 index 00000000000..4874173333f --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceFactoriesManager.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2017 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 + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.framework; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory; +import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * This is a Debug Service Factories Manager which keeps track of the factories provided by specific test cases. + * This allow individual tests to override DSF-GDB Services which is sometimes needed to validate different + * code paths. + * + * The test is in charge of providing a unique id for the given factory, however this class will trigger an + * exception if a duplicate id is detected. + * + * This id can then be shared via launch attributes, since each individual test method has its + * own launch configuration there is no possibility to override the launch attributes by other tests + * + * Users can then retrieve/remove the registered factory via the unique factory id provided by the test + */ +public class ServiceFactoriesManager { + public final static String DEBUG_SERVICES_FACTORY_KEY = TestsPlugin.PLUGIN_ID + ".DEBUG_SERVICES_FACTORY"; + + private final Map fTestServiceFactoriesMap = new HashMap<>(); + + public void addTestServicesFactory(String id, GdbDebugServicesFactory servicesFactory) + throws CoreException { + if (fTestServiceFactoriesMap.containsKey(id)) { + throw new CoreException(new Status(IStatus.ERROR, TestsPlugin.getUniqueIdentifier(), + "A factory with this id already exists " + id)); + } + + fTestServiceFactoriesMap.put(id, servicesFactory); + } + + public GdbDebugServicesFactory removeTestServicesFactory(String id) { + return fTestServiceFactoriesMap.remove(id); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/launching/TestLaunchDelegate.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/launching/TestLaunchDelegate.java index fcc984254d9..c874ec09f70 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/launching/TestLaunchDelegate.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/launching/TestLaunchDelegate.java @@ -11,7 +11,10 @@ package org.eclipse.cdt.tests.dsf.gdb.launching; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; +import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate; +import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; +import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceFactoriesManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -62,4 +65,22 @@ public class TestLaunchDelegate extends GdbLaunchDelegate return super.checkBinaryDetails(config); } + @Override + protected IDsfDebugServicesFactory newServiceFactory(ILaunchConfiguration config, String version) { + // Check if this test has registered a services factory for this launch + String servicesFactoryId = null; + try { + servicesFactoryId = config.getAttribute(ServiceFactoriesManager.DEBUG_SERVICES_FACTORY_KEY, ""); + } catch (CoreException e) { + } + + if (servicesFactoryId != null && servicesFactoryId.length() > 0) { + // A services factory has been registered, so lets resolve it and use it + return BaseTestCase.getServiceFactoriesManager() + .removeTestServicesFactory(servicesFactoryId); + } + + // Use the original services factory + return super.newServiceFactory(config, version); + } } \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIModifiedServicesTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIModifiedServicesTest.java new file mode 100644 index 00000000000..c310ce6efc0 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIModifiedServicesTest.java @@ -0,0 +1,343 @@ +/******************************************************************************* + * Copyright (c) 2017 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 + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +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.datamodel.DMContexts; +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.IContainerDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory; +import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; +import org.eclipse.cdt.dsf.gdb.service.extensions.GDBBackend_HEAD; +import org.eclipse.cdt.dsf.mi.service.IMIBackend; +import org.eclipse.cdt.dsf.mi.service.IMIProcesses; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase; +import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor; +import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceFactoriesManager; +import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; +import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +/** + * The tests of this class use special versions of services. + */ +@RunWith(Parameterized.class) +public class MIModifiedServicesTest extends BaseParametrizedTestCase { + + private IMIRunControl fRunCtrl; + + private IContainerDMContext fContainerDmc; + private IExecutionDMContext fThreadExecDmc; + private IGDBBackend fBackend; + + /* + * Name of the executable + */ + private static final String EXEC_NAME = "MultiThread.exe"; + private static final String SOURCE_NAME = "MultiThread.cc"; + + /** + * A backend class that disables the full GDB console and uses the basic console instead. + */ + private class TestBackendBasicConsole extends GDBBackend_HEAD { + public TestBackendBasicConsole(DsfSession session, ILaunchConfiguration lc) { + super(session, lc); + } + + @Override + public boolean isFullGdbConsoleSupported() { + return false; + } + } + + /** + * A services factory that uses the test backend service that instantiates + * a basic console instead of a full console. + */ + private class TestServicesFactoryBasicConsole extends GdbDebugServicesFactory { + public TestServicesFactoryBasicConsole(String version, ILaunchConfiguration config) { + super(version, config); + } + + @Override + protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) { + if (compareVersionWith(GDB_7_12_VERSION) >= 0) { + return new TestBackendBasicConsole(session, lc); + } + return super.createBackendGDBService(session, lc); + } + } + + + @Override + public void doBeforeTest() throws Exception { + removeTeminatedLaunchesBeforeTest(); + setLaunchAttributes(); + + // Can't run the launch right away because each test needs to first set some + // parameters. The individual tests will be responsible for starting the launch. + + // Looks up line tags in source file(s). + clearLineTags(); + resolveLineTagLocations(SOURCE_NAME, MIRunControlTest.LINE_TAGS); + } + + @Override + protected void setLaunchAttributes() { + super.setLaunchAttributes(); + + setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME); + + // This is crude, but effective. We need to determine if the program was + // built with cygwin. The easiest way is to scan the binary file looking + // for 'cygwin1.dll'. In the real world, this wouldn't cut mustard, but + // since this is just testing code, and we control the programs, it's a + // no brainer. + if (runningOnWindows()) { + + // This is interesting. Our tests rely on the working directory. + // That is, we specify a program path in the launch configuration + // that is relative to the working directory. + File file = new File(EXEC_PATH + EXEC_NAME); + + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + } catch (FileNotFoundException e) { + Assert.fail(e.getLocalizedMessage()); + return; // needed to avoid warning at fis usage below + } + + final String MATCH = "cygwin1.dll"; + final int MATCH_LEN = MATCH.length(); + int i = 0; + int ch = 0; + while (true) { + try { + ch = fis.read(); + } catch (IOException e) { + Assert.fail("Problem inspecting file to see if it's a cygwin executable : " + + e.getLocalizedMessage()); + } + if (ch == -1) { // EOF + break; + } + if (ch == MATCH.charAt(i)) { + if (i == MATCH_LEN - 1) { + break; // found it! + } + i++; + } else { + i = 0; + } + } + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + } + } + } + } + + // This method cannot be tagged as @Before, because the launch is not + // running yet. We have to call this manually after all the proper + // parameters have been set for the launch + @Override + protected void doLaunch() throws Exception { + // perform the launch + super.doLaunch(); + + fContainerDmc = SyncUtil.getContainerContext(); + + final DsfSession session = getGDBLaunch().getSession(); + + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + DsfServicesTracker servicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), + session.getId()); + + IMIProcesses procService = servicesTracker.getService(IMIProcesses.class); + IProcessDMContext procDmc = DMContexts.getAncestorOfType(fContainerDmc, IProcessDMContext.class); + IThreadDMContext threadDmc = procService.createThreadContext(procDmc, "1"); + fThreadExecDmc = procService.createExecutionContext(fContainerDmc, threadDmc, "1"); + + fRunCtrl = servicesTracker.getService(IMIRunControl.class); + fBackend = servicesTracker.getService(IGDBBackend.class); + + servicesTracker.dispose(); + + rm.done(); + } + }; + session.getExecutor().execute(query); + query.get(TestsPlugin.massageTimeout(5000), TimeUnit.MILLISECONDS); + + } + + protected void registerServicesFactoryForBasicConsole() throws CoreException { + // Resolve a unique id for the Test Debug services factory + String servicesFactoryId = this.getClass().getName() + "#" + testName.getMethodName(); + + // Register this test case factory + getServiceFactoriesManager().addTestServicesFactory(servicesFactoryId, + new TestServicesFactoryBasicConsole(getGdbVersion(), getLaunchConfiguration())); + + // Register the factory id using a launch attribute, so it can be later resolved + // e.g. by a test launch delegate + setLaunchAttribute(ServiceFactoriesManager.DEBUG_SERVICES_FACTORY_KEY, servicesFactoryId); + } + + private void resumeContainerContextExe() + throws InterruptedException, ExecutionException, TimeoutException { + + final ServiceEventWaitor resumedWaitor = new ServiceEventWaitor( + getGDBLaunch().getSession(), IResumedDMEvent.class); + + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + fRunCtrl.resume(fContainerDmc, rm); + } + }; + + fRunCtrl.getExecutor().execute(query); + query.get(TestsPlugin.massageTimeout(5000), TimeUnit.MILLISECONDS); + + try { + resumedWaitor.waitForEvent(TestsPlugin.massageTimeout(5000)); + } catch (Exception e) { + Assert.fail("Exception raised:: " + e.getMessage()); + e.printStackTrace(); + return; + } + + Query querySuspend = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + rm.done(fRunCtrl.isSuspended(fContainerDmc)); + } + }; + + fRunCtrl.getExecutor().execute(querySuspend); + Boolean suspended = querySuspend.get(TestsPlugin.massageTimeout(5000), TimeUnit.MILLISECONDS); + Assert.assertFalse("Target is suspended. It should have been running", suspended); + } + + /** + * Validate we can interrupt via the CLI, This would not be feasible to test in the traditional test + * environment e.g. Linux with GDB 7.12 This test case forces the use of the Basic console which triggers + * async mode off, and will cause the program interrupt via the CLI (rather than MI -exec-interrupt which + * is used with async mode) + * + * Note: This test case uses a modified Test Backend service which is instrumented before test execution, + * see initializeLaunchAttributes + */ + private void interruptRunningTargetExe() + throws InterruptedException, Exception, ExecutionException, TimeoutException { + ServiceEventWaitor suspendedEventWaitor = new ServiceEventWaitor( + getGDBLaunch().getSession(), ISuspendedDMEvent.class); + + Query requestSuspend = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + fRunCtrl.suspend(fThreadExecDmc, rm); + } + }; + + fRunCtrl.getExecutor().execute(requestSuspend); + requestSuspend.get(TestsPlugin.massageTimeout(5000), TimeUnit.MILLISECONDS); + + // Wait up to 2 seconds for the target to suspend. Should happen immediately. + suspendedEventWaitor.waitForEvent(TestsPlugin.massageTimeout(2000)); + + // Double check that the target is in the suspended state + Query querySuspend = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + rm.done(fRunCtrl.isSuspended(fContainerDmc)); + } + }; + + fRunCtrl.getExecutor().execute(querySuspend); + Boolean suspended = querySuspend.get(TestsPlugin.massageTimeout(5000), TimeUnit.MILLISECONDS); + + Assert.assertTrue("Target is running. It should have been suspended", suspended); + } + + /** + * Validate that with the basic console, GDB will not accept commands while the target is running. + * This would not be feasible to test with our standard services. This test case forces the use of the Basic + * console by using a test IGDBBackEnd service. + */ + @Test + public void doNotAcceptCommandsWhenTargetRunning_BasicConsole() throws Throwable { + assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_12); + + registerServicesFactoryForBasicConsole(); + + doLaunch(); + + // Make sure we are using our test version of IGDBBackEnd + assertTrue("Not using the expected backend service", fBackend instanceof TestBackendBasicConsole); + + resumeContainerContextExe(); + + // Verify that with the basic console, we cannot accept commands when the target is running. + assertFalse("Target should be running with async off, and should NOT be accepting commands", + fRunCtrl.isTargetAcceptingCommands()); + } + + /** + * Validate that with the basic console, interrupting a running target does work. + * This would not be feasible to test with our standard services. + * This test case forces the use of the Basic console by using a test IGDBBackEnd service. + */ + @Test + public void interruptRunningTarget_BasicConsole() throws Throwable { + assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_12); + + registerServicesFactoryForBasicConsole(); + + doLaunch(); + + // Make sure we are using our test version of IGDBBackEnd + assertTrue("Not using the expected backend service", fBackend instanceof TestBackendBasicConsole); + + resumeContainerContextExe(); + + interruptRunningTargetExe(); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlTest.java index 90785318395..23602e85bb1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlTest.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.tests.dsf.gdb.tests; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; @@ -39,6 +40,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; +import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; @@ -81,6 +83,7 @@ public class MIRunControlTest extends BaseParametrizedTestCase { private IGDBControl fGDBCtrl; private IMIRunControl fRunCtrl; + private IGDBBackend fBackEnd; private IContainerDMContext fContainerDmc; private IExecutionDMContext fThreadExecDmc; @@ -121,6 +124,7 @@ public class MIRunControlTest extends BaseParametrizedTestCase { fThreadExecDmc = procService.createExecutionContext(fContainerDmc, threadDmc, "1"); fRunCtrl = fServicesTracker.getService(IMIRunControl.class); + fBackEnd = fServicesTracker.getService(IGDBBackend.class); } }; session.getExecutor().submit(runnable).get(); @@ -185,6 +189,12 @@ public class MIRunControlTest extends BaseParametrizedTestCase { i = 0; } } + if (fis !=null) { + try { + fis.close(); + } catch (IOException e) { + } + } } } @@ -668,7 +678,17 @@ public class MIRunControlTest extends BaseParametrizedTestCase { Assert.assertFalse("Target is suspended. It should have been running", (Boolean)wait.getReturnInfo()); wait.waitReset(); - } + + // In all-stop mode, MI async is active when the Full GDB console is used + if (fBackEnd.isFullGdbConsoleSupported()) { + assertTrue("Target should be running with async on, and shall be accepting commands", + fRunCtrl.isTargetAcceptingCommands()); + return; + } + + assertFalse("Target should be running with async off, and shall NOT be accepting commands", + fRunCtrl.isTargetAcceptingCommands()); + } @Test public void runToLine() throws Throwable { diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SuiteGdb.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SuiteGdb.java index 1a0c5fd533c..3ff09ce9e8b 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SuiteGdb.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SuiteGdb.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; SourceLookupTest.class, StepIntoSelectionTest.class, OperationsWhileTargetIsRunningTest.class, + MIModifiedServicesTest.class, MIRunControlTest.class, MIRunControlTargetAvailableTest.class, MIRunControlReverseTest.class,