diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java index ac18ef3e340..b2ae8cb9a60 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java @@ -263,6 +263,14 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence { if (fUserBreakpoint != null) { fUserBreakpointIsOnMain = fBreakPointForReverse.getAddress() .equals(fUserBreakpoint.getAddress()); + if (fUserBreakpointIsOnMain) { + String number = fBreakPointForReverse.getNumber(); + fBreakPointForReverse = fUserBreakpoint; + fCommandControl.queueCommand( + fCommandFactory.createMIBreakDelete(bpTargetDmc, number), + new ImmediateDataRequestMonitor(rm)); + return; + } } } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/LaunchConfigurationAndRestartTestApp.cc b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/LaunchConfigurationAndRestartTestApp.cc index 75b4a2fd2ad..bb107bfadf5 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/LaunchConfigurationAndRestartTestApp.cc +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/LaunchConfigurationAndRestartTestApp.cc @@ -23,11 +23,15 @@ int envTest() { } int main (int argc, char *argv[]) -{ - int dummy = 1; // FIRST_LINE_IN_MAIN - envTest(); // main_init +{ int dummy = 1; // FIRST_LINE_IN_MAIN (make the line of code the same as opening brace to account for different gdb/gcc combinations) + int var = 1; // GDB has incomplete support for reverse debugging - so for the purpose of tests reverse debug these simple assignment statements + var = 2; + var = 3; + var = 4; // three_steps_back_from_b_stopAtOther + var = 5; + stopAtOther(); // main_init reverseTest(); // tests assume that every line between first and last - stopAtOther(); // is steppable, so no blank lines allowed. + envTest(); // is steppable, so no blank lines allowed. return 36; // LAST_LINE_IN_MAIN // Return special value to allow // testing exit code feature 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 85be46a4507..b753b13052e 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 @@ -224,8 +224,11 @@ public class BaseTestCase { private ILaunchConfiguration fLaunchConfiguration; + private boolean ignoreFirstStop = false; + public SessionEventListener(ILaunchConfiguration launchConfiguration) { fLaunchConfiguration = launchConfiguration; + this.ignoreFirstStop = SyncUtil.shouldIgnoreFirstStopAtStartup(launchConfiguration); } public void setSession(DsfSession session) { @@ -260,38 +263,59 @@ public class BaseTestCase { Object miEvent = iMIEvent.getMIEvent(); if (miEvent instanceof MIStoppedEvent) { - // Store the corresponding MI *stopped event - fInitialStoppedEvent = (MIStoppedEvent) miEvent; + if (ignoreFirstStop) { + ignoreFirstStop = false; - // Check the content of the frame for the method we - // should stop at - String stopAt = null; - try { - stopAt = fLaunchConfiguration.getAttribute( - ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); - } catch (CoreException e) { - } - if (stopAt == null) - stopAt = "main"; + } else { + // Store the corresponding MI *stopped event + fInitialStoppedEvent = (MIStoppedEvent) miEvent; - MIFrame frame = fInitialStoppedEvent.getFrame(); - if (frame != null && frame.getFunction() != null && frame.getFunction().indexOf(stopAt) != -1) { - // Set the event semaphore that will allow the test - // to proceed - synchronized (fTargetSuspendedSem) { - fTargetSuspended = true; - fTargetSuspendedSem.notify(); + // Check the content of the frame for the method we + // should stop at + String stopAt = null; + boolean stopAtEnabled = true; + boolean reverseEnabledAtStartup = true; + try { + stopAt = fLaunchConfiguration.getAttribute( + ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); + stopAtEnabled = fLaunchConfiguration.getAttribute( + ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, true); + reverseEnabledAtStartup = fLaunchConfiguration + .getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, false); + } catch (CoreException e) { } - // We found our event, no further need for this - // listener - fSession.removeServiceEventListener(this); + if (!stopAtEnabled) { + success(); + } else { + if (stopAt == null) + stopAt = "main"; + + MIFrame frame = fInitialStoppedEvent.getFrame(); + if (frame != null && frame.getFunction() != null + && frame.getFunction().indexOf(stopAt) != -1) { + success(); + } + } } } } } } + private void success() { + // Set the event semaphore that will allow the test + // to proceed + synchronized (fTargetSuspendedSem) { + fTargetSuspended = true; + fTargetSuspendedSem.notify(); + } + + // We found our event, no further need for this + // listener + fSession.removeServiceEventListener(this); + } + public void waitUntilTargetSuspended() throws InterruptedException { if (!fTargetSuspended) { synchronized (fTargetSuspendedSem) { @@ -304,6 +328,7 @@ public class BaseTestCase { public MIStoppedEvent getInitialStoppedEvent() { return fInitialStoppedEvent; } + } /** 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 ac75c52480b..64bbbfc82b3 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 @@ -37,10 +37,12 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -66,11 +68,13 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles; import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo; import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2; import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses; +import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIRunControl; @@ -90,6 +94,7 @@ 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; +import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.model.MemoryByte; /** @@ -152,6 +157,31 @@ public class SyncUtil { fSession.getExecutor().submit(runnable).get(); } + /** + * Enable reverse mode on the target and checks that the reverse service thinks it is set. + * + * Will fail the test if reverse debugging is not supported. + */ + public static void enableReverseMode() throws Throwable { + assertTrue("Reverse debugging is not supported", fRunControl instanceof IReverseRunControl); + final IReverseRunControl reverseService = (IReverseRunControl) fRunControl; + Query query = new Query<>() { + @Override + protected void execute(final DataRequestMonitor rm) { + reverseService.enableReverseMode(fGdbControl.getContext(), true, new ImmediateRequestMonitor(rm) { + @Override + protected void handleSuccess() { + reverseService.isReverseModeEnabled(fGdbControl.getContext(), rm); + } + }); + } + }; + + fSession.getExecutor().execute(query); + Boolean enabled = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS); + assertTrue("Reverse debugging should be enabled", enabled); + } + /** * Steps forward with the given {@code stepType} and can also specify to step a * fixed number of time/s using {@code numSteps}. For possible step types see @@ -1120,6 +1150,32 @@ public class SyncUtil { return canRestart; } + /** + * Under some conditions the startup code of CDT runs, stops and then resumes. This method + * can be used to determine if that first stop should be ignored while waiting for startup. + */ + public static boolean shouldIgnoreFirstStopAtStartup(ILaunchConfiguration launchConfiguration) { + boolean ignoreFirstStop = false; + try { + String stopAt = launchConfiguration + .getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); + boolean stopAtEnabled = launchConfiguration + .getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, true); + boolean reverseEnabledAtStartup = launchConfiguration + .getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, false); + if (stopAt == null) + stopAt = "main"; + if (reverseEnabledAtStartup && !stopAtEnabled) { + ignoreFirstStop = true; + } + if (reverseEnabledAtStartup && stopAtEnabled && !"main".equals(stopAt)) { + ignoreFirstStop = true; + } + } catch (CoreException e) { + } + return ignoreFirstStop; + } + /** * Restarts the program ({@code launch}) * @@ -1160,6 +1216,14 @@ public class SyncUtil { // This is not the stopped event we were waiting for. Get the next one. event = eventWaitor.waitForEvent(DefaultTimeouts.get(ETimeout.waitForStop)); } + + if (shouldIgnoreFirstStopAtStartup(launch.getLaunchConfiguration())) { + event = eventWaitor.waitForEvent(DefaultTimeouts.get(ETimeout.waitForStop)); + if (event instanceof MISignalEvent) { + // This is not the stopped event we were waiting for. Get the next one. + event = eventWaitor.waitForEvent(DefaultTimeouts.get(ETimeout.waitForStop)); + } + } return event; } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/LaunchConfigurationAndRestartTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/LaunchConfigurationAndRestartTest.java index 144b5f1baca..ea823041a13 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/LaunchConfigurationAndRestartTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/LaunchConfigurationAndRestartTest.java @@ -29,7 +29,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; -import org.eclipse.cdt.debug.core.model.ICBreakpointType; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; @@ -38,6 +37,7 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContex import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; +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.StepType; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData; @@ -58,11 +58,10 @@ 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.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IProcess; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -72,10 +71,12 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase protected static final String EXEC_NAME = "LaunchConfigurationAndRestartTestApp.exe"; protected static final String SOURCE_NAME = "LaunchConfigurationAndRestartTestApp.cc"; - protected static final String[] LINE_TAGS = new String[] { "FIRST_LINE_IN_MAIN", "LAST_LINE_IN_MAIN", }; + protected static final String[] LINE_TAGS = new String[] { "FIRST_LINE_IN_MAIN", "LAST_LINE_IN_MAIN", + "three_steps_back_from_b_stopAtOther" }; protected int FIRST_LINE_IN_MAIN; protected int LAST_LINE_IN_MAIN; + protected int three_steps_back_from_b_stopAtOther; // The exit code returned by the test program private static final int TEST_EXIT_CODE = 36; @@ -103,6 +104,7 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase FIRST_LINE_IN_MAIN = getLineForTag("FIRST_LINE_IN_MAIN"); LAST_LINE_IN_MAIN = getLineForTag("LAST_LINE_IN_MAIN"); + three_steps_back_from_b_stopAtOther = getLineForTag("three_steps_back_from_b_stopAtOther"); } @Override @@ -503,9 +505,10 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); assertTrue( - "Expected to stop at main:27 but got " + stoppedEvent.getFrame().getFunction() + ":" - + Integer.toString(stoppedEvent.getFrame().getLine()), - stoppedEvent.getFrame().getFunction().equals("main") && stoppedEvent.getFrame().getLine() == 27); + "Expected to stop at main:" + FIRST_LINE_IN_MAIN + " but got " + stoppedEvent.getFrame().getFunction() + + ":" + Integer.toString(stoppedEvent.getFrame().getLine()), + stoppedEvent.getFrame().getFunction().equals("main") + && stoppedEvent.getFrame().getLine() == FIRST_LINE_IN_MAIN); } /** @@ -546,32 +549,28 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase * the launch to NOT "stop on main". We will verify that the first stop is * at the breakpoint that we set. */ - @Ignore @Test public void testNoStopAtMain() throws Throwable { setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); // Set this one as well to make sure it gets ignored setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); - // We need to set the breakpoint before the launch is started, but the only way to do that is - // to set it in the platorm. Ok, but how do I get an IResource that points to my binary? - // The current workspace is the JUnit runtime workspace instead of the workspace containing - // the JUnit tests. - - IFile fakeFile = null; - CDIDebugModel.createLineBreakpoint(EXEC_PATH + EXEC_NAME, fakeFile, ICBreakpointType.REGULAR, - LAST_LINE_IN_MAIN + 1, true, 0, "", true); //$NON-NLS-1$ + CDIDebugModel.createFunctionBreakpoint(null, ResourcesPlugin.getWorkspace().getRoot(), 0, "stopAtOther", -1, -1, + -1, true, 0, "", true); doLaunch(); MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); - assertTrue("Expected to stop at envTest but got " + stoppedEvent.getFrame().getFunction() + ":", - stoppedEvent.getFrame().getFunction().equals("envTest")); + assertTrue("Expected to stop at stopAtOther but got " + stoppedEvent.getFrame().getFunction() + ":", + stoppedEvent.getFrame().getFunction().equals("stopAtOther")); + final IExecutionDMContext execDmc = stoppedEvent.getDMContext(); + IFrameDMData frame = SyncUtil.getFrameData(execDmc, 0); + assertTrue("Expected to stop at stopAtOther but got " + frame.getFunction() + ":", + frame.getFunction().equals("stopAtOther")); } /** * Repeat the test testNoStopAtMain, but after a restart. */ - @Ignore @Test public void testNoStopAtMainRestart() throws Throwable { fRestart = true; @@ -709,11 +708,12 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase final int REVERSE_NUM_STEPS = 2; final IExecutionDMContext execDmc = stoppedEvent.getDMContext(); + IContainerDMContext containerDmc = SyncUtil.getContainerContext(); Query query = new Query<>() { @Override protected void execute(DataRequestMonitor rm) { fGdbControl.queueCommand( - fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, REVERSE_NUM_STEPS), rm); + fGdbControl.getCommandFactory().createMIExecReverseNext(containerDmc, REVERSE_NUM_STEPS), rm); } }; { @@ -787,18 +787,16 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); - assertTrue( - "Expected to stop at main:" + (FIRST_LINE_IN_MAIN) + " but got " + stoppedEvent.getFrame().getFunction() - + ":" + Integer.toString(stoppedEvent.getFrame().getLine()), + assertTrue("Expected to stop at main:" + (three_steps_back_from_b_stopAtOther) + " but got " + + stoppedEvent.getFrame().getFunction() + ":" + Integer.toString(stoppedEvent.getFrame().getLine()), stoppedEvent.getFrame().getFunction().equals("main") - && stoppedEvent.getFrame().getLine() == FIRST_LINE_IN_MAIN); + && stoppedEvent.getFrame().getLine() == three_steps_back_from_b_stopAtOther); } /** * Repeat the test testStopAtOtherWithReverse, but after a restart. */ @Test - @Ignore("Fails. Investigate what it needs to wait for.") public void testStopAtOtherWithReverseRestart() throws Throwable { assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); fRestart = true; @@ -813,7 +811,6 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase * enabled at the very start). */ @Test - @Ignore("TODO: this is not working because it does not insert the breakpoint propertly") public void testNoStopAtMainWithReverse() throws Throwable { assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); @@ -821,58 +818,47 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, true); - // MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED - // MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED - // MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED - // see testNoStopAtMain() - + CDIDebugModel.createFunctionBreakpoint(null, ResourcesPlugin.getWorkspace().getRoot(), 0, "stopAtOther", -1, -1, + -1, true, 0, "", true); doLaunch(); MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); - - // The initial stopped event is not the last stopped event. - // With reverse we have to stop the program, turn on reverse and start it again. - // Let's get the frame where we really are stopped right now. + assertTrue("Expected to stop at stopAtOther but got " + stoppedEvent.getFrame().getFunction() + ":", + stoppedEvent.getFrame().getFunction().equals("stopAtOther")); final IExecutionDMContext execDmc = stoppedEvent.getDMContext(); IFrameDMData frame = SyncUtil.getFrameData(execDmc, 0); - - // Make sure we stopped at the first line of main - assertTrue( - "Expected to stop at main:" + LAST_LINE_IN_MAIN + " but got " + frame.getFunction() + ":" - + Integer.toString(frame.getLine()), - frame.getFunction().equals("main") && frame.getLine() == LAST_LINE_IN_MAIN); + assertTrue("Expected to stop at stopAtOther but got " + frame.getFunction() + ":", + frame.getFunction().equals("stopAtOther")); // Now step backwards all the way to the start to make sure reverse was enabled from the very start final ServiceEventWaitor eventWaitor = new ServiceEventWaitor<>(fSession, MIStoppedEvent.class); - final int REVERSE_NUM_STEPS = 3; - Query query2 = new Query<>() { - @Override - protected void execute(DataRequestMonitor rm) { - fGdbControl.queueCommand( - fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, REVERSE_NUM_STEPS), rm); - } - }; - { + int maxSteps = 100; + while (--maxSteps > 0) { + Query query2 = new Query<>() { + @Override + protected void execute(DataRequestMonitor rm) { + fGdbControl.queueCommand(fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, 1), rm); + } + }; fGdbControl.getExecutor().execute(query2); query2.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS); + stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); + + if (stoppedEvent.getFrame().getFunction().equals("main") + && stoppedEvent.getFrame().getLine() == FIRST_LINE_IN_MAIN) { + // success + return; + } + } - - stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); - - assertTrue( - "Expected to stop at main:" + (FIRST_LINE_IN_MAIN) + " but got " + stoppedEvent.getFrame().getFunction() - + ":" + Integer.toString(stoppedEvent.getFrame().getLine()), - stoppedEvent.getFrame().getFunction().equals("main") - && stoppedEvent.getFrame().getLine() == FIRST_LINE_IN_MAIN); + fail("Expected to eventually stop at main:" + (FIRST_LINE_IN_MAIN)); } /** * Repeat the test testNoStopAtMainWithReverse, but after a restart. - * TODO: remove ignore when parent test is fixed */ @Test - @Ignore public void testNoStopAtMainWithReverseRestart() throws Throwable { assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); fRestart = true; diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlReverseTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlReverseTest.java index fed626e256d..1ca26698f30 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlReverseTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRunControlReverseTest.java @@ -18,14 +18,12 @@ 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.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; import org.eclipse.cdt.dsf.debug.service.command.IEventListener; -import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; @@ -101,25 +99,7 @@ public class MIRunControlReverseTest extends BaseParametrizedTestCase { @Test public void testQueryHandling() throws Throwable { SyncUtil.runToLocation("testLocals"); - - assertTrue("Reverse debugging is not supported", fRunCtrl instanceof IReverseRunControl); - final IReverseRunControl reverseService = (IReverseRunControl) fRunCtrl; - - Query query = new Query<>() { - @Override - protected void execute(final DataRequestMonitor rm) { - reverseService.enableReverseMode(fGDBCtrl.getContext(), true, new ImmediateRequestMonitor(rm) { - @Override - protected void handleSuccess() { - reverseService.isReverseModeEnabled(fGDBCtrl.getContext(), rm); - } - }); - } - }; - - fSession.getExecutor().execute(query); - Boolean enabled = query.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS); - assertTrue("Reverse debugging should be enabled", enabled); + SyncUtil.enableReverseMode(); // Step forward a couple of times SyncUtil.step(2, StepType.STEP_OVER);