Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUmair Sair2019-08-18 01:23:03 +0000
committerJonah Graham2019-08-19 16:43:22 +0000
commit9d97a364190efb6bf73df45a78772289917cbe54 (patch)
tree71ea807ad8be433cc249e15b1a1ab33d03817375
parent342d0c7b892cd216650a0b17f36c8539f519705a (diff)
downloadorg.eclipse.cdt-9d97a364190efb6bf73df45a78772289917cbe54.tar.gz
org.eclipse.cdt-9d97a364190efb6bf73df45a78772289917cbe54.tar.xz
org.eclipse.cdt-9d97a364190efb6bf73df45a78772289917cbe54.zip
Bug 550165: Debugging is stuck when "command aborts" on step return
Adding unit test for MIAsyncErrorProcessor. The test adds breakpoint on 0x0 address and try to continue and step return. It asserts that the target is in stopped state and error as reason in both cases. Then it removes all the breakpoints and resumes the target and asserts that target is in resumed state. Change-Id: I2e024e0d5f55b4e9464a6f2b7a2b0c78bee4e8e8 Signed-off-by: Umair Sair <umair_sair@hotmail.com>
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SuiteGdb.java3
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/mi/service/command/MIAsyncErrorProcessorTests.java218
2 files changed, 220 insertions, 1 deletions
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 29c3e7f7030..76ebe71e9f3 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
@@ -20,6 +20,7 @@ import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.MIRunControlNonStopTargetAvai
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.OperationsWhileTargetIsRunningNonStopTest;
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.StepIntoSelectionNonStopTest;
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.ThreadStackFrameSyncTest;
+import org.eclipse.cdt.tests.dsf.mi.service.command.MIAsyncErrorProcessorTests;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -45,7 +46,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest.class, StepIntoSelectionNonStopTest.class,
GDBRemoteTracepointsTest.class, TraceFileTest.class, GDBConsoleSynchronizingTest.class, MIMemoryTest.class,
MIDisassemblyTest.class, GDBProcessesTest.class, PostMortemCoreTest.class, CommandTimeoutTest.class,
- ThreadStackFrameSyncTest.class, CommandLineArgsTest.class,
+ ThreadStackFrameSyncTest.class, CommandLineArgsTest.class, MIAsyncErrorProcessorTests.class
/* Add your test class here */
})
public class SuiteGdb {
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/mi/service/command/MIAsyncErrorProcessorTests.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/mi/service/command/MIAsyncErrorProcessorTests.java
new file mode 100644
index 00000000000..afc903444a8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/mi/service/command/MIAsyncErrorProcessorTests.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Mentor Graphics and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Umair Sair (Mentor Graphics) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.tests.dsf.mi.service.command;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData;
+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.command.IGDBControl;
+import org.eclipse.cdt.dsf.mi.service.MIRunControl;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
+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.AsyncCompletionWaitor;
+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.SyncUtil;
+import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
+import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Tests MIAsyncErrorProcessor for continue and step return command failure
+ */
+@RunWith(Parameterized.class)
+public class MIAsyncErrorProcessorTests extends BaseParametrizedTestCase {
+
+ private static final String EXEC_NAME = "MultiThread.exe";
+
+ private MIRunControl runControl;
+ private IGDBControl commandControl;
+ private IContainerDMContext containerDmc;
+
+ @Override
+ protected void setLaunchAttributes() {
+ super.setLaunchAttributes();
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME);
+ }
+
+ @Override
+ public void doBeforeTest() throws Exception {
+ assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_12);
+
+ super.doBeforeTest();
+
+ DsfSession session = getGDBLaunch().getSession();
+ Runnable runnable = () -> {
+ DsfServicesTracker servicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(),
+ session.getId());
+ assert (servicesTracker != null);
+
+ runControl = servicesTracker.getService(MIRunControl.class);
+ assert (runControl != null);
+
+ commandControl = servicesTracker.getService(IGDBControl.class);
+ assert (commandControl != null);
+
+ servicesTracker.dispose();
+ };
+
+ session.getExecutor().submit(runnable).get();
+ containerDmc = SyncUtil.getContainerContext();
+
+ try {
+ prepareEnvironment();
+ } catch (Throwable e) {
+ throw new Exception(e);
+ }
+ }
+
+ private void prepareEnvironment() throws Throwable {
+ AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ /*
+ * 1. Confirm that target is suspended initially
+ */
+ assertTrue(runControl.isSuspended(containerDmc));
+
+ /*
+ * 2. 'set confirm off' as we'll will be deleting all breakpoints latter using 'del' command
+ */
+ commandControl.queueCommand(
+ commandControl.getCommandFactory().createMIInterpreterExecConsole(containerDmc, "set confirm off"),
+ new ImmediateDataRequestMonitor<MIInfo>() {
+ @Override
+ public void handleCompleted() {
+ wait.waitFinished(getStatus());
+ }
+ });
+
+ wait.waitUntilDone(TestsPlugin.massageTimeout(1000));
+ wait.waitReset();
+
+ /*
+ * 3. Add breakpoint at ThreadSetName symbol and resume so that we have deeper stack
+ */
+ SyncUtil.addBreakpoint("ThreadSetName");
+ performOperationAndWaitForSuspend(SyncUtil::resume);
+
+ /*
+ * 4. Add breakpoint at 0x0 which will cause continue and step return failure
+ */
+ SyncUtil.addBreakpoint("*0x0", false);
+ }
+
+ @Test
+ public void executeContinueTest() throws Throwable {
+ performOperationAndWaitForSuspend(SyncUtil::resume);
+
+ assertTrue(isTargetStoppedWithError());
+ }
+
+ @Test
+ public void executeStepReturnTest() throws Throwable {
+ performOperationAndWaitForSuspend(() -> SyncUtil.step(StepType.STEP_RETURN));
+
+ assertTrue(isTargetStoppedWithError());
+ }
+
+ @Test
+ public void executeContinueTestThenRemoveBreakpointsAndResume() throws Throwable {
+ executeContinueTest();
+
+ AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ /*
+ * Remove all breakpoints and resume. Target should be in resumed state now
+ */
+ commandControl.queueCommand(
+ commandControl.getCommandFactory().createMIInterpreterExecConsole(containerDmc, "del"),
+ new ImmediateDataRequestMonitor<MIInfo>() {
+ @Override
+ public void handleCompleted() {
+ wait.waitFinished(getStatus());
+ }
+ });
+
+ wait.waitUntilDone(TestsPlugin.massageTimeout(1000));
+ wait.waitReset();
+
+ SyncUtil.resume();
+
+ Thread.sleep(1000);
+
+ assertFalse(runControl.isSuspended(containerDmc));
+ }
+
+ /**
+ * Performs the operation and wait for suspend. The operation should be such that the target
+ * is resumed on running it
+ *
+ * @param operation
+ * an operation that will resume the target
+ * @throws Throwable
+ * Any problem while running the operation or waiting for stop event
+ */
+ private void performOperationAndWaitForSuspend(Operation operation) throws Throwable {
+ ServiceEventWaitor<IContainerResumedDMEvent> resumeEventWaitor = new ServiceEventWaitor<>(
+ getGDBLaunch().getSession(), IContainerResumedDMEvent.class);
+ ServiceEventWaitor<MIStoppedEvent> stopEventWaitor = new ServiceEventWaitor<>(getGDBLaunch().getSession(),
+ MIStoppedEvent.class);
+
+ operation.run();
+
+ resumeEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
+ stopEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
+ waitUntil("Waiting for suspend", () -> runControl.isSuspended(containerDmc), TestsPlugin.massageTimeout(1000));
+ }
+
+ private boolean isTargetStoppedWithError() throws Exception {
+ if (!runControl.isSuspended(containerDmc))
+ return false;
+
+ Query<Boolean> query = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ runControl.getExecutionData(containerDmc, new ImmediateDataRequestMonitor<IExecutionDMData>(rm) {
+ @Override
+ protected void handleCompleted() {
+ rm.done(isSuccess() && getData().getStateChangeReason() == StateChangeReason.ERROR);
+ }
+ });
+ }
+ };
+
+ runControl.getExecutor().execute(query);
+
+ return query.get(TestsPlugin.massageTimeout(2000), TimeUnit.MILLISECONDS);
+ }
+
+ private interface Operation {
+ void run() throws Throwable;
+ }
+}

Back to the top