diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index 0bc2fc6befc..6f7ed6045eb 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -24,6 +24,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.ISourceLookup; import org.eclipse.cdt.dsf.debug.service.IStack; import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; +import org.eclipse.cdt.dsf.gdb.service.command.CommandFactory_6_8; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0; import org.eclipse.cdt.dsf.mi.service.CSourceLookup; @@ -42,6 +43,7 @@ import org.eclipse.debug.core.ILaunchConfiguration; public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { + private static final String GDB_6_8_VERSION = "6.8"; //$NON-NLS-1$ // This should eventually be "7.0" once GDB 7.0 is released private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$ private static final String GDB_7_1_VERSION = "7.1"; //$NON-NLS-1$ @@ -99,7 +101,10 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) { if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) { - return new GDBControl_7_0(session, config, new CommandFactory()); + return new GDBControl_7_0(session, config, new CommandFactory_6_8()); + } + if (GDB_6_8_VERSION.compareTo(fVersion) <= 0) { + return new GDBControl(session, config, new CommandFactory_6_8()); } return new GDBControl(session, config, new CommandFactory()); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CommandFactory_6_8.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CommandFactory_6_8.java new file mode 100644 index 00000000000..e3e04368975 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CommandFactory_6_8.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2010 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.service.command; + +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; +import org.eclipse.cdt.dsf.debug.service.command.ICommand; +import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; +import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; + +/** + * A command factory for commands that should only be used starting with GDB 6.8 + * @since 4.0 */ +public class CommandFactory_6_8 extends CommandFactory { + + @Override + public ICommand createMIBreakInsert(IBreakpointsTargetDMContext ctx, String func) { + return new MIBreakInsert(ctx, func, true); + } + + @Override + public ICommand createMIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, + boolean isHardware, String condition, int ignoreCount, String line, int tid) { + return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, line, tid, true); + } + + @Override + public ICommand createMIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, + boolean isHardware, String condition, int ignoreCount, String location, int tid, boolean disabled, boolean isTracepoint) { + return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, location, tid, disabled, isTracepoint, true); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointDMData.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointDMData.java index 4b91825cda0..afe3b74f9fa 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointDMData.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointDMData.java @@ -353,4 +353,10 @@ public class MIBreakpointDMData implements IBreakpointDMData { return fBreakpoint.isAccessWatchpoint(); } + /** + * @since 4.0 + */ + public boolean isPending() { + return fBreakpoint.isPending(); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java index 392f00771b7..e5241f20a97 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java @@ -44,6 +44,7 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpoints; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension; import org.eclipse.cdt.dsf.debug.service.IRunControl; @@ -588,12 +589,27 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo // Remove breakpoint problem marker (if any) removeBreakpointProblemMarker(breakpoint); - // Finally, update the platform breakpoint - try { - breakpoint.incrementInstallCount(); - } catch (CoreException e) { - } - installRM.done(); + // Check for a pending breakpoint before showing that it was properly installed + fBreakpoints.getBreakpointDMData(targetBP, new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + boolean pending = false; + if (isSuccess()) { + IBreakpointDMData data = getData(); + if (data instanceof MIBreakpointDMData) { + pending = ((MIBreakpointDMData)data).isPending(); + } + } + // Finally, update the platform breakpoint to show it was installed, unless we have a pending breakpoint + if (!pending) { + try { + breakpoint.incrementInstallCount(); + } catch (CoreException e) { + } + } + installRM.done(); + } + }); } @Override @@ -712,7 +728,7 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo // Remove completion monitor // Upon completion, update the mappings - CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) { + final CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) { @Override protected void handleSuccess() { // Update the mappings @@ -738,18 +754,44 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo Vector list = breakpointIDs.get(breakpoint); int count = 0; if (list != null) { - for (IBreakpointDMContext bp : list) { - fBreakpoints.removeBreakpoint(bp, removeRM); - try { - breakpoint.decrementInstallCount(); - } catch (CoreException e) { - } + for (final IBreakpointDMContext bp : list) { + decrementInstallCount(bp, breakpoint, new RequestMonitor(getExecutor(), removeRM) { + @Override + protected void handleCompleted() { + fBreakpoints.removeBreakpoint(bp, removeRM); + } + }); } count = list.size(); } removeRM.setDoneCount(count); } + + private void decrementInstallCount(IBreakpointDMContext targetDmc, final ICBreakpoint breakpoint, final RequestMonitor rm) { + fBreakpoints.getBreakpointDMData(targetDmc, new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleCompleted() { + boolean pending = false; + if (isSuccess()) { + IBreakpointDMData data = getData(); + if (data instanceof MIBreakpointDMData) { + pending = ((MIBreakpointDMData)data).isPending(); + } + } + // Finally, update the platform breakpoint to show it was un-installed. + // But we don't do this for pending breakpoints since they were + // not marked as installed. + if (!pending) { + try { + breakpoint.decrementInstallCount(); + } catch (CoreException e) { + } + } + rm.done(); + } + }); + } //------------------------------------------------------------------------- // modifyBreakpoint //------------------------------------------------------------------------- @@ -911,12 +953,14 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo // Get the list of new back-end breakpoints contexts newTargetBPs.addAll(getData()); threadsIDs.put(breakpoint, newThreads); - for (IBreakpointDMContext ref : oldTargetBPs) { - fBreakpoints.removeBreakpoint(ref, removeRM); - try { - breakpoint.decrementInstallCount(); // A tad early but it should work... - } catch (CoreException e) { - } + for (final IBreakpointDMContext ref : oldTargetBPs) { + decrementInstallCount(ref, breakpoint, // A tad early but it should work... + new RequestMonitor(getExecutor(), removeRM) { + @Override + protected void handleCompleted() { + fBreakpoints.removeBreakpoint(ref, removeRM); + } + }); } removeRM.setDoneCount(oldTargetBPs.size()); } @@ -991,11 +1035,28 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo protected void handleSuccess() { // Add the new back-end breakpoint context to the list breakpointList.add(getData()); - try { - breakpoint.incrementInstallCount(); - } catch (CoreException e) { - } - installRM.done(); + + // Check for a pending breakpoint before showing that it was properly installed + fBreakpoints.getBreakpointDMData(getData(), new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + boolean pending = false; + if (isSuccess()) { + IBreakpointDMData data = getData(); + if (data instanceof MIBreakpointDMData) { + pending = ((MIBreakpointDMData)data).isPending(); + } + } + // Finally, update the platform breakpoint to show it was installed, unless we have a pending breakpoint + if (!pending) { + try { + breakpoint.incrementInstallCount(); + } catch (CoreException e) { + } + } + installRM.done(); + } + }); } @Override @@ -1341,8 +1402,8 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo Map> breakpoints = fBreakpointIDs.get(ctx); for (ICBreakpoint breakpoint : breakpoints.keySet()) { Vector targetBps = breakpoints.get(breakpoint); - for (int i=0; i createMIBreakInsert(IBreakpointsTargetDMContext ctx, String func) { - return new MIBreakInsert(ctx, func); + return new MIBreakInsert(ctx, func, false); } public ICommand createMIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, boolean isHardware, String condition, int ignoreCount, String line, int tid) { - return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, line, tid); + return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, line, tid, false); } public ICommand createMIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, boolean isHardware, String condition, int ignoreCount, String location, int tid, boolean disabled, boolean isTracepoint) { - return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, location, tid, disabled, isTracepoint); + return new MIBreakInsert(ctx, isTemporary, isHardware, condition, ignoreCount, location, tid, disabled, isTracepoint, false); } public ICommand createMIBreakList(IBreakpointsTargetDMContext ctx) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java index 180fee3506b..49a22d77c62 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIBreakInsert.java @@ -64,23 +64,26 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; */ public class MIBreakInsert extends MICommand { - public MIBreakInsert(IBreakpointsTargetDMContext ctx, String func) { - this(ctx, false, false, null, 0, func, 0); + /** @since 4.0 */ + public MIBreakInsert(IBreakpointsTargetDMContext ctx, String func, boolean allowPending) { + this(ctx, false, false, null, 0, func, 0, allowPending); } - + + /** @since 4.0 */ public MIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, boolean isHardware, - String condition, int ignoreCount, String line, int tid) { - this(ctx, isTemporary, isHardware, condition, ignoreCount, line, tid, false, false); + String condition, int ignoreCount, String line, int tid, boolean allowPending) { + this(ctx, isTemporary, isHardware, condition, ignoreCount, line, tid, false, false, allowPending); } /** * This constructor allows to specify if the breakpoint should actually be * a tracepoint (this will only work starting with GDB 7.1) * It also includes if a breakpoint should be created disabled (starting GDB 7.0) - * @since 3.0 + * @since 4.0 */ public MIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, boolean isHardware, - String condition, int ignoreCount, String location, int tid, boolean disabled, boolean isTracepoint) { + String condition, int ignoreCount, String location, int tid, boolean disabled, boolean isTracepoint, + boolean allowPending) { super(ctx, "-break-insert"); //$NON-NLS-1$ // For a tracepoint, force certain parameters to what is allowed @@ -118,6 +121,10 @@ public class MIBreakInsert extends MICommand if (isTracepoint) { i++; } + if (allowPending) { + i ++; + } + String[] opts = new String[i]; // Fill in the optional parameters @@ -157,6 +164,10 @@ public class MIBreakInsert extends MICommand opts[i] = "-a"; //$NON-NLS-1$ i++; } + if (allowPending) { + opts[i] = "-f"; //$NON-NLS-1$ + i ++; + } if (opts.length > 0) { setOptions(opts); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIBreakpoint.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIBreakpoint.java index 9256378d246..1c15865d7ea 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIBreakpoint.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIBreakpoint.java @@ -49,7 +49,14 @@ import java.util.StringTokenizer; * bkpt={number="5",type="tracepoint",disp="keep",enabled="y",addr="0x0804846b",func="main",file="hello.c",line="4",thread="0",thread="0",times="0"} * bkpt={number="1",type="tracepoint",disp="keep",enabled="y",addr="0x0041bca0",func="main",file="hello.c",line="4",times="0",pass="4",original-location="hello.c:4"}, * bkpt={number="5",type="fast tracepoint",disp="keep",enabled="y",addr="0x0804852d",func="testTracepoints()",file="TracepointTestApp.cc",fullname="/local/src/TracepointTestApp.cc",line="84",times="0",original-location="TracepointTestApp.cc:84"} - * */ + * + * Pending breakpoint + * -break-insert -f NotLoadedLibrary.c:26 + * &"No source file named NotLoadedLibrary.c.\n" + * ^done,bkpt={number="9",type="breakpoint",disp="keep",enabled="y",addr="",pending="NotLoadedLibrary.c:26",times="0",original-location="NotLoadedLibrary.c:26"} + * + * Note that any breakpoint that fails to install will be marked as pending when the -f option is used. + */ public class MIBreakpoint { int number = -1; @@ -87,6 +94,14 @@ public class MIBreakpoint { /** See {@link #getCatchpointType()} */ private String catchpointType; + /** + * A pending breakpoint is a breakpoint that did not install properly, + * but that will be kept in the hopes that it installs later, triggered by + * the loading of a library. + * This concept is only supported starting with GDB 6.8 + */ + private boolean pending; + public MIBreakpoint() { } @@ -115,6 +130,7 @@ public class MIBreakpoint { isTpt = other.isTpt; isCatchpoint = other.isCatchpoint; catchpointType = other.catchpointType; + pending = other.pending; } public MIBreakpoint(MITuple tuple) { @@ -382,6 +398,15 @@ public class MIBreakpoint { commands = cmds; } + /** + * Returns wether this breakpoint is pending + * + * @since 4.0 + */ + public boolean isPending() { + return pending; + } + // Parse the result string void parse(MITuple tuple) { MIResult[] results = tuple.getMIResults(); @@ -468,6 +493,9 @@ public class MIBreakpoint { } } else if (var.equals("cond")) { //$NON-NLS-1$ cond = str; + } else if (var.equals("pending")) { //$NON-NLS-1$ + // Only supported starting with GDB 6.8 + pending = true; } } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/TestMIBreakInsertCommand.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/TestMIBreakInsertCommand.java index 6d76f83e5d3..395b24b10a2 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/TestMIBreakInsertCommand.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/TestMIBreakInsertCommand.java @@ -28,7 +28,7 @@ public class TestMIBreakInsertCommand { @Test public void pathShouldNotContainDoubleBackSlashes() { MIBreakInsert target = new MIBreakInsert(new TestContext(), false, - false, null, 1, "c:\\test\\this\\path:14", 4); + false, null, 1, "c:\\test\\this\\path:14", 4, false); assertEquals("Wrong syntax for command", "-break-insert -i 1 -p 4 c:\\test\\this\\path:14\n", target @@ -38,7 +38,7 @@ public class TestMIBreakInsertCommand { @Test public void pathWithSlashesShouldNotBeSubstituted() { MIBreakInsert target = new MIBreakInsert(new TestContext(), false, - false, null, 1, "/test/this/path:14", 4); + false, null, 1, "/test/this/path:14", 4, false); assertEquals("Wrong syntax for command", "-break-insert -i 1 -p 4 /test/this/path:14\n", target diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java index 7329bc542be..7cbe7646736 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIBreakpointsTest.java @@ -88,58 +88,57 @@ public class MIBreakpointsTest extends BaseTestCase { public static final String SOURCE_FILE = "BreakpointTestApp.cc"; //$NON-NLS-1$ // Asynchronous Completion - private final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor(); + protected final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor(); // Services references - private DsfSession fSession; - private IBreakpointsTargetDMContext fBreakpointsDmc; - private DsfServicesTracker fServicesTracker; - private MIRunControl fRunControl; - private IBreakpoints fBreakpointService; + protected DsfSession fSession; + protected IBreakpointsTargetDMContext fBreakpointsDmc; + protected DsfServicesTracker fServicesTracker; + protected MIRunControl fRunControl; + protected IBreakpoints fBreakpointService; // Event Management - private static Boolean lock = true; - enum Events { BP_ADDED, BP_UPDATED, BP_REMOVED, BP_HIT, WP_HIT, WP_OOS } - final int BP_ADDED = Events.BP_ADDED.ordinal(); - final int BP_UPDATED = Events.BP_UPDATED.ordinal(); - final int BP_REMOVED = Events.BP_REMOVED.ordinal(); - final int BP_HIT = Events.BP_HIT.ordinal(); - final int WP_HIT = Events.WP_HIT.ordinal(); - final int WP_OOS = Events.WP_OOS.ordinal(); - private int[] fBreakpointEvents = new int[Events.values().length]; - private int fBreakpointEventCount; - private int fBreakpointRef; + protected static Boolean lock = true; + protected enum Events { BP_ADDED, BP_UPDATED, BP_REMOVED, BP_HIT, WP_HIT, WP_OOS } + protected final int BP_ADDED = Events.BP_ADDED.ordinal(); + protected final int BP_UPDATED = Events.BP_UPDATED.ordinal(); + protected final int BP_REMOVED = Events.BP_REMOVED.ordinal(); + protected final int BP_HIT = Events.BP_HIT.ordinal(); + protected final int WP_HIT = Events.WP_HIT.ordinal(); + protected final int WP_OOS = Events.WP_OOS.ordinal(); + protected int[] fBreakpointEvents = new int[Events.values().length]; + protected int fBreakpointEventCount; + protected int fBreakpointRef; // Some useful constants - final String BREAKPOINT_TYPE_TAG = MIBreakpoints.BREAKPOINT_TYPE; - final String BREAKPOINT_TAG = MIBreakpoints.BREAKPOINT; - final String WATCHPOINT_TAG = MIBreakpoints.WATCHPOINT; + protected final String BREAKPOINT_TYPE_TAG = MIBreakpoints.BREAKPOINT_TYPE; + protected final String BREAKPOINT_TAG = MIBreakpoints.BREAKPOINT; + protected final String WATCHPOINT_TAG = MIBreakpoints.WATCHPOINT; - final String FILE_NAME_TAG = MIBreakpoints.FILE_NAME; - final String LINE_NUMBER_TAG = MIBreakpoints.LINE_NUMBER; - final String FUNCTION_TAG = MIBreakpoints.FUNCTION; - final String ADDRESS_TAG = MIBreakpoints.ADDRESS; - final String CONDITION_TAG = MIBreakpoints.CONDITION; - final String IGNORE_COUNT_TAG = MIBreakpoints.IGNORE_COUNT; - final String IS_ENABLED_TAG = MIBreakpoints.IS_ENABLED; - final String THREAD_ID_TAG = MIBreakpointDMData.THREAD_ID; - final String NUMBER_TAG = MIBreakpointDMData.NUMBER; + protected final String FILE_NAME_TAG = MIBreakpoints.FILE_NAME; + protected final String LINE_NUMBER_TAG = MIBreakpoints.LINE_NUMBER; + protected final String FUNCTION_TAG = MIBreakpoints.FUNCTION; + protected final String ADDRESS_TAG = MIBreakpoints.ADDRESS; + protected final String CONDITION_TAG = MIBreakpoints.CONDITION; + protected final String IGNORE_COUNT_TAG = MIBreakpoints.IGNORE_COUNT; + protected final String IS_ENABLED_TAG = MIBreakpoints.IS_ENABLED; + protected final String THREAD_ID_TAG = MIBreakpointDMData.THREAD_ID; + protected final String NUMBER_TAG = MIBreakpointDMData.NUMBER; - final String EXPRESSION_TAG = MIBreakpoints.EXPRESSION; - final String READ_TAG = MIBreakpoints.READ; - final String WRITE_TAG = MIBreakpoints.WRITE; + protected final String EXPRESSION_TAG = MIBreakpoints.EXPRESSION; + protected final String READ_TAG = MIBreakpoints.READ; + protected final String WRITE_TAG = MIBreakpoints.WRITE; // Target application 'special' locations - private final int LINE_NUMBER_1 = 20; - private final int LINE_NUMBER_2 = 21; - @SuppressWarnings("unused") - private final int LINE_NUMBER_3 = 27; - private final int LINE_NUMBER_4 = 36; - private final int LINE_NUMBER_5 = 49; - private final int LINE_NUMBER_6 = 50; - private final String FUNCTION = "zeroBlocks"; - private final String SIGNED_FUNCTION = "zeroBlocks(int)"; - private final String NO_CONDITION = ""; + protected final int LINE_NUMBER_1 = 20; + protected final int LINE_NUMBER_2 = 21; + protected final int LINE_NUMBER_3 = 27; + protected final int LINE_NUMBER_4 = 36; + protected final int LINE_NUMBER_5 = 49; + protected final int LINE_NUMBER_6 = 50; + protected final String FUNCTION = "zeroBlocks"; + protected final String SIGNED_FUNCTION = "zeroBlocks(int)"; + protected final String NO_CONDITION = ""; // NOTE: The back-end can reformat the condition. In order for the // comparison to work, better specify the condition as the back-end @@ -157,10 +156,10 @@ public class MIBreakpointsTest extends BaseTestCase { private final String EXPRESSION_3 = "a"; // Error messages - final String UNKNOWN_EXECUTION_CONTEXT = "Unknown execution context"; - final String INVALID_BREAKPOINT_LOCATION = "Invalid breakpoint location"; - final String BREAKPOINT_INSERTION_FAILURE = "Breakpoint insertion failure"; - final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; + protected final String UNKNOWN_EXECUTION_CONTEXT = "Unknown execution context"; + protected final String INVALID_BREAKPOINT_LOCATION = "Invalid breakpoint location"; + protected final String BREAKPOINT_INSERTION_FAILURE = "Breakpoint insertion failure"; + protected final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; // ======================================================================== // Housekeeping stuff @@ -292,7 +291,7 @@ public class MIBreakpointsTest extends BaseTestCase { } // Clears the counters - private void clearEventCounters() { + protected void clearEventCounters() { synchronized (lock) { for (int i = 0; i < fBreakpointEvents.length; i++) { fBreakpointEvents[i] = 0; @@ -302,7 +301,7 @@ public class MIBreakpointsTest extends BaseTestCase { } // Get the breakpoint hit count - private int getBreakpointEventCount(int event) { + protected int getBreakpointEventCount(int event) { int count = 0; synchronized (lock) { count = fBreakpointEvents[event]; @@ -340,7 +339,7 @@ public class MIBreakpointsTest extends BaseTestCase { /** * Simplified variant that just waits up to two seconds */ - private void waitForBreakpointEvent(int count) throws Exception { + protected void waitForBreakpointEvent(int count) throws Exception { waitForBreakpointEvent(count, TestsPlugin.massageTimeout(2000)); } @@ -413,7 +412,7 @@ public class MIBreakpointsTest extends BaseTestCase { * @param context the execution context * ------------------------------------------------------------------------ */ - private IBreakpointDMContext[] getBreakpoints(final IBreakpointsTargetDMContext context) throws InterruptedException + protected IBreakpointDMContext[] getBreakpoints(final IBreakpointsTargetDMContext context) throws InterruptedException { // Clear the completion waiter fWait.waitReset(); @@ -455,7 +454,7 @@ public class MIBreakpointsTest extends BaseTestCase { * @param breakpoint the breakpoint to retrieve * ------------------------------------------------------------------------ */ - private IBreakpointDMData getBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException + protected IBreakpointDMData getBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException { // Clear the completion waiter fWait.waitReset(); @@ -534,7 +533,7 @@ public class MIBreakpointsTest extends BaseTestCase { * @param attributes the breakpoint attributes * ------------------------------------------------------------------------ */ - private IBreakpointDMContext insertBreakpoint(final IBreakpointsTargetDMContext context, + protected IBreakpointDMContext insertBreakpoint(final IBreakpointsTargetDMContext context, final Map attributes) throws InterruptedException { // Clear the completion waiter @@ -821,6 +820,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getIgnoreCount() == 0); assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)", breakpoint1.isEnabled()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -869,6 +870,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getIgnoreCount() == 0); assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)", breakpoint1.isEnabled()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -918,6 +921,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getIgnoreCount() == 0); assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)", !breakpoint1.isEnabled()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -964,6 +969,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -1011,6 +1018,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getCondition().equals(CONDITION_1)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -1058,6 +1067,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint1.getIgnoreCount() == IGNORE_COUNT_1); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -1104,6 +1115,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Create a function breakpoint breakpoint = new HashMap(); @@ -1133,6 +1146,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint2.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint2.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint2.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -1190,6 +1205,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint1.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); // Create a second line breakpoint, same attributes... ref = insertBreakpoint(fBreakpointsDmc, breakpoint); @@ -1213,6 +1230,8 @@ public class MIBreakpointsTest extends BaseTestCase { breakpoint2.getCondition().equals(NO_CONDITION)); assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", breakpoint2.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint2.isPending()); // Ensure the BreakpointService holds only the right breakpoints IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); @@ -1276,6 +1295,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); assertTrue("Did not stop because of breakpoint, but stopped because of: " + @@ -1334,6 +1355,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); assertTrue("Did not stop because of breakpoint, but stopped because of: " + @@ -1382,6 +1405,9 @@ public class MIBreakpointsTest extends BaseTestCase { watchpoint1.isWriteWatchpoint()); assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)", !watchpoint1.isAccessWatchpoint()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); + // Ensure the BreakpointService holds only the right watchpoints IBreakpointDMContext[] watchpoints = getBreakpoints(fBreakpointsDmc); @@ -1428,6 +1454,8 @@ public class MIBreakpointsTest extends BaseTestCase { !watchpoint1.isWriteWatchpoint()); assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)", !watchpoint1.isAccessWatchpoint()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); // Ensure the BreakpointService holds only the right watchpoints IBreakpointDMContext[] watchpoints = getBreakpoints(fBreakpointsDmc); @@ -1475,6 +1503,8 @@ public class MIBreakpointsTest extends BaseTestCase { !watchpoint1.isWriteWatchpoint()); assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)", watchpoint1.isAccessWatchpoint()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); // Ensure the BreakpointService holds only the right watchpoints IBreakpointDMContext[] watchpoints = getBreakpoints(fBreakpointsDmc); @@ -1538,6 +1568,8 @@ public class MIBreakpointsTest extends BaseTestCase { watchpoint1.isWriteWatchpoint()); assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)", !watchpoint1.isAccessWatchpoint()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); // Ensure the BreakpointService holds only the right watchpoints IBreakpointDMContext[] watchpoints = getBreakpoints(fBreakpointsDmc); @@ -2792,6 +2824,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); } @@ -2832,6 +2866,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); } @@ -2876,6 +2912,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -2937,6 +2975,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -2985,6 +3025,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3046,6 +3088,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1); assertTrue("BreakpointService problem: breakpoint mismatch", fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !breakpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3092,6 +3136,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3138,6 +3184,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3185,6 +3233,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3247,6 +3297,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3310,6 +3362,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Verify that the condition is met @@ -3362,6 +3416,8 @@ public class MIBreakpointsTest extends BaseTestCase { + getBreakpointEventCount(WP_OOS), getBreakpointEventCount(WP_OOS) == 1); assertTrue("BreakpointService problem: watchpoint mismatch", fBreakpointRef == watchpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (pending)", + !watchpoint1.isPending()); clearEventCounters(); // Ensure the watchpoint is gone diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/MIBreakpointsTest_6_8.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/MIBreakpointsTest_6_8.java index fa57bdb2192..3ecf5474c10 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/MIBreakpointsTest_6_8.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/MIBreakpointsTest_6_8.java @@ -10,11 +10,20 @@ *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_8; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; +import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData; +import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext; import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil; import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; import org.eclipse.cdt.tests.dsf.gdb.tests.MIBreakpointsTest; +import org.eclipse.core.runtime.Platform; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,9 +34,159 @@ public class MIBreakpointsTest_6_8 extends MIBreakpointsTest { public static void beforeClassMethod_6_8() { setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_6_8); } + @Override - @Ignore("This GDB 6.8 only has a bug which ignores watchpoint conditions") @Test public void breakpointHit_watchpointUpdateCondition() throws Throwable { + // GDB 6.8 has a bug that ignores watchpoint conditions,which makes this + // test fail. We therefore ignore this test for GDB 6.8 only, but run it + // for all other versions + if (getClass().equals(MIBreakpointsTest_6_8.class) == false) { + super.breakpointHit_watchpointUpdateCondition(); + } + } + + /** + * Starting with GDB 6.8, we request failed breakpoints to be pending in + * GDB. So we no longer get an installation error from GDB. + */ + @Override + @Test + public void insertBreakpoint_InvalidFileName() throws Throwable { + + // Create an invalid line breakpoint + Map breakpoint = new HashMap(); + breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG); + breakpoint.put(FILE_NAME_TAG, SOURCE_FILE + "_bad"); + breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1); + + // Perform the test, which we still expect to succeed + // giving us a pending breakpoint + IBreakpointDMContext ref = insertBreakpoint(fBreakpointsDmc, breakpoint); + assertTrue(fWait.getMessage(), fWait.isOK()); + + // Ensure that right BreakpointEvents were received + waitForBreakpointEvent(1); + assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received " + + fBreakpointEventCount, fBreakpointEventCount == 1); + assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received " + + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1); + clearEventCounters(); + + // Ensure that the breakpoint was correctly installed + MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)", + breakpoint1.getFileName().equals("")); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)", + breakpoint1.getLineNumber() == -1); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)", + breakpoint1.getCondition().equals(NO_CONDITION)); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", + breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)", + breakpoint1.isEnabled()); + assertTrue("BreakpointService problem: breakpoint mismatch (not pending)", + breakpoint1.isPending()); + + // Ensure the BreakpointService holds only the right breakpoints + IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); + assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received " + + breakpoints.length, breakpoints.length == 1); + MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]); + assertTrue("BreakpointService problem: breakpoint mismatch", + breakpoint1.equals(breakpoint2)); + } + + /** + * Starting with GDB 6.8, we request failed breakpoints to be pending in + * GDB. So we no longer get an installation error from GDB. + */ + @Override + @Test + public void insertBreakpoint_InvalidFunctionName() throws Throwable { + + // Create an invalid function breakpoint + Map breakpoint = new HashMap(); + breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG); + breakpoint.put(FILE_NAME_TAG, SOURCE_FILE); + breakpoint.put(FUNCTION_TAG, "invalid-function-name"); + + // Perform the test, which we still expect to succeed + // giving us a pending breakpoint + IBreakpointDMContext ref = insertBreakpoint(fBreakpointsDmc, breakpoint); + assertTrue(fWait.getMessage(), fWait.isOK()); + + // Ensure that right BreakpointEvents were received + waitForBreakpointEvent(1); + assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received " + + fBreakpointEventCount, fBreakpointEventCount == 1); + assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received " + + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1); + clearEventCounters(); + + // Ensure that the breakpoint was correctly installed + MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)", + breakpoint1.getFileName().equals("")); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong function)", + breakpoint1.getFunctionName().equals("")); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)", + breakpoint1.getCondition().equals(NO_CONDITION)); + assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)", + breakpoint1.getIgnoreCount() == 0); + assertTrue("BreakpointService problem: breakpoint mismatch (not pending)", + breakpoint1.isPending()); + + // Ensure the BreakpointService holds only the right breakpoints + IBreakpointDMContext[] breakpoints = getBreakpoints(fBreakpointsDmc); + assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received " + + breakpoints.length, breakpoints.length == 1); + MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]); + assertTrue("BreakpointService problem: breakpoint mismatch", + breakpoint1.equals(breakpoint2)); + } + + /** + * Starting with GDB 6.8, we request failed breakpoints to be pending in + * GDB. So we no longer get an installation error from GDB. + */ + @Override + @Test + public void insertInvalidBreakpoint_WhileTargetRunning() throws Throwable { + // Interrupting the target on Windows is susceptible to an additional, + // unwanted suspension. That means that silently interrupting the target + // to set/modify/remove a breakpoint then resuming it can leave the + // target in a suspended state. Unfortunately, there is nothing + // practical CDT can do to address this issue except wait for the gdb + // folks to resolve it. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c27 + if (Platform.getOS().equals(Platform.OS_WIN32)) { + return; + } + + // Create an invalid line breakpoint + Map breakpoint = new HashMap(); + breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG); + breakpoint.put(FILE_NAME_TAG, "Bad file name"); + breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_5); + + // Run the program. It will make a two second sleep() call, during which time... + SyncUtil.resume(); + + // ...we install the breakpoint + MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fBreakpointsDmc, breakpoint); + assertTrue(fWait.getMessage(), fWait.isOK()); + + waitForBreakpointEvent(1); + // Ensure the correct BreakpointEvent was received + MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref); + assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received " + + fBreakpointEventCount, fBreakpointEventCount == 1); + assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT_HIT event(s), received " + + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 0); + assertTrue("BreakpointService problem: breakpoint mismatch", + fBreakpointRef == breakpoint1.getNumber()); + assertTrue("BreakpointService problem: breakpoint mismatch (not pending)", + breakpoint1.isPending()); + clearEventCounters(); } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/MIBreakpointsTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/MIBreakpointsTest_7_0.java index 3e2b1ba5e33..9229a89db5d 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/MIBreakpointsTest_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/MIBreakpointsTest_7_0.java @@ -12,12 +12,12 @@ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0; 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.MIBreakpointsTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_8.MIBreakpointsTest_6_8; import org.junit.BeforeClass; import org.junit.runner.RunWith; @RunWith(BackgroundRunner.class) -public class MIBreakpointsTest_7_0 extends MIBreakpointsTest { +public class MIBreakpointsTest_7_0 extends MIBreakpointsTest_6_8 { @BeforeClass public static void beforeClassMethod_7_0() { setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_0); diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/MIBreakpointsTest_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/MIBreakpointsTest_7_1.java index e0395e65b43..76b3867992b 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/MIBreakpointsTest_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/MIBreakpointsTest_7_1.java @@ -12,12 +12,12 @@ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1; 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.MIBreakpointsTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0.MIBreakpointsTest_7_0; import org.junit.BeforeClass; import org.junit.runner.RunWith; @RunWith(BackgroundRunner.class) -public class MIBreakpointsTest_7_1 extends MIBreakpointsTest { +public class MIBreakpointsTest_7_1 extends MIBreakpointsTest_7_0 { @BeforeClass public static void beforeClassMethod_7_1() { setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_1); diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/MIBreakpointsTest_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/MIBreakpointsTest_7_2.java index cf4867f976d..f1abd0464dc 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/MIBreakpointsTest_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/MIBreakpointsTest_7_2.java @@ -12,12 +12,12 @@ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2; 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.MIBreakpointsTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1.MIBreakpointsTest_7_1; import org.junit.BeforeClass; import org.junit.runner.RunWith; @RunWith(BackgroundRunner.class) -public class MIBreakpointsTest_7_2 extends MIBreakpointsTest { +public class MIBreakpointsTest_7_2 extends MIBreakpointsTest_7_1 { @BeforeClass public static void beforeClassMethod_7_2() { setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_2);