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

[303828] SyncUtil calls no longer wait indefinitely

This commit is contained in:
John Cortell 2010-02-26 20:27:29 +00:00
parent cf8ca123cf
commit 0ca9d1d016
3 changed files with 198 additions and 47 deletions

View file

@ -114,7 +114,9 @@ public class BaseTestCase {
new ServiceEventWaitor<MIStoppedEvent>(
fLaunch.getSession(),
MIStoppedEvent.class);
fInitialStoppedEvent = eventWaitor.waitForEvent(10000);
// In practice, most launches happen within 100-300 milliseconds
fInitialStoppedEvent = eventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
} catch (Exception e) {}
// If we started a gdbserver add it to the launch to make sure it is killed at the end

View file

@ -114,11 +114,22 @@ public class ServiceEventWaitor<V> {
}
if (timeout != WAIT_FOREVER) {
if (timeout/duration > 7.0) {
System.out.println("WARNING: Caller specified a timeout that was more than 7X what was necessary. The timeout is probably too loose.");
if (duration == 0) {
if (timeout > 1000) {
System.out.println("WARNING: Caller specified a timeout over a second but the operation was instantenous. The timeout is probably too loose.");
}
else if (timeout < 100) {
System.out.println("WARNING: Caller specified a timeout less than 100 milliseconds. Even though the operation completed instantaneously, the timeout is probably too tight.");
}
}
else if ((((float)(timeout - duration))/(float)duration) < 0.20) {
System.out.println("WARNING: Caller specified a timeout that was less than 20% above actual time. The timeout is probably too tight.");
else {
if (timeout/duration > 7.0 && timeout > 2000) {
// don't bother for timeouts less than 2 seconds
System.out.println("WARNING: Caller specified a timeout that was more than 7X what was necessary. The timeout is probably too loose.");
}
else if ((((float)(timeout - duration))/(float)duration) < 0.20) {
System.out.println("WARNING: Caller specified a timeout that was less than 20% above actual time. The timeout is probably too tight.");
}
}
}
else {

View file

@ -12,6 +12,8 @@ package org.eclipse.cdt.tests.dsf.gdb.framework;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import junit.framework.Assert;
@ -52,10 +54,14 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.DefaultTimeouts.ETimeout;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
/**
* Timeout wait values are in milliseconds, or WAIT_FOREVER.
*/
public class SyncUtil {
private static ICommandControlService fCommandControl;
@ -67,6 +73,8 @@ public class SyncUtil {
private static IContainerDMContext fGdbContainerDmc;
private static IBreakpointsTargetDMContext fBreakpointsDmc;
public static final int WAIT_FOREVER = ServiceEventWaitor.WAIT_FOREVER;
// Initialize some common things, once the session has been established
public static void initialize(DsfSession session) {
fSession = session;
@ -89,19 +97,27 @@ public class SyncUtil {
tracker.dispose();
}
public static MIStoppedEvent step(final StepType stepType, int numSteps) throws Throwable {
public static MIStoppedEvent step(final StepType stepType, int numSteps, int timeout) throws Throwable {
MIStoppedEvent retVal = null;
for (int i=0; i<numSteps; i++) {
retVal = step(stepType);
retVal = step(stepType, timeout);
}
return retVal;
}
public static MIStoppedEvent step(final StepType stepType) throws Throwable {
return step(fGdbContainerDmc, stepType);
return step(stepType, DefaultTimeouts.get(ETimeout.step));
}
public static MIStoppedEvent step(final StepType stepType, int timeout) throws Throwable {
return step(fGdbContainerDmc, stepType, timeout);
}
public static MIStoppedEvent step(final IExecutionDMContext dmc, final StepType stepType) throws Throwable {
return step(dmc, stepType, DefaultTimeouts.get(ETimeout.step));
}
public static MIStoppedEvent step(final IExecutionDMContext dmc, final StepType stepType, int timeout) throws Throwable {
final ServiceEventWaitor<MIStoppedEvent> eventWaitor =
new ServiceEventWaitor<MIStoppedEvent>(
@ -129,11 +145,16 @@ public class SyncUtil {
});
// Wait for the execution to suspend after the step
return eventWaitor.waitForEvent(ServiceEventWaitor.WAIT_FOREVER);
return eventWaitor.waitForEvent(timeout);
}
public static MIStoppedEvent runToLine(final IExecutionDMContext dmc, final String fileName, final String lineNo,
final boolean skipBreakpoints) throws Throwable {
final boolean skipBreakpoints) throws Throwable {
return runToLine(dmc, fileName, lineNo, skipBreakpoints, DefaultTimeouts.get(ETimeout.runToLine));
}
public static MIStoppedEvent runToLine(final IExecutionDMContext dmc, final String fileName, final String lineNo,
final boolean skipBreakpoints, int timeout) throws Throwable {
final ServiceEventWaitor<MIStoppedEvent> eventWaitor =
new ServiceEventWaitor<MIStoppedEvent>(
@ -152,24 +173,40 @@ public class SyncUtil {
});
// Wait for the execution to suspend after the step
return eventWaitor.waitForEvent(ServiceEventWaitor.WAIT_FOREVER);
return eventWaitor.waitForEvent(timeout);
}
public static MIStoppedEvent runToLine(final String fileName, final String lineNo,
final boolean skipBreakpoints) throws Throwable {
return runToLine(fGdbContainerDmc, fileName, lineNo, skipBreakpoints);
return runToLine(fileName, lineNo, skipBreakpoints, DefaultTimeouts.get(ETimeout.runToLine));
}
public static MIStoppedEvent runToLine(final String fileName, final String lineNo,
final boolean skipBreakpoints, int timeout) throws Throwable {
return runToLine(fGdbContainerDmc, fileName, lineNo, skipBreakpoints, timeout);
}
public static MIStoppedEvent runToLine(final String fileName, final String lineNo) throws Throwable {
return runToLine(fGdbContainerDmc, fileName, lineNo, false);
return runToLine(fileName, lineNo, DefaultTimeouts.get(ETimeout.runToLine));
}
public static MIStoppedEvent runToLine(final String fileName, final String lineNo, int timeout) throws Throwable {
return runToLine(fGdbContainerDmc, fileName, lineNo, false, timeout);
}
public static int addBreakpoint(final String location) throws Throwable {
return addBreakpoint(location, true);
return addBreakpoint(location, DefaultTimeouts.get(ETimeout.addBreakpoint));
}
public static int addBreakpoint(final String location, boolean temporary)
public static int addBreakpoint(final String location, int timeout) throws Throwable {
return addBreakpoint(location, true, timeout);
}
public static int addBreakpoint(final String location, boolean temporary) throws Throwable {
return addBreakpoint(location, temporary, DefaultTimeouts.get(ETimeout.addBreakpoint));
}
public static int addBreakpoint(final String location, boolean temporary, int timeout)
throws Throwable {
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
@ -190,14 +227,14 @@ public class SyncUtil {
new MIBreakInsert(fBreakpointsDmc, temporary, false, null, 0, location, 0),
addBreakDone);
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
wait.waitUntilDone(timeout);
assertTrue(wait.getMessage(), wait.isOK());
MIBreakInsertInfo info = (MIBreakInsertInfo) wait.getReturnInfo();
return info.getMIBreakpoints()[0].getNumber();
}
public static int[] getBreakpointList() throws Throwable {
public static int[] getBreakpointList(int timeout) throws Throwable {
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
@ -214,7 +251,7 @@ public class SyncUtil {
fCommandControl.queueCommand(new MIBreakList(fBreakpointsDmc), listDRM);
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
wait.waitUntilDone(timeout);
assertTrue(wait.getMessage(), wait.isOK());
MIBreakpoint[] breakpoints = listDRM.getData().getMIBreakpoints();
@ -225,11 +262,11 @@ public class SyncUtil {
return result;
}
public static void deleteBreakpoint(int breakpointIndex) throws Throwable {
deleteBreakpoint(new int[] {breakpointIndex});
public static void deleteBreakpoint(int breakpointIndex, int timeout) throws Throwable {
deleteBreakpoint(new int[] {breakpointIndex}, timeout);
}
public static void deleteBreakpoint(int[] breakpointIndices) throws Throwable {
public static void deleteBreakpoint(int[] breakpointIndices, int timeout) throws Throwable {
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
@ -249,12 +286,12 @@ public class SyncUtil {
new MIBreakDelete(fBreakpointsDmc, breakpointIndices), //$NON-NLS-1$
deleteBreakDone);
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
wait.waitUntilDone(timeout);
assertTrue(wait.getMessage(), wait.isOK());
}
public static MIStoppedEvent resumeUntilStopped(final IExecutionDMContext dmc) throws Throwable {
public static MIStoppedEvent resumeUntilStopped(final IExecutionDMContext dmc, int timeout) throws Throwable {
final ServiceEventWaitor<MIStoppedEvent> eventWaitor =
new ServiceEventWaitor<MIStoppedEvent>(
fSession,
@ -271,14 +308,18 @@ public class SyncUtil {
});
// Wait for the execution to suspend after the step
return eventWaitor.waitForEvent(ServiceEventWaitor.WAIT_FOREVER);
}
public static MIStoppedEvent resumeUntilStopped() throws Throwable {
return resumeUntilStopped(fGdbContainerDmc);
return eventWaitor.waitForEvent(timeout);
}
public static MIRunningEvent resume(final IExecutionDMContext dmc) throws Throwable {
public static MIStoppedEvent resumeUntilStopped() throws Throwable {
return resumeUntilStopped(DefaultTimeouts.get(ETimeout.resumeUntilStopped));
}
public static MIStoppedEvent resumeUntilStopped(int timeout) throws Throwable {
return resumeUntilStopped(fGdbContainerDmc, timeout);
}
public static MIRunningEvent resume(final IExecutionDMContext dmc, int timeout) throws Throwable {
final ServiceEventWaitor<MIRunningEvent> eventWaitor =
new ServiceEventWaitor<MIRunningEvent>(
fSession,
@ -295,29 +336,41 @@ public class SyncUtil {
});
// Wait for the execution to suspend after the step
return eventWaitor.waitForEvent(ServiceEventWaitor.WAIT_FOREVER);
return eventWaitor.waitForEvent(timeout);
}
public static MIRunningEvent resume() throws Throwable {
return resume(fGdbContainerDmc);
return resume(DefaultTimeouts.get(ETimeout.resume));
}
public static MIRunningEvent resume(int timeout) throws Throwable {
return resume(fGdbContainerDmc, timeout);
}
public static MIStoppedEvent waitForStop() throws Throwable {
return waitForStop(DefaultTimeouts.get(ETimeout.waitForStop));
}
public static MIStoppedEvent waitForStop(int timeout) throws Throwable {
final ServiceEventWaitor<MIStoppedEvent> eventWaitor =
new ServiceEventWaitor<MIStoppedEvent>(
fSession,
MIStoppedEvent.class);
// Wait for the execution to suspend
return eventWaitor.waitForEvent(ServiceEventWaitor.WAIT_FOREVER);
return eventWaitor.waitForEvent(timeout);
}
public static MIStoppedEvent runToLocation(final String location) throws Throwable {
return runToLocation(location, DefaultTimeouts.get(ETimeout.runToLocation));
}
public static MIStoppedEvent runToLocation(final String location, int timeout) throws Throwable {
// Set a temporary breakpoint and run to it.
// Note that if there were other breakpoints set ahead of this one,
// they will stop execution earlier than planned
addBreakpoint(location, true);
return resumeUntilStopped();
addBreakpoint(location, true, timeout);
return resumeUntilStopped(timeout);
}
public static IFrameDMContext getStackFrame(final IExecutionDMContext execCtx, final int level) throws Throwable {
@ -364,14 +417,99 @@ public class SyncUtil {
return fSession.getExecutor().submit(callable).get();
}
public static IMIExecutionDMContext createExecutionContext(final IContainerDMContext parentCtx, final int threadId)
throws Throwable {
Callable<IMIExecutionDMContext> callable = new Callable<IMIExecutionDMContext>() {
public IMIExecutionDMContext call() throws Exception {
return fRunControl.createMIExecutionContext(parentCtx, threadId);
}
};
return fSession.getExecutor().submit(callable).get();
}
public static IMIExecutionDMContext createExecutionContext(final IContainerDMContext parentCtx, final int threadId) throws Throwable {
Callable<IMIExecutionDMContext> callable = new Callable<IMIExecutionDMContext>() {
public IMIExecutionDMContext call() throws Exception {
return fRunControl.createMIExecutionContext(parentCtx, threadId);
}
};
return fSession.getExecutor().submit(callable).get();
}
static class DefaultTimeouts {
/**
* Overridable default timeout values. An override is specified using a
* system property that is "dsf.gdb.tests.timeout.default." plus the
* name of the enum below.
*/
enum ETimeout {
addBreakpoint,
deleteBreakpoint,
getBreakpointList,
createExecutionContext,
createExpression,
getFormattedValue,
getStackFrame,
resume,
resumeUntilStopped,
runToLine,
runToLocation,
step,
waitForStop
}
/**
* Map of timeout enums to their <b>harcoded</b> default value )in
* milliseconds). These can be individually overridden with a system
* property.
*
* <p>
* In practice, these operations are either very quick or the amount of
* time is hard to predict (depends on what the test is doing). For ones
* that are quick, we allot 1 second, which is ample. For the unknowns
* we allows 10 seconds, which is probably ample in most cases. Tests
* can provide larger values as needed in specific SyncUtil calls.
*/
private static Map<ETimeout,Integer> sTimeouts = new HashMap<ETimeout, Integer>();
static {
sTimeouts.put(ETimeout.addBreakpoint, 1000);
sTimeouts.put(ETimeout.deleteBreakpoint, 1000);
sTimeouts.put(ETimeout.getBreakpointList, 1000);
sTimeouts.put(ETimeout.createExecutionContext, 1000);
sTimeouts.put(ETimeout.createExpression, 1000);
sTimeouts.put(ETimeout.getFormattedValue, 1000);
sTimeouts.put(ETimeout.getStackFrame, 1000);
sTimeouts.put(ETimeout.resume, 1000);
sTimeouts.put(ETimeout.resumeUntilStopped, 10000); // 10 seconds
sTimeouts.put(ETimeout.runToLine, 10000); // 10 seconds
sTimeouts.put(ETimeout.step, 1000);
sTimeouts.put(ETimeout.waitForStop, 10000); // 10 seconds
}
/**
* Get the default timeout to use when the caller of a SyncUtil method
* doesn't specify one. We honor overrides specified via system
* properties, as well as apply the multiplier that can also be
* specified via a system property.
*
* @param timeout
* the timeout enum
* @return the default value
*/
static int get(ETimeout timeout) {
int value = -1;
final String propname = "dsf.gdb.tests.timeout.default." + timeout.toString();
final String prop = System.getProperty(propname);
if (prop != null) {
try {
value = Integer.valueOf(value);
if (value < 0) {
TestsPlugin.log(new Status(IStatus.ERROR, TestsPlugin.getUniqueIdentifier(), "\"" + propname + "\" property incorrectly specified. Should be an integer value or not specified at all.")); //$NON-NLS-1$
value = -1;
}
}
catch (NumberFormatException exc) {
TestsPlugin.log(new Status(IStatus.ERROR, TestsPlugin.getUniqueIdentifier(), "\"" + propname + "\" property incorrectly specified. Should be an integer value or not specified at all.")); //$NON-NLS-1$
value = -1;
}
}
if (value == -1) {
value = sTimeouts.get(timeout);
}
assert value >= 0;
return TestsPlugin.massageTimeout(value);
}
}
}