1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-10 17:55:39 +02:00

Bug 439926 - CommandTimeout tests can fail on fast machines

Change-Id: I7bd4862cb8b3900a2fc41ad7476b2dff6f541009
Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/30144
This commit is contained in:
Marc Khouzam 2014-07-18 16:06:03 -04:00
parent 947b25009a
commit 90718216f1
4 changed files with 112 additions and 73 deletions

View file

@ -20,7 +20,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: org.eclipse.cdt.dsf.gdb, Export-Package: org.eclipse.cdt.dsf.gdb,
org.eclipse.cdt.dsf.gdb.actions, org.eclipse.cdt.dsf.gdb.actions,
org.eclipse.cdt.dsf.gdb.breakpoints, org.eclipse.cdt.dsf.gdb.breakpoints,
org.eclipse.cdt.dsf.gdb.internal;x-friends:="org.eclipse.cdt.dsf.gdb.ui,org.eclipse.cdt.debug.gdbjtag.ui", org.eclipse.cdt.dsf.gdb.internal;x-friends:="org.eclipse.cdt.dsf.gdb.ui,org.eclipse.cdt.debug.gdbjtag.ui,org.eclipse.cdt.tests.dsf.gdb",
org.eclipse.cdt.dsf.gdb.internal.commands;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.dsf.gdb.internal.commands;x-friends:="org.eclipse.cdt.dsf.gdb.ui",
org.eclipse.cdt.dsf.gdb.internal.memory;x-internal:=true, org.eclipse.cdt.dsf.gdb.internal.memory;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.service.command.commands;x-internal:=true, org.eclipse.cdt.dsf.gdb.internal.service.command.commands;x-internal:=true,

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2010 Ericsson and others. * Copyright (c) 2007, 2014 Ericsson and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -31,6 +31,7 @@ import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.service.DsfSession.SessionStartedListener; 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.tests.dsf.gdb.tests.ITestConstants;
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;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
@ -215,6 +216,7 @@ public class BaseTestCase {
launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, true); launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, true);
launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_HOST, "localhost"); launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_HOST, "localhost");
launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_PORT, "9999"); launchAttributes.put(IGDBLaunchConfigurationConstants.ATTR_PORT, "9999");
launchAttributes.put(ITestConstants.LAUNCH_GDB_SERVER, true);
setGdbVersion(); setGdbVersion();
@ -236,9 +238,7 @@ public class BaseTestCase {
boolean postMortemLaunch = launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE) boolean postMortemLaunch = launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE); .equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE);
// First check if we should launch gdbserver in the case of a remote session launchGdbServer();
if (reallyLaunchGDBServer())
launchGdbServer();
ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager(); ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType lcType = launchMgr.getLaunchConfigurationType("org.eclipse.cdt.tests.dsf.gdb.TestLaunch"); ILaunchConfigurationType lcType = launchMgr.getLaunchConfigurationType("org.eclipse.cdt.tests.dsf.gdb.TestLaunch");
@ -315,6 +315,12 @@ public class BaseTestCase {
* If the user specified a different host, things won't work. * If the user specified a different host, things won't work.
*/ */
private void launchGdbServer() { private void launchGdbServer() {
// First check if we should not launch gdbserver even for a remote session
if (launchAttributes.get(ITestConstants.LAUNCH_GDB_SERVER).equals(false)) {
System.out.println("Forcing to not start gdbserver for this test");
return;
}
if (launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE) if (launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)) { .equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)) {
if (launchAttributes.get(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP).equals(Boolean.TRUE)) { if (launchAttributes.get(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP).equals(Boolean.TRUE)) {
@ -392,16 +398,6 @@ public class BaseTestCase {
} }
} }
/**
* In some tests we need to start a gdbserver session without starting gdbserver.
* This method allows super classes of this class control the launch of gdbserver.
*
* @return whether gdbserver should be started
*/
protected boolean reallyLaunchGDBServer() {
return true;
}
@BeforeClass @BeforeClass
public static void setGlobalPreferences() { public static void setGlobalPreferences() {
IEclipsePreferences node = InstanceScope.INSTANCE.getNode(DebugPlugin.getUniqueIdentifier()); IEclipsePreferences node = InstanceScope.INSTANCE.getNode(DebugPlugin.getUniqueIdentifier());

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2012 Mentor Graphics and others. * Copyright (c) 2012, 2014 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,21 +7,32 @@
* *
* Contributors: * Contributors:
* Mentor Graphics - Initial API and implementation * Mentor Graphics - Initial API and implementation
* Marc Khouzam (Ericsson) - Update tests to use long timeouts (Bug 439926)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests; package org.eclipse.cdt.tests.dsf.gdb.tests;
import junit.framework.Assert; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants; import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITargetSelect;
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.BackgroundRunner; import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase;
import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugException; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -31,9 +42,11 @@ public class CommandTimeoutTest extends BaseTestCase {
private static boolean fgTimeoutEnabled = false; private static boolean fgTimeoutEnabled = false;
private static int fgTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT; private static int fgTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT;
private static boolean fgAutoTerminate;
@BeforeClass @BeforeClass
public static void doBeforeClass() throws Exception { public static void doBeforeClass() throws Exception {
// Save the original values of the timeout-related preferences
fgTimeoutEnabled = Platform.getPreferencesService().getBoolean( fgTimeoutEnabled = Platform.getPreferencesService().getBoolean(
GdbPlugin.PLUGIN_ID, GdbPlugin.PLUGIN_ID,
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT,
@ -44,6 +57,11 @@ public class CommandTimeoutTest extends BaseTestCase {
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE,
IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT, IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT,
null ); null );
fgAutoTerminate = Platform.getPreferencesService().getBoolean(
GdbPlugin.PLUGIN_ID,
IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB,
true,
null );
} }
@Override @Override
@ -51,65 +69,90 @@ public class CommandTimeoutTest extends BaseTestCase {
setLaunchAttributes(); setLaunchAttributes();
// Can't run the launch right away because each test needs to first set some // Can't run the launch right away because each test needs to first set some
// parameters. The individual tests will be responsible for starting the launch. // parameters. The individual tests will be responsible for starting the launch.
// Save the original values of the timeout-related preferences
} }
@Override @Override
public void doAfterTest() throws Exception { public void doAfterTest() throws Exception {
// Don't call super here, as the launch is already terminated // Don't call super here, as each test needs to deal with the launch in its own way
// Restore the timeout preferences // Restore the different preferences we might have changed
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, fgTimeoutEnabled ); node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, fgTimeoutEnabled );
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, fgTimeout ); node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, fgTimeout );
} node.putBoolean( IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB, fgAutoTerminate );
protected void performLaunchAndTerminate() throws Exception {
// perform the launch
doLaunch();
// terminate the launch right away
super.doAfterTest();
}
@Override
protected boolean reallyLaunchGDBServer() {
return false;
} }
/** /**
* Enables the timeout support and sets the timeout value to minimal - 1. * Sends a command to which GDB will take a long time to reply, so as to generate a timeout.
* Launch is expected to timeout on the first gdb command. * This is done after the launch has completed and while the debug session is ongoing.
*/ */
@Test @Test
public void firstCommandTimedOut() { public void commandTimedOutDuringSession() throws Exception {
// Enable timeout
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true ); node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true );
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1 ); node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 2000 );
// Note that sending a "target-select" command when a program is running will kill the program.
// If that triggers us to kill GDB, then our testcase won't have time to timeout.
// Therefore we set the preference to keep GDB alive even if the program is no longer running
node.putBoolean( IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB, false );
doLaunch();
final DsfSession session = getGDBLaunch().getSession();
ServiceEventWaitor<ICommandControlShutdownDMEvent> shutdownEventWaitor = new ServiceEventWaitor<ICommandControlShutdownDMEvent>(
session,
ICommandControlShutdownDMEvent.class);
// Send the command that will timeout
Query<MIInfo> query = new Query<MIInfo>() {
@Override
protected void execute( DataRequestMonitor<MIInfo> rm ) {
DsfServicesTracker tracker = new DsfServicesTracker( TestsPlugin.getBundleContext(), session.getId() );
ICommandControlService commandService = tracker.getService( ICommandControlService.class );
tracker.dispose();
commandService.queueCommand( new MITargetSelect( commandService.getContext(), "localhost", "1", false ), rm );
}
};
try { try {
performLaunchAndTerminate(); session.getExecutor().execute( query );
Assert.fail( "Launch is expected to fail" ); query.get();
// Cleanup in case the query does not throw the expected exception
super.doAfterTest();
Assert.fail( "Command is expected to timeout" );
} }
catch( Exception e ) { catch( Exception e ) {
processException( e ); processException( e );
} }
// Make sure we receive a shutdown event to confirm we have aborted the session
shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(5000));
} }
/** /**
* Tries to connect to gdbserver without starting it. * Sends a command to which GDB will take a long time to reply, so as to generate a timeout.
* Launch is expected to timeout on "target-remote" command. * This is done during the launch to verify that we properly handle that case.
*/ */
@Test @Test
public void remoteConnectionTimedOut() { public void commandTimedOutDuringLaunch() {
if ( !isRemoteSession() ) // Enable timeout
return;
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true ); node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true );
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1000 ); node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 2000 );
// Setup a remote launch so that it sends a "-target-remote" as part of the
// launch steps.
setLaunchAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE );
// We won't start gdbserver, so the command will timeout
setLaunchAttribute( ITestConstants.LAUNCH_GDB_SERVER, false);
try { try {
performLaunchAndTerminate(); doLaunch();
// Cleanup in case the launch does not throw the expected exception
super.doAfterTest();
Assert.fail( "Launch is expected to fail" ); Assert.fail( "Launch is expected to fail" );
} }
catch( Exception e ) { catch( Exception e ) {
@ -122,21 +165,16 @@ public class CommandTimeoutTest extends BaseTestCase {
* with the status code 20100 which indicates that a gdb command has been timed out. * with the status code 20100 which indicates that a gdb command has been timed out.
*/ */
private void processException( Exception e ) { private void processException( Exception e ) {
if ( e instanceof DebugException ) { Throwable t = getExceptionCause( e );
Throwable t = getExceptionCause( e ); Assert.assertTrue(
Assert.assertTrue(
"Unexpected exception", "Unexpected exception",
t instanceof CoreException && ((CoreException)t).getStatus().getCode() == 20100 ); t instanceof CoreException && ((CoreException)t).getStatus().getCode() == 20100 );
}
else {
Assert.fail( "Unexpected exception type" );
}
} }
private Throwable getExceptionCause(Throwable e) { private Throwable getExceptionCause(Throwable e) {
Throwable current = e; Throwable current = e;
while ( current instanceof CoreException ) { while ( true ) {
Throwable t = ((CoreException)current).getCause(); Throwable t = (current).getCause();
if ( t == null ) if ( t == null )
break; break;
current = t; current = t;

View file

@ -11,6 +11,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests; package org.eclipse.cdt.tests.dsf.gdb.tests;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
public interface ITestConstants { public interface ITestConstants {
public static final String SUFFIX_GDB_6_6 = "6.6"; public static final String SUFFIX_GDB_6_6 = "6.6";
@ -25,4 +27,7 @@ public interface ITestConstants {
public static final String SUFFIX_GDB_7_6 = "7.6"; public static final String SUFFIX_GDB_7_6 = "7.6";
public static final String SUFFIX_GDB_7_7 = "7.7"; public static final String SUFFIX_GDB_7_7 = "7.7";
public static final String SUFFIX_GDB_7_8 = "7.8"; public static final String SUFFIX_GDB_7_8 = "7.8";
// Attribute that allows a test to request not to start gdbserver even if the session is a remote one
public static final String LAUNCH_GDB_SERVER = TestsPlugin.PLUGIN_ID + ".launchGdbServer";
} }