1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 06:05:24 +02:00

Bug 572742: Fix reverse debugging enable at startup

This fixes and reenables a bunch of reverse debugging tests

Change-Id: Ib44a60c06c4c94b2dfca4631794f960ed99a0465
This commit is contained in:
Jonah Graham 2021-04-09 10:02:51 -04:00
parent 554bf844d5
commit 549b9d00c0
6 changed files with 174 additions and 107 deletions

View file

@ -263,6 +263,14 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
if (fUserBreakpoint != null) { if (fUserBreakpoint != null) {
fUserBreakpointIsOnMain = fBreakPointForReverse.getAddress() fUserBreakpointIsOnMain = fBreakPointForReverse.getAddress()
.equals(fUserBreakpoint.getAddress()); .equals(fUserBreakpoint.getAddress());
if (fUserBreakpointIsOnMain) {
String number = fBreakPointForReverse.getNumber();
fBreakPointForReverse = fUserBreakpoint;
fCommandControl.queueCommand(
fCommandFactory.createMIBreakDelete(bpTargetDmc, number),
new ImmediateDataRequestMonitor<MIInfo>(rm));
return;
}
} }
} }
} }

View file

@ -23,11 +23,15 @@ int envTest() {
} }
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ { 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 dummy = 1; // FIRST_LINE_IN_MAIN int var = 1; // GDB has incomplete support for reverse debugging - so for the purpose of tests reverse debug these simple assignment statements
envTest(); // main_init 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 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 36; // LAST_LINE_IN_MAIN
// Return special value to allow // Return special value to allow
// testing exit code feature // testing exit code feature

View file

@ -224,8 +224,11 @@ public class BaseTestCase {
private ILaunchConfiguration fLaunchConfiguration; private ILaunchConfiguration fLaunchConfiguration;
private boolean ignoreFirstStop = false;
public SessionEventListener(ILaunchConfiguration launchConfiguration) { public SessionEventListener(ILaunchConfiguration launchConfiguration) {
fLaunchConfiguration = launchConfiguration; fLaunchConfiguration = launchConfiguration;
this.ignoreFirstStop = SyncUtil.shouldIgnoreFirstStopAtStartup(launchConfiguration);
} }
public void setSession(DsfSession session) { public void setSession(DsfSession session) {
@ -260,22 +263,47 @@ public class BaseTestCase {
Object miEvent = iMIEvent.getMIEvent(); Object miEvent = iMIEvent.getMIEvent();
if (miEvent instanceof MIStoppedEvent) { if (miEvent instanceof MIStoppedEvent) {
if (ignoreFirstStop) {
ignoreFirstStop = false;
} else {
// Store the corresponding MI *stopped event // Store the corresponding MI *stopped event
fInitialStoppedEvent = (MIStoppedEvent) miEvent; fInitialStoppedEvent = (MIStoppedEvent) miEvent;
// Check the content of the frame for the method we // Check the content of the frame for the method we
// should stop at // should stop at
String stopAt = null; String stopAt = null;
boolean stopAtEnabled = true;
boolean reverseEnabledAtStartup = true;
try { try {
stopAt = fLaunchConfiguration.getAttribute( stopAt = fLaunchConfiguration.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); 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) { } catch (CoreException e) {
} }
if (!stopAtEnabled) {
success();
} else {
if (stopAt == null) if (stopAt == null)
stopAt = "main"; stopAt = "main";
MIFrame frame = fInitialStoppedEvent.getFrame(); MIFrame frame = fInitialStoppedEvent.getFrame();
if (frame != null && frame.getFunction() != null && frame.getFunction().indexOf(stopAt) != -1) { if (frame != null && frame.getFunction() != null
&& frame.getFunction().indexOf(stopAt) != -1) {
success();
}
}
}
}
}
}
}
private void success() {
// Set the event semaphore that will allow the test // Set the event semaphore that will allow the test
// to proceed // to proceed
synchronized (fTargetSuspendedSem) { synchronized (fTargetSuspendedSem) {
@ -287,10 +315,6 @@ public class BaseTestCase {
// listener // listener
fSession.removeServiceEventListener(this); fSession.removeServiceEventListener(this);
} }
}
}
}
}
public void waitUntilTargetSuspended() throws InterruptedException { public void waitUntilTargetSuspended() throws InterruptedException {
if (!fTargetSuspended) { if (!fTargetSuspended) {
@ -304,6 +328,7 @@ public class BaseTestCase {
public MIStoppedEvent getInitialStoppedEvent() { public MIStoppedEvent getInitialStoppedEvent() {
return fInitialStoppedEvent; return fInitialStoppedEvent;
} }
} }
/** /**

View file

@ -37,10 +37,12 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.eclipse.cdt.core.IAddress; 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.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; 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.Query;
import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor; import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
import org.eclipse.cdt.dsf.datamodel.DMContexts; 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.IFrameDMData;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData; 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.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles; import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo; import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2; import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses; 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.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl; 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.CoreException;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.MemoryByte; import org.eclipse.debug.core.model.MemoryByte;
/** /**
@ -152,6 +157,31 @@ public class SyncUtil {
fSession.getExecutor().submit(runnable).get(); 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<Boolean> query = new Query<>() {
@Override
protected void execute(final DataRequestMonitor<Boolean> 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 * 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 * fixed number of time/s using {@code numSteps}. For possible step types see
@ -1120,6 +1150,32 @@ public class SyncUtil {
return canRestart; 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}) * 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. // This is not the stopped event we were waiting for. Get the next one.
event = eventWaitor.waitForEvent(DefaultTimeouts.get(ETimeout.waitForStop)); 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; return event;
} }

View file

@ -29,7 +29,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; 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.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query; 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;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; 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.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.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData; 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.ServiceEventWaitor;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; 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.launching.TestsPlugin;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IProcess;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; 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 EXEC_NAME = "LaunchConfigurationAndRestartTestApp.exe";
protected static final String SOURCE_NAME = "LaunchConfigurationAndRestartTestApp.cc"; 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 FIRST_LINE_IN_MAIN;
protected int LAST_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 // The exit code returned by the test program
private static final int TEST_EXIT_CODE = 36; 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"); FIRST_LINE_IN_MAIN = getLineForTag("FIRST_LINE_IN_MAIN");
LAST_LINE_IN_MAIN = getLineForTag("LAST_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 @Override
@ -503,9 +505,10 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
assertTrue( assertTrue(
"Expected to stop at main:27 but got " + stoppedEvent.getFrame().getFunction() + ":" "Expected to stop at main:" + FIRST_LINE_IN_MAIN + " but got " + stoppedEvent.getFrame().getFunction()
+ Integer.toString(stoppedEvent.getFrame().getLine()), + ":" + Integer.toString(stoppedEvent.getFrame().getLine()),
stoppedEvent.getFrame().getFunction().equals("main") && stoppedEvent.getFrame().getLine() == 27); 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 * the launch to NOT "stop on main". We will verify that the first stop is
* at the breakpoint that we set. * at the breakpoint that we set.
*/ */
@Ignore
@Test @Test
public void testNoStopAtMain() throws Throwable { public void testNoStopAtMain() throws Throwable {
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false);
// Set this one as well to make sure it gets ignored // Set this one as well to make sure it gets ignored
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main"); 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 CDIDebugModel.createFunctionBreakpoint(null, ResourcesPlugin.getWorkspace().getRoot(), 0, "stopAtOther", -1, -1,
// to set it in the platorm. Ok, but how do I get an IResource that points to my binary? -1, true, 0, "", true);
// 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$
doLaunch(); doLaunch();
MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
assertTrue("Expected to stop at envTest but got " + stoppedEvent.getFrame().getFunction() + ":", assertTrue("Expected to stop at stopAtOther but got " + stoppedEvent.getFrame().getFunction() + ":",
stoppedEvent.getFrame().getFunction().equals("envTest")); 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. * Repeat the test testNoStopAtMain, but after a restart.
*/ */
@Ignore
@Test @Test
public void testNoStopAtMainRestart() throws Throwable { public void testNoStopAtMainRestart() throws Throwable {
fRestart = true; fRestart = true;
@ -709,11 +708,12 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
final int REVERSE_NUM_STEPS = 2; final int REVERSE_NUM_STEPS = 2;
final IExecutionDMContext execDmc = stoppedEvent.getDMContext(); final IExecutionDMContext execDmc = stoppedEvent.getDMContext();
IContainerDMContext containerDmc = SyncUtil.getContainerContext();
Query<MIInfo> query = new Query<>() { Query<MIInfo> query = new Query<>() {
@Override @Override
protected void execute(DataRequestMonitor<MIInfo> rm) { protected void execute(DataRequestMonitor<MIInfo> rm) {
fGdbControl.queueCommand( 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)); stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
assertTrue( assertTrue("Expected to stop at main:" + (three_steps_back_from_b_stopAtOther) + " but got "
"Expected to stop at main:" + (FIRST_LINE_IN_MAIN) + " but got " + stoppedEvent.getFrame().getFunction() + stoppedEvent.getFrame().getFunction() + ":" + Integer.toString(stoppedEvent.getFrame().getLine()),
+ ":" + Integer.toString(stoppedEvent.getFrame().getLine()),
stoppedEvent.getFrame().getFunction().equals("main") 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. * Repeat the test testStopAtOtherWithReverse, but after a restart.
*/ */
@Test @Test
@Ignore("Fails. Investigate what it needs to wait for.")
public void testStopAtOtherWithReverseRestart() throws Throwable { public void testStopAtOtherWithReverseRestart() throws Throwable {
assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2);
fRestart = true; fRestart = true;
@ -813,7 +811,6 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
* enabled at the very start). * enabled at the very start).
*/ */
@Test @Test
@Ignore("TODO: this is not working because it does not insert the breakpoint propertly")
public void testNoStopAtMainWithReverse() throws Throwable { public void testNoStopAtMainWithReverse() throws Throwable {
assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2);
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); 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(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main");
setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, true); setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, true);
// MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED CDIDebugModel.createFunctionBreakpoint(null, ResourcesPlugin.getWorkspace().getRoot(), 0, "stopAtOther", -1, -1,
// MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED -1, true, 0, "", true);
// MUST SET BREAKPOINT AT LAST LINE BUT BEFORE LAUNCH IS STARTED
// see testNoStopAtMain()
doLaunch(); doLaunch();
MIStoppedEvent stoppedEvent = getInitialStoppedEvent(); MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
assertTrue("Expected to stop at stopAtOther but got " + stoppedEvent.getFrame().getFunction() + ":",
// The initial stopped event is not the last stopped event. stoppedEvent.getFrame().getFunction().equals("stopAtOther"));
// 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.
final IExecutionDMContext execDmc = stoppedEvent.getDMContext(); final IExecutionDMContext execDmc = stoppedEvent.getDMContext();
IFrameDMData frame = SyncUtil.getFrameData(execDmc, 0); IFrameDMData frame = SyncUtil.getFrameData(execDmc, 0);
assertTrue("Expected to stop at stopAtOther but got " + frame.getFunction() + ":",
// Make sure we stopped at the first line of main frame.getFunction().equals("stopAtOther"));
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);
// Now step backwards all the way to the start to make sure reverse was enabled from the very start // Now step backwards all the way to the start to make sure reverse was enabled from the very start
final ServiceEventWaitor<MIStoppedEvent> eventWaitor = new ServiceEventWaitor<>(fSession, MIStoppedEvent.class); final ServiceEventWaitor<MIStoppedEvent> eventWaitor = new ServiceEventWaitor<>(fSession, MIStoppedEvent.class);
final int REVERSE_NUM_STEPS = 3; int maxSteps = 100;
while (--maxSteps > 0) {
Query<MIInfo> query2 = new Query<>() { Query<MIInfo> query2 = new Query<>() {
@Override @Override
protected void execute(DataRequestMonitor<MIInfo> rm) { protected void execute(DataRequestMonitor<MIInfo> rm) {
fGdbControl.queueCommand( fGdbControl.queueCommand(fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, 1), rm);
fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, REVERSE_NUM_STEPS), rm);
} }
}; };
{
fGdbControl.getExecutor().execute(query2); fGdbControl.getExecutor().execute(query2);
query2.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS); query2.get(TestsPlugin.massageTimeout(500), TimeUnit.MILLISECONDS);
}
stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); stoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
assertTrue( if (stoppedEvent.getFrame().getFunction().equals("main")
"Expected to stop at main:" + (FIRST_LINE_IN_MAIN) + " but got " + stoppedEvent.getFrame().getFunction() && stoppedEvent.getFrame().getLine() == FIRST_LINE_IN_MAIN) {
+ ":" + Integer.toString(stoppedEvent.getFrame().getLine()), // success
stoppedEvent.getFrame().getFunction().equals("main") return;
&& 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. * Repeat the test testNoStopAtMainWithReverse, but after a restart.
* TODO: remove ignore when parent test is fixed
*/ */
@Test @Test
@Ignore
public void testNoStopAtMainWithReverseRestart() throws Throwable { public void testNoStopAtMainWithReverseRestart() throws Throwable {
assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2); assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_2);
fRestart = true; fRestart = true;

View file

@ -18,14 +18,12 @@ import java.util.concurrent.TimeoutException;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; 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.concurrent.Query;
import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
import org.eclipse.cdt.dsf.debug.service.command.IEventListener; 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.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
@ -101,25 +99,7 @@ public class MIRunControlReverseTest extends BaseParametrizedTestCase {
@Test @Test
public void testQueryHandling() throws Throwable { public void testQueryHandling() throws Throwable {
SyncUtil.runToLocation("testLocals"); SyncUtil.runToLocation("testLocals");
SyncUtil.enableReverseMode();
assertTrue("Reverse debugging is not supported", fRunCtrl instanceof IReverseRunControl);
final IReverseRunControl reverseService = (IReverseRunControl) fRunCtrl;
Query<Boolean> query = new Query<>() {
@Override
protected void execute(final DataRequestMonitor<Boolean> 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);
// Step forward a couple of times // Step forward a couple of times
SyncUtil.step(2, StepType.STEP_OVER); SyncUtil.step(2, StepType.STEP_OVER);