From 1333b20ec54f01c7dfdbb44d430102a07b73d97e Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 22 Dec 2014 16:41:03 -0500 Subject: [PATCH] Avoid gdb bug in StepIntoSelectionTests for gdb <= 7.3 When a breakpoint is set directly at the start of a function, and you step into that function, gdb <= 7.3 will generate a "stopped" event with two reason fields. The first to indicate that the step range ended and the other to indicate that a breakpoint was hit. While this is not really correct from gdb to include the same field twice in a single event, the implementation of MIRunControlEventProcessor_7_0 will generate two distinct MIStoppedEvent events. This confuses the step-into-selection mechanism, who will issue two finish/step-return instead of one. For all gdbs, we will have a test where the breakpoint is a not at the function entry. Then, for gdb > 7.3, we will have the same test but with the breakpoint at the function entry, to test that particular case. This case is known to be broken with gdb <= 7.3 (rather old) and will stay that way unless somebody feels like fixing it. So, for both: - atDoubleMethodStopAtBreakpoint - atDoubleMethodSkipBreakpoint I extracted the code in a common function which takes in parameter the line to set the breakpoint at. Change-Id: I2ae4bc527afe0ab195e9b066279ed92f74d652f3 Signed-off-by: Simon Marchi Reviewed-on: https://git.eclipse.org/r/38717 Tested-by: Hudson CI Reviewed-by: Marc Khouzam Tested-by: Marc Khouzam --- .../dsf/gdb/tests/StepIntoSelectionTest.java | 104 ++++++++++++------ .../tests_7_4/StepIntoSelectionTest_7_4.java | 25 ++++- 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/StepIntoSelectionTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/StepIntoSelectionTest.java index 07cab21c032..75bb1f978d1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/StepIntoSelectionTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/StepIntoSelectionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Ericsson and others. + * Copyright (c) 2013, 2014 Ericsson 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 @@ -7,6 +7,7 @@ * * Contributors: * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) + * Simon Marchi (Ericsson) - Fix atDoubleMethod* tests for older gdb (<= 7.3) *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.tests; @@ -36,6 +37,7 @@ 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.framework.SyncUtil; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -427,51 +429,87 @@ public class StepIntoSelectionTest extends BaseTestCase { validateLocation(suspendedEvent, targetFunction.getElementName(), SRC_FILE, FOO_LINE, originalDepth + 1); } - + + private void atDoubleMethodStopAtBreakpointCommon(int foo_line) throws Throwable { + MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("doubleMethodTest"); + int originalDepth = SyncUtil.getStackDepth(stoppedEvent.getDMContext()); + + // Set a breakpoint inside foo, which will hit before our + // StepInto is finished + SyncUtil.addBreakpoint(Integer.toString(foo_line)); + + FunctionDeclaration targetFunction = funcBar; + int line = stoppedEvent.getFrame().getLine() + 1; // The method to stepInto is one line below the start of the method + // StepInto the method + ISuspendedDMEvent suspendedEvent = triggerStepIntoSelection(stoppedEvent.getDMContext(), SRC_FILE, + line, targetFunction, false); // Set not to skip breakpoints, but it should have no effect + + validateLocation(suspendedEvent, targetFunction.getElementName(), SRC_FILE, BAR_LINE, originalDepth + 1); + } + /** * This test verifies that we will not stop at a breakpoint if it is in the middle * of the step-in operations when the run-to-line skip breakpoint option is not selected. + * + * It is only enabled for gdb > 7.3. gdb <= 7.3 generates a stopped event with two + * reasons, resulting in two MIStoppedEvent in the step-into-selection machinery. Later + * gdbs generate a stopped event with only one reason, as they should. + */ + @Ignore + @Test + public void atDoubleMethodStopAtBreakpointFunctionEntry() throws Throwable { + atDoubleMethodStopAtBreakpointCommon(FOO_LINE); + } + + /** + * This test is just like atDoubleMethodStopAtBreakpointFunctionEntry, but avoids placing + * the breakpoint at the beginning of foo(). */ @Test public void atDoubleMethodStopAtBreakpoint() throws Throwable { - MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("doubleMethodTest"); - int originalDepth = SyncUtil.getStackDepth(stoppedEvent.getDMContext()); - - // Set a breakpoint inside foo, which will hit before our - // StepInto is finished - SyncUtil.addBreakpoint(Integer.toString(FOO_LINE)); - - FunctionDeclaration targetFunction = funcBar; - int line = stoppedEvent.getFrame().getLine() + 1; // The method to stepInto is one line below the start of the method - // StepInto the method - ISuspendedDMEvent suspendedEvent = triggerStepIntoSelection(stoppedEvent.getDMContext(), SRC_FILE, - line, targetFunction, false); // Set not to skip breakpoints, but it should have no effect - - validateLocation(suspendedEvent, targetFunction.getElementName(), SRC_FILE, BAR_LINE, originalDepth + 1); + atDoubleMethodStopAtBreakpointCommon(FOO_LINE + 1); } - + + private void atDoubleMethodSkipBreakpointCommon(int foo_line) throws Throwable { + MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("doubleMethodTest"); + int originalDepth = SyncUtil.getStackDepth(stoppedEvent.getDMContext()); + + // Set a breakpoint inside foo, which will hit before our + // StepInto is finished + SyncUtil.addBreakpoint(Integer.toString(foo_line)); + + FunctionDeclaration targetFunction = funcBar; + int line = stoppedEvent.getFrame().getLine() + 1; // The method to stepInto is one line below the start of the method + // StepInto the method + ISuspendedDMEvent suspendedEvent = triggerStepIntoSelection(stoppedEvent.getDMContext(), SRC_FILE, + line, targetFunction, true); // Set skip breakpoints, which should have non impact + + validateLocation(suspendedEvent, targetFunction.getElementName(), SRC_FILE, BAR_LINE, originalDepth + 1); + } + /** * This test verifies that we will not stop at a breakpoint if it is in the middle - * of the step-in operations even if the run-to-line skip breakpoint option is selected. + * of the step-in operations even if the run-to-line skip breakpoint option is selected. + * + * It is only enabled for gdb > 7.3. gdb <= 7.3 generates a stopped event with two + * reasons, resulting in two MIStoppedEvent in the step-into-selection machinery. Later + * gdbs generate a stopped event with only one reason, as they should. + */ + @Test + @Ignore + public void atDoubleMethodSkipBreakpointFunctionEntry() throws Throwable { + atDoubleMethodSkipBreakpointCommon(FOO_LINE); + } + + /** + * This test is just like atDoubleMethodSkipBreakpointFunctionEntry, but avoids placing + * the breakpoint at the beginning of foo(). */ @Test public void atDoubleMethodSkipBreakpoint() throws Throwable { - MIStoppedEvent stoppedEvent = SyncUtil.runToLocation("doubleMethodTest"); - int originalDepth = SyncUtil.getStackDepth(stoppedEvent.getDMContext()); - - // Set a breakpoint inside foo, which will hit before our - // StepInto is finished - SyncUtil.addBreakpoint(Integer.toString(FOO_LINE)); - - FunctionDeclaration targetFunction = funcBar; - int line = stoppedEvent.getFrame().getLine() + 1; // The method to stepInto is one line below the start of the method - // StepInto the method - ISuspendedDMEvent suspendedEvent = triggerStepIntoSelection(stoppedEvent.getDMContext(), SRC_FILE, - line, targetFunction, true); // Set skip breakpoints, which should have non impact - - validateLocation(suspendedEvent, targetFunction.getElementName(), SRC_FILE, BAR_LINE, originalDepth + 1); + atDoubleMethodSkipBreakpointCommon(FOO_LINE + 1); } - + /** * This test verifies that if we have two methods with the same name on the same line, * we properly choose the method with the correct number of arguments based on the diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/StepIntoSelectionTest_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/StepIntoSelectionTest_7_4.java index 388c4688eed..6cd4cc98b51 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/StepIntoSelectionTest_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/StepIntoSelectionTest_7_4.java @@ -7,6 +7,7 @@ * * Contributors: * Marc Khouzam (Ericsson) - Support for Step into selection (bug 244865) + * Simon Marchi (Ericsson) - Fix atDoubleMethod* tests for older gdb (<= 7.3) *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4; @@ -14,12 +15,30 @@ import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3.StepIntoSelectionTest_7_3; import org.junit.runner.RunWith; - +import org.junit.Test; @RunWith(BackgroundRunner.class) public class StepIntoSelectionTest_7_4 extends StepIntoSelectionTest_7_3 { - @Override + @Override protected void setGdbVersion() { - setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4); + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4); + } + + /** + * Enable test for gdb >= 7.4. + */ + @Override + @Test + public void atDoubleMethodStopAtBreakpointFunctionEntry() throws Throwable { + super.atDoubleMethodStopAtBreakpointFunctionEntry(); + } + + /** + * Enable test for gdb >= 7.4. + */ + @Override + @Test + public void atDoubleMethodSkipBreakpointFunctionEntry() throws Throwable { + super.atDoubleMethodSkipBreakpointFunctionEntry(); } }