1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-13 19:25:38 +02:00

Bug 314174: Eliminate the 1s wait at start of each DSF-GDB test.

This commit is contained in:
John Cortell 2010-05-27 21:08:28 +00:00
parent c48835544d
commit 87aa0351e6

View file

@ -17,9 +17,14 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; 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.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.service.DsfSession.SessionStartedListener;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.cdt.utils.spawner.ProcessFactory; import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
@ -31,6 +36,7 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.ILaunchManager;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -51,7 +57,14 @@ public class BaseTestCase {
private static Map<String, Object> attrs = new HashMap<String, Object>(); private static Map<String, Object> attrs = new HashMap<String, Object>();
private static Process gdbserverProc = null; private static Process gdbserverProc = null;
private MIStoppedEvent fInitialStoppedEvent = null; /** The MI event associated with the breakpoint at main() */
private MIStoppedEvent fInitialStoppedEvent;
/** Flag we set to true when the target has reached the breakpoint at main() */
private boolean fTargetSuspended;
/** Event semaphore we set when the target has reached the breakpoint at main() */
final private String fTargetSuspendedSem = new String(); // just used as a semaphore
public GdbLaunch getGDBLaunch() { return fLaunch; } public GdbLaunch getGDBLaunch() { return fLaunch; }
@ -59,7 +72,7 @@ public class BaseTestCase {
attrs.put(key, value); attrs.put(key, value);
} }
public MIStoppedEvent getInitialStoppedEvent() { return fInitialStoppedEvent; } public synchronized MIStoppedEvent getInitialStoppedEvent() { return fInitialStoppedEvent; }
@BeforeClass @BeforeClass
public static void baseBeforeClassMethod() { public static void baseBeforeClassMethod() {
@ -96,28 +109,41 @@ public class BaseTestCase {
ILaunchConfigurationWorkingCopy lcWorkingCopy = lcType.newInstance( ILaunchConfigurationWorkingCopy lcWorkingCopy = lcType.newInstance(
null, null,
launchMgr.generateUniqueLaunchConfigurationNameFrom("Test Launch")); //$NON-NLS-1$ launchMgr.generateLaunchConfigurationName("Test Launch")); //$NON-NLS-1$
assert lcWorkingCopy != null; assert lcWorkingCopy != null;
lcWorkingCopy.setAttributes(attrs); lcWorkingCopy.setAttributes(attrs);
final ILaunchConfiguration lc = lcWorkingCopy.doSave(); final ILaunchConfiguration lc = lcWorkingCopy.doSave();
assert lc != null;
// Register ourselves as a listener for the new session so that we can
// register ourselves with that particular session before any events
// occur. We want to find out when the break on main() occurs.
SessionStartedListener sessionStartedListener = new SessionStartedListener() {
public void sessionStarted(DsfSession session) {
session.addServiceEventListener(BaseTestCase.this, null);
}
};
// Launch the debug session. The session-started listener will be called
// before the launch() call returns (unless, of course, there was a
// problem launching and no session is created).
DsfSession.addSessionStartedListener(sessionStartedListener);
fLaunch = (GdbLaunch)lc.launch(ILaunchManager.DEBUG_MODE, new NullProgressMonitor()); fLaunch = (GdbLaunch)lc.launch(ILaunchManager.DEBUG_MODE, new NullProgressMonitor());
assert fLaunch != null; DsfSession.removeSessionStartedListener(sessionStartedListener);
try { // Wait for the program to hit the breakpoint at main() before
// Also wait for the program to stop before allowing tests to start // proceeding. All tests assume that stable initial state. Two
// This should be done as soon as we have the launch, to avoid missing the Stopped // seconds is plenty; we typically get to that state in a few
// event. If we do miss it, we'll just have a 10 second delay. // hundred milliseconds with the tiny test programs we use.
final ServiceEventWaitor<MIStoppedEvent> eventWaitor = synchronized (fTargetSuspendedSem) {
new ServiceEventWaitor<MIStoppedEvent>( fTargetSuspendedSem.wait(TestsPlugin.massageTimeout(2000));
fLaunch.getSession(), Assert.assertTrue(fTargetSuspended);
MIStoppedEvent.class); }
// In practice, most launches happen within 100-300 milliseconds // This should be a given if the above check passes
fInitialStoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); synchronized(this) {
} catch (Exception e) {} Assert.assertNotNull(fInitialStoppedEvent);
}
// If we started a gdbserver add it to the launch to make sure it is killed at the end // If we started a gdbserver add it to the launch to make sure it is killed at the end
if (gdbserverProc != null) { if (gdbserverProc != null) {
@ -129,6 +155,35 @@ public class BaseTestCase {
} }
/**
* We listen for the target to stop at the main breakpoint. This listener is
* installed when the session is created and we uninstall ourselves when we
* get to the breakpoint state, as we have no further need to monitor events
* beyond that point.
*/
@DsfServiceEventHandler
public void eventDispatched(IDMEvent<?> event) {
if (event instanceof MIStoppedEvent) {
// We get this low-level event first. Record the MI event; various
// tests use it for context
synchronized(this) {
fInitialStoppedEvent = (MIStoppedEvent)event;
}
}
else if (event instanceof ISuspendedDMEvent) {
// We get this higher level event shortly thereafter. We don't want
// to consider the session suspended until we get it. Set the event
// semaphore that will allow the test to proceed
synchronized (fTargetSuspendedSem) {
fTargetSuspended = true;
fTargetSuspendedSem.notify();
}
// no further need for this listener
fLaunch.getSession().removeServiceEventListener(BaseTestCase.this);
}
}
@After @After
public void baseAfterMethod() throws Exception { public void baseAfterMethod() throws Exception {
if (fLaunch != null) { if (fLaunch != null) {