1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Stop trying to side-step the fact that on Windows interrupting the target can leave it suspended prematurely, only to have it suspend again when you resume it. My previous attempt worked only some of the time. Trying to close the gap would be way too messy, so just skip the "while target running" tests on Windows.

This commit is contained in:
John Cortell 2010-06-01 18:07:55 +00:00
parent 2bedd8397b
commit 429c116b18
2 changed files with 141 additions and 166 deletions

View file

@ -1205,7 +1205,16 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void insertBreakpoint_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
@ -1219,9 +1228,10 @@ public class MIBreakpointsTest extends BaseTestCase {
MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fBreakpointsDmc, breakpoint);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for breakpoint to hit.
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure the correct BreakpointEvent was received
MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
@ -1248,7 +1258,16 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void insertInvalidBreakpoint_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
@ -1267,8 +1286,9 @@ public class MIBreakpointsTest extends BaseTestCase {
breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fBreakpointsDmc, breakpoint);
// Wait for breakpoint to hit.
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure the correct BreakpointEvent was received
MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
@ -1436,6 +1456,15 @@ public class MIBreakpointsTest extends BaseTestCase {
@Ignore("Not supported because the frame where we stop does not contain the expression")
@Test
public void insertWatchpoint_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a write watchpoint
Map<String, Object> watchpoint = new HashMap<String, Object>();
@ -1450,8 +1479,9 @@ public class MIBreakpointsTest extends BaseTestCase {
IBreakpointDMContext ref = insertBreakpoint(fBreakpointsDmc, watchpoint);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for breakpoint to hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure that right BreakpointEvents were received
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
@ -1716,6 +1746,15 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void removeBreakpoint_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
@ -1741,8 +1780,9 @@ public class MIBreakpointsTest extends BaseTestCase {
removeBreakpoint(ref);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for the breakpoint to hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 4);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(4);
// Ensure the correct BreakpointEvent was received
assertTrue("BreakpointEvent problem: expected " + 4 + " BREAKPOINT event(s), received "
@ -1936,6 +1976,15 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void updateBreakpoint_ModifyCondition_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
@ -1966,8 +2015,9 @@ public class MIBreakpointsTest extends BaseTestCase {
updateBreakpoint(ref, delta);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for the breakpoint to hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure that right BreakpointEvents were received
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
@ -2303,6 +2353,15 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void updateBreakpoint_ModifyCount_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
@ -2334,8 +2393,9 @@ public class MIBreakpointsTest extends BaseTestCase {
updateBreakpoint(ref, delta);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for the breakpoint to hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure that right BreakpointEvents were received
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
@ -2440,6 +2500,15 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void updateBreakpoint_Disable_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
@ -2476,10 +2545,9 @@ public class MIBreakpointsTest extends BaseTestCase {
updateBreakpoint(ref, delta);
assertTrue(fWait.getMessage(), fWait.isOK());
// Ensure that right BreakpointEvents were received
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
+ fBreakpointEventCount, fBreakpointEventCount == 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
@ -2609,6 +2677,15 @@ public class MIBreakpointsTest extends BaseTestCase {
// ------------------------------------------------------------------------
@Test
public void updateBreakpoint_Enable_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Create a line breakpoint
Map<String, Object> breakpoint = new HashMap<String, Object>();
@ -2640,8 +2717,9 @@ public class MIBreakpointsTest extends BaseTestCase {
updateBreakpoint(ref, delta);
assertTrue(fWait.getMessage(), fWait.isOK());
// Wait for the breakpoint to hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure that right BreakpointEvents were received
assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
@ -3298,73 +3376,4 @@ public class MIBreakpointsTest extends BaseTestCase {
assertTrue("BreakpointEvent problem: expected watchpoint to be deleted after going out of scope",
watchpoint1 == null);
}
/**
* This method allows the while-target-running tests to side-step a bug in
* Windows gdb. To perform a breakpoint operation while the target is
* running, the DSF debugger temporarily suspends the target (gdb) with a
* SIGINT, carries out the operation, and then resumes the target. On
* Windows gdbs, there's a race condition problem with the SIGINT handling
* resulting in the target suspending for a reason other than the SIGINT.
* Resuming the target, though, will result in the target suspending
* again...this time for the SIGINT.
*
* See http://sourceware.org/ml/gdb-patches/2008-05/msg00264.html
*
* I've looked at the latest gdb sources and the problem has not yet been
* fixed. Search "FIXME: brobecker/2008-05-20" in windows-nat.c
*
* @param waitForStop
* indicates whether we should first wait for the target to stop.
* Otherwise we just wait until [eventCount] number of breakpoint
* events have occurred. If this arg is true, we return the
* MIStoppedEvent.
* @param eventCount
* the number of breakpoint events to wait for
* @return the stopped event, if [waitForStop] is true; otherwise null
* @throws Throwable
*/
MIStoppedEvent waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(boolean waitForStop, int eventCount) throws Throwable {
MIStoppedEvent event = null;
if (waitForStop) {
// The target program should be in the middle of a one second
// sleep() call. Most tests involve setting a breakpoint at
// some line after the sleep call. Allow up to three seconds
// for the sleep() call to complete and the breakpoint to be
// hit.
event = SyncUtil.waitForStop(3000);
}
if (Platform.getOS().equals(Platform.OS_WIN32)) {
// Normally, we would now give a couple of seconds for any
// additional expected breakpoint events to occur after the target's
// sleep call returns and fail the test if they don't. But the
// Windws gdb bug may have gotten in the way. If it has, the target
// is in an unexpected suspended state instead of running or stopped
// at the test breakpoint. We just don't know. So, we wait two
// seconds in case everything is actually behaving normally, since
// that's how patient waitForBreakpointEvent() is. If waitForStop is
// false, we need to allow enough time for the sleep() to return AND
// any subsequent breakpoint events to occur.
Thread.sleep(TestsPlugin.massageTimeout(waitForStop ? 2000 : 5000));
assertTrue("We should have gotten at least one breakpoint event", fBreakpointEventCount >= 1);
if (fBreakpointEventCount < eventCount) {
// It's likely we ran into the gdb bug. We can ignore it (since
// it's out of our control) and proceed to test whether the
// breakpoint operation was properly carried out.
System.out.println("Performing an additional resume to work around Windows gdb bug");
SyncUtil.resume();
if (waitForStop) {
event = SyncUtil.waitForStop(4000);
}
}
}
// OK, at this point, all the expected breakpoint events should have
// occurred, or we really have a problem (unrelated to the gdb bug)
waitForBreakpointEvent(eventCount);
return event;
}
}

View file

@ -79,8 +79,6 @@ import org.junit.runner.RunWith;
*
* Refer to the JUnit4 documentation for an explanation of the annotations.
*
* NOTE: the WhileTargetRunning tests intermittently fail with MinGW gdb 7.0 and
* fail 100% with cygwin. Bug 304096 will address this.
*/
@RunWith(BackgroundRunner.class)
@ -731,6 +729,16 @@ public class MICatchpointsTest extends BaseTestCase {
*/
@Test
public void insertCatchpoint_WhileTargetRunning() throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Run the program. It will make a two second sleep() call, during which time...
SyncUtil.resume();
@ -743,8 +751,10 @@ public class MICatchpointsTest extends BaseTestCase {
assertTrue(fWait.getMessage(), fWait.isOK());
// After the sleep, the test app throws a C++ exception. Wait for the
// catchpoint to hit.
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// catchpoint to hit and for the expected number of breakpoint events to
// have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
// Ensure that right breakpoint events were received. One indicating the
// catchpoint was created, another indicating it was hit
@ -916,6 +926,16 @@ public class MICatchpointsTest extends BaseTestCase {
* one.
*/
private void removeCatchpoint_WhileTargetRunning(boolean removeThrow) throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Set a line breakpoint at the sleep() call. We need to get the program
// past the initial loop that throws and catches C++ exceptions.
IBreakpointDMContext refLineBkpt = setLineBreakpoint(LINE_NUMBER_SLEEP_CALL);
@ -937,7 +957,10 @@ public class MICatchpointsTest extends BaseTestCase {
// After the sleep, the test app throws a C++ exception and catches it.
// The catchpoint we DIDN'T remove should stop the program
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for catchpoint to hit and for the expected number of breakpoint
// events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
assertTrue("stopped event is of an unexpected type: " + event.getClass().getName(), event instanceof MIBreakpointHitEvent);
MIBreakpointHitEvent bkptHitEvent = (MIBreakpointHitEvent)event;
MIBreakpointDMData bkptNotRemoved = (MIBreakpointDMData) getBreakpoint(removeThrow ? refCatch : refThrow);
@ -1058,6 +1081,16 @@ public class MICatchpointsTest extends BaseTestCase {
* one.
*/
private void updateCatchpoint_WhileTargetRunning(boolean modifyThrow) throws Throwable {
// Interrupting the target on Windows is susceptible to an additional,
// unwanted suspension. That means that silently interrupting the target
// to set/modify/remove a breakpoint then resuming it can leave the
// target in a suspended state. Unfortunately, there is nothing
// practical CDT can do to address this issue except wait for the gdb
// folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27
if (Platform.getOS().equals(Platform.OS_WIN32)) {
return;
}
// Set a line breakpoint at the sleep() call.
IBreakpointDMContext refLineBkpt = setLineBreakpoint(LINE_NUMBER_SLEEP_CALL);
@ -1076,7 +1109,7 @@ public class MICatchpointsTest extends BaseTestCase {
assertEquals("Target stopped as expected, but the responsible breakpoint was not the expected one", lineBkpt.getNumber(), fBreakpointRef);
clearEventCounters();
// Resume the program. It will make a two second sleep() call, during which time...
// Resume the program. It will make a one second sleep() call, during which time...
SyncUtil.resume();
// ...we modify one of the catchpoints's condition
@ -1084,7 +1117,9 @@ public class MICatchpointsTest extends BaseTestCase {
// After the sleep, the test app throws a C++ exception and catches it.
// So, the catchpoint whose condition we modified should get hit
MIStoppedEvent event = waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(true, 2);
// Wait for breakpoint to hit and for the expected number of breakpoint events to have occurred
MIStoppedEvent event = SyncUtil.waitForStop(3000);
waitForBreakpointEvent(2);
assertTrue("stopped event is of an unexpected type: " + event.getClass().getName(), event instanceof MIBreakpointHitEvent);
MIBreakpointHitEvent bkptHitEvent = (MIBreakpointHitEvent)event;
MIBreakpointDMData bkptUpdated = (MIBreakpointDMData) getBreakpoint(modifyThrow ? refThrow : refCatch);
@ -1208,75 +1243,6 @@ public class MICatchpointsTest extends BaseTestCase {
assertNull(GdbCatchpoints.gdbCatchpointKeywordToEvent("signals"));
}
/**
* This method allows the while-target-running tests to side-step a bug in
* Windows gdb. To perform a breakpoint operation while the target is
* running, the DSF debugger temporarily suspends the target (gdb) with a
* SIGINT, carries out the operation, and then resumes the target. On
* Windows gdbs, there's a race condition problem with the SIGINT handling
* resulting in the target suspending for a reason other than the SIGINT.
* Resuming the target, though, will result in the target suspending
* again...this time for the SIGINT.
*
* See http://sourceware.org/ml/gdb-patches/2008-05/msg00264.html
*
* I've looked at the latest gdb sources and the problem has not yet been
* fixed. Search "FIXME: brobecker/2008-05-20" in windows-nat.c
*
* @param waitForStop
* indicates whether we should first wait for the target to stop.
* Otherwise we just wait until [eventCount] number of breakpoint
* events have occurred. If this arg is true, we return the
* MIStoppedEvent.
* @param eventCount
* the number of breakpoint events to wait for
* @return the stopped event, if [waitForStop] is true; otherwise null
* @throws Throwable
*/
MIStoppedEvent waitForBreakpointEventsAfterBreakpointOperationWhileTargetRunning(boolean waitForStop, int eventCount) throws Throwable {
MIStoppedEvent event = null;
if (waitForStop) {
// The target program should be in the middle of a one second
// sleep() call. Most tests involve setting a breakpoint at
// some line after the sleep call. Allow up to three seconds
// for the sleep() call to complete and the breakpoint to be
// hit.
event = SyncUtil.waitForStop(3000);
}
if (Platform.getOS().equals(Platform.OS_WIN32)) {
// Normally, we would now give a couple of seconds for any
// additional expected breakpoint events to occur after the target's
// sleep call returns and fail the test if they don't. But the
// Windws gdb bug may have gotten in the way. If it has, the target
// is in an unexpected suspended state instead of running or stopped
// at the test breakpoint. We just don't know. So, we wait two
// seconds in case everything is actually behaving normally, since
// that's how patient waitForBreakpointEvent() is. If waitForStop is
// false, we need to allow enough time for the sleep() to return AND
// any subsequent breakpoint events to occur.
Thread.sleep(TestsPlugin.massageTimeout(waitForStop ? 2000 : 5000));
int eventsReceived = totalBreakpointEventsCount();
assertTrue("We should have gotten at least one breakpoint event", eventsReceived >= 1);
if (eventsReceived < eventCount) {
// It's likely we ran into the gdb bug. We can ignore it (since
// it's out of our control) and proceed to test whether the
// breakpoint operation was properly carried out.
System.out.println("Performing an additional resume to work around Windows gdb bug");
SyncUtil.resume();
if (waitForStop) {
event = SyncUtil.waitForStop(4000);
}
}
}
// OK, at this point, all the expected breakpoint events should have
// occurred, or we really have a problem (unrelated to the gdb bug)
waitForBreakpointEvent(eventCount);
return event;
}
/**
* Set a line breakpoint and validate it was set correctly.
*