mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-30 21:55:31 +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:
parent
554bf844d5
commit
549b9d00c0
6 changed files with 174 additions and 107 deletions
|
@ -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<MIInfo>(rm));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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<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
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MIInfo> query = new Query<>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIInfo> 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<MIStoppedEvent> eventWaitor = new ServiceEventWaitor<>(fSession, MIStoppedEvent.class);
|
||||
|
||||
final int REVERSE_NUM_STEPS = 3;
|
||||
Query<MIInfo> query2 = new Query<>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIInfo> rm) {
|
||||
fGdbControl.queueCommand(
|
||||
fGdbControl.getCommandFactory().createMIExecReverseNext(execDmc, REVERSE_NUM_STEPS), rm);
|
||||
}
|
||||
};
|
||||
{
|
||||
int maxSteps = 100;
|
||||
while (--maxSteps > 0) {
|
||||
Query<MIInfo> query2 = new Query<>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<MIInfo> 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;
|
||||
|
|
|
@ -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<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);
|
||||
SyncUtil.enableReverseMode();
|
||||
|
||||
// Step forward a couple of times
|
||||
SyncUtil.step(2, StepType.STEP_OVER);
|
||||
|
|
Loading…
Add table
Reference in a new issue