1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Fix for the JUnit test due to Bug 223969.

The JUnit launch now re-uses (without any changes) the standard DSF launch sequence.  The problem then became that the tests would start too fast, before the suspend event was received.  To address this, I added a wait for the Suspend event in the BaseTestCase.baseBeforeMethod() which runs before every test.
This commit is contained in:
Marc Khouzam 2008-03-28 15:18:45 +00:00
parent c50257d07d
commit d571b6e48a
4 changed files with 33 additions and 381 deletions

View file

@ -16,6 +16,7 @@ import java.util.Map;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.dd.gdb.launching.GdbLaunch;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
@ -81,6 +82,16 @@ public class BaseTestCase {
// Now initialize our SyncUtility, since we have the launcher
SyncUtil.initialize(fLaunch.getSession());
try {
// Also wait for the program to stop before allowing tests to start
final ServiceEventWaitor<MIStoppedEvent> eventWaitor =
new ServiceEventWaitor<MIStoppedEvent>(
fLaunch.getSession(),
MIStoppedEvent.class);
eventWaitor.waitForEvent(10000);
} catch (Exception e) {}
}
@After

View file

@ -1,267 +0,0 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.tests.gdb.launching;
import java.util.concurrent.TimeUnit;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.concurrent.Sequence;
import org.eclipse.dd.dsf.debug.service.StepQueueManager;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.launching.GdbLaunch;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.CSourceLookup;
import org.eclipse.dd.mi.service.ExpressionService;
import org.eclipse.dd.mi.service.MIBreakpoints;
import org.eclipse.dd.mi.service.MIBreakpointsManager;
import org.eclipse.dd.mi.service.MIDisassembly;
import org.eclipse.dd.mi.service.MIMemory;
import org.eclipse.dd.mi.service.MIRegisters;
import org.eclipse.dd.mi.service.MIStack;
import org.eclipse.dd.mi.service.command.commands.MIBreakInsert;
import org.eclipse.dd.mi.service.command.commands.MIExecRun;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.debug.core.DebugException;
public class LaunchSequence extends Sequence {
public class EntryPointHitEventListener {
boolean fAborted = false;
boolean fFinished = false;
final RequestMonitor fRequestMonitor;
EntryPointHitEventListener(RequestMonitor requestMonitor) {
fRequestMonitor = requestMonitor;
}
@DsfServiceEventHandler
public void eventDispatched(@SuppressWarnings("unused")
MIStoppedEvent e) {
fFinished = true;
if (!fAborted) {
fSession.removeServiceEventListener(this);
fRequestMonitor.done();
}
}
}
Step[] fSteps = new Step[] {
// Create and initialize the Connection service.
new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
//
// Create the connection.
//
fCommandControl = new GDBControl(
fSession, getGDBPath(), fExecPath, GDBControl.SessionType.RUN, 30);
fCommandControl.initialize(requestMonitor);
}
},
/*
* If needed, insert breakpoint at main and run to it.
*/
new Step() {
private boolean fStopInMain = false;
private String fStopSymbol = null;
/**
* @return The return value actually indicates whether the get operation succeeded,
* not whether to stop.
*/
private boolean readStopAtMain(RequestMonitor requestMonitor) {
try {
fStopInMain = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, -1, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
requestMonitor.done();
return false;
}
return true;
}
private boolean readStopSymbol(RequestMonitor requestMonitor) {
try {
fStopSymbol = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT );
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
requestMonitor.done();
return false;
}
return true;
}
@Override
public void execute(final RequestMonitor requestMonitor) {
if (!readStopAtMain(requestMonitor)) return;
if (!fStopInMain) {
requestMonitor.done();
return;
}
if (!readStopSymbol(requestMonitor)) return;
// Create a listener to wait for the stopped event, and register as even handler.
// This handler will execute the requestMonitor.
final EntryPointHitEventListener entryPointHitListener = new EntryPointHitEventListener(requestMonitor);
fSession.addServiceEventListener(entryPointHitListener, null);
// Create a time-out, to abort if breakpoint not hit.
fSession.getExecutor().schedule(
new Runnable() { public void run() {
// Only process the event if we have not finished yet (hit the breakpoint).
if (!entryPointHitListener.fFinished) {
// Mark the listener as aborted, and unregister it as event listener.
entryPointHitListener.fAborted = true;
fSession.removeServiceEventListener(entryPointHitListener);
// Submit the error result for the step.
requestMonitor.setStatus(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED, "Timed out running to entry point.", null)); //$NON-NLS-1$
requestMonitor.done();
}
}},
60, TimeUnit.SECONDS);
// Insert a breakpoint at the requested stop symbol.
fCommandControl.queueCommand(
new MIBreakInsert(fCommandControl.getGDBDMContext(), true, false, null, 0, fStopSymbol, 0),
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
// After the break-insert is done, execute the -exec-run command.
fCommandControl.queueCommand(
new MIExecRun(fCommandControl.getGDBDMContext(), new String[0]),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
// Note : Do we not need to do something with the original requestMonitor?
// Do nothing. Execution was resumed and the EntryPointHitEventListener
// will resume execution
}
}
);
}
});
}
},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new GDBRunControl(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new StepQueueManager(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIMemory(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIStack(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new ExpressionService(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
fSourceLookup = new CSourceLookup(fSession);
fSourceLookup.initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
fSourceLookup.setSourceLookupDirector(
fCommandControl.getGDBDMContext(),
((CSourceLookupDirector)fLaunch.getSourceLocator()));
requestMonitor.done();
}},
new Step() { @Override
public void execute(final RequestMonitor requestMonitor) {
// Create the low-level breakpoint service
final MIBreakpoints bpService = new MIBreakpoints(fSession);
bpService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
requestMonitor.done();
}
});
}},
new Step() { @Override
public void execute(final RequestMonitor requestMonitor) {
// Create high-level breakpoint service and install breakpoints
// for the GDB debug context.
final MIBreakpointsManager bpmService = new MIBreakpointsManager(fSession, CDebugCorePlugin.PLUGIN_ID);
bpmService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
bpmService.startTrackingBreakpoints(fCommandControl.getGDBDMContext(), requestMonitor);
}
});
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIRegisters(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIDisassembly(fSession).initialize(requestMonitor);
}},
/*new Step() { public void execute(RequestMonitor requestMonitor) {
new GDBVariables(fSession).initialize(requestMonitor);
}},*/
};
final DsfSession fSession;
final GdbLaunch fLaunch;
final IPath fExecPath;
GDBControl fCommandControl;
CSourceLookup fSourceLookup;
public LaunchSequence(DsfSession session, GdbLaunch launch, IPath execPath) {
super(session.getExecutor());
fSession = session;
fLaunch = launch;
fExecPath = execPath;
}
@Override
public Step[] getSteps() {
return fSteps;
}
private IPath getGDBPath() {
IPath retVal = new Path("gdb.exe"); //$NON-NLS-1$
try {
retVal = new Path( fLaunch.getLaunchConfiguration().getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, IMILaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT ) );
} catch (CoreException e) {
}
return retVal;
}
}

View file

@ -1,108 +0,0 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.tests.gdb.launching;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.concurrent.Sequence;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.CSourceLookup;
import org.eclipse.dd.mi.service.ExpressionService;
import org.eclipse.dd.mi.service.MIBreakpoints;
import org.eclipse.dd.mi.service.MIBreakpointsManager;
import org.eclipse.dd.mi.service.MIDisassembly;
import org.eclipse.dd.mi.service.MIMemory;
import org.eclipse.dd.mi.service.MIRegisters;
import org.eclipse.dd.mi.service.MIStack;
public class ShutdownSequence extends Sequence {
String fSessionId;
String fApplicationName;
String fDebugModelId;
DsfServicesTracker fTracker;
public ShutdownSequence(DsfExecutor executor, String sessionId, RequestMonitor requestMonitor) {
super(executor, requestMonitor);
fSessionId = sessionId;
}
@Override
public Step[] getSteps() { return fSteps; }
private final Step[] fSteps = new Step[] {
new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
fTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSessionId);
requestMonitor.done();
}
@Override
public void rollBack(RequestMonitor requestMonitor) {
fTracker.dispose();
fTracker = null;
requestMonitor.done();
}
},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIDisassembly.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIRegisters.class, requestMonitor); }},
new Step() {
// Uninstall the breakpoints before the service is shut down.
@Override
public void execute(RequestMonitor requestMonitor) {
MIBreakpointsManager bpm = fTracker.getService(MIBreakpointsManager.class);
GDBControl commandControl = fTracker.getService(GDBControl.class);
if (bpm != null && commandControl != null) {
bpm.stopTrackingBreakpoints(commandControl.getGDBDMContext(), requestMonitor);
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
"Needed services not found.", null)); //$NON-NLS-1$
requestMonitor.done();
}
}
},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIBreakpointsManager.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIBreakpoints.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(CSourceLookup.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(ExpressionService.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIStack.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIMemory.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(GDBRunControl.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(GDBControl.class, requestMonitor); }},
new Step() { @Override public void execute(RequestMonitor requestMonitor) {
fTracker.dispose();
fTracker = null;
requestMonitor.done();
}}
};
@SuppressWarnings("unchecked")
private void shutdownService(Class clazz, RequestMonitor requestMonitor) {
IDsfService service = fTracker.getService(clazz);
if (service != null) {
service.shutdown(requestMonitor);
}
else {
requestMonitor.setStatus(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
"Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$
requestMonitor.done();
}
}
}

View file

@ -34,9 +34,13 @@ import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval;
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.gdb.launching.FinalLaunchSequence;
import org.eclipse.dd.gdb.launching.GdbLaunch;
import org.eclipse.dd.gdb.launching.ServicesLaunchSequence;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.gdb.service.command.GDBControl.SessionType;
import org.eclipse.dd.mi.service.command.AbstractCLIProcess;
import org.eclipse.dd.mi.service.command.MIInferiorProcess;
import org.eclipse.debug.core.DebugException;
@ -104,15 +108,16 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
monitor.worked( 1 );
// Create and invoke the launch sequence to create the debug control and services
final LaunchSequence launchSequence =
new LaunchSequence(launch.getSession(), launch, exePath);
launch.getSession().getExecutor().execute(launchSequence);
// Create and invoke the launch sequence to create the debug control and services
final ServicesLaunchSequence servicesLaunchSequence =
new ServicesLaunchSequence(launch.getSession(), launch, exePath);
launch.getSession().getExecutor().execute(servicesLaunchSequence);
try {
launchSequence.get();
servicesLaunchSequence.get();
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
throw new DebugException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in services launch sequence", e1.getCause())); //$NON-NLS-1$
}
launch.initializeControl();
@ -143,6 +148,17 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
throw new CoreException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
}
// Create and invoke the final launch sequence to setup GDB
final FinalLaunchSequence finalLaunchSequence =
new FinalLaunchSequence(launch.getSession().getExecutor(), launch, SessionType.RUN);
launch.getSession().getExecutor().execute(finalLaunchSequence);
try {
finalLaunchSequence.get();
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in final launch sequence", e1.getCause())); //$NON-NLS-1$
}
// Create a memory retrieval and register it with session
try {
launch.getDsfExecutor().submit( new Callable<Object>() {
@ -151,7 +167,7 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
GDBControl gdbControl = tracker.getService(GDBControl.class);
if (gdbControl != null) {
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
GDB_DEBUG_MODEL_ID, config, gdbControl.getGDBDMContext());
GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
}