From 6abf9e1a4231252f06587bb0f2de002057e293ad Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Fri, 20 Apr 2012 14:59:43 -0400 Subject: [PATCH 01/14] Bug 317173: Cleanup warnings for DSF-GDB. --- core/org.eclipse.cdt.core/META-INF/MANIFEST.MF | 3 ++- debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF | 7 ++++++- debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF | 4 ++-- dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF | 4 ++-- dsf/org.eclipse.cdt.dsf.ui/META-INF/MANIFEST.MF | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 9f82f059e8e..908a38a6432 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -47,7 +47,8 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.managedbuilder.core, org.eclipse.cdt.make.core, org.eclipse.cdt.make.ui, - org.eclipse.cdt.codan.core.cxx", + org.eclipse.cdt.codan.core.cxx, + org.eclipse.cdt.dsf.gdb", org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true, org.eclipse.cdt.internal.core.dom;x-internal:=true, diff --git a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF index d62fbbc42b8..31e74c889b6 100644 --- a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF @@ -22,7 +22,12 @@ Export-Package: org.eclipse.cdt.debug.core, org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc,org.eclipse.cdt.dsf.gdb", org.eclipse.cdt.debug.internal.core.executables;x-internal:=true, org.eclipse.cdt.debug.internal.core.model;x-internal:=true, - org.eclipse.cdt.debug.internal.core.sourcelookup;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.debug.edc,org.eclipse.cdt.debug.gdbjtag.core" + org.eclipse.cdt.debug.internal.core.sourcelookup; + x-friends:="org.eclipse.cdt.dsf.ui, + org.eclipse.cdt.debug.edc, + org.eclipse.cdt.debug.gdbjtag.core, + org.eclipse.cdt.dsf.gdb, + org.eclipse.cdt.dsf" Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)", org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)", org.eclipse.cdt.core;bundle-version="[5.0.0,6.0.0)", diff --git a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF index 11eba71e802..e68437be26c 100644 --- a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF @@ -10,9 +10,9 @@ Export-Package: org.eclipse.cdt.debug.internal.ui;x-internal:x-friends:="org.eclipse.cdt.dsf.ui";x-friends:="org.eclipse.cdt.dsf.ui", org.eclipse.cdt.debug.internal.ui.actions;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.debug.ui.memory.memorybrowser", org.eclipse.cdt.debug.internal.ui.actions.breakpoints;x-internal:=true, - org.eclipse.cdt.debug.internal.ui.breakpoints;x-internal:=true, + org.eclipse.cdt.debug.internal.ui.breakpoints;x-friends:="org.eclipse.cdt.dsf.ui", org.eclipse.cdt.debug.internal.ui.commands;x-internal:=true, - org.eclipse.cdt.debug.internal.ui.dialogfields;x-internal:=true, + org.eclipse.cdt.debug.internal.ui.dialogfields;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.debug.internal.ui.dialogs;x-internal:=true, org.eclipse.cdt.debug.internal.ui.disassembly.commands;x-internal:=true, org.eclipse.cdt.debug.internal.ui.disassembly.dsf;x-friends:="org.eclipse.cdt.dsf.ui", diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF index 194a1f188b0..4e896ba4dc2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF @@ -20,10 +20,10 @@ Export-Package: org.eclipse.cdt.dsf.gdb, org.eclipse.cdt.dsf.gdb.actions, 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.commands;x-internal:=true, + 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.service.command.events;x-internal:=true, - org.eclipse.cdt.dsf.gdb.internal.tracepointactions;x-internal:=true, + org.eclipse.cdt.dsf.gdb.internal.tracepointactions;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.dsf.gdb.launching, org.eclipse.cdt.dsf.gdb.service, org.eclipse.cdt.dsf.gdb.service.command, diff --git a/dsf/org.eclipse.cdt.dsf.ui/META-INF/MANIFEST.MF b/dsf/org.eclipse.cdt.dsf.ui/META-INF/MANIFEST.MF index 0c22d13ecf0..e72b7850fed 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/META-INF/MANIFEST.MF +++ b/dsf/org.eclipse.cdt.dsf.ui/META-INF/MANIFEST.MF @@ -34,7 +34,7 @@ Export-Package: org.eclipse.cdt.dsf.debug.internal.ui;x-internal:=true, org.eclipse.cdt.dsf.debug.internal.ui.disassembly.util;x-internal:=true, org.eclipse.cdt.dsf.debug.internal.ui.preferences;x-internal:=true, org.eclipse.cdt.dsf.debug.internal.ui.viewmodel;x-internal:=true, - org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions;x-internal:=true, + org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport;x-internal:=true, org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.numberformat.detail;x-internal:=true, org.eclipse.cdt.dsf.debug.ui, From 3964dbeab6c33f5a79e46257dc14df43695ceed3 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Fri, 20 Apr 2012 16:11:04 -0400 Subject: [PATCH 02/14] Bug 373707: [tracepoints] Make use of the new 'collect /s' command Change-Id: I60689b73dd1f081fa3e3b53807e52800c9c03006 Reviewed-on: https://git.eclipse.org/r/5576 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../tracepointactions/CollectActionPage.java | 125 +++++++++++++++++- .../MessagesForTracepointActions.java | 6 +- .../ui/tracepointactions/messages.properties | 6 +- .../cdt/dsf/gdb/internal/GdbPlugin.java | 41 ++++++ .../tracepointactions/CollectAction.java | 122 +++++++++++++++-- .../tracepointactions/EvaluateAction.java | 16 ++- .../MessagesForTracepointActions.java | 6 +- .../WhileSteppingAction.java | 16 ++- .../tracepointactions/messages.properties | 7 +- .../GDBRemoteTracepointsTest_7_0.java | 56 ++++---- .../GDBRemoteTracepointsTest_7_4.java | 50 +++++++ 11 files changed, 383 insertions(+), 68 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/CollectActionPage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/CollectActionPage.java index 1f6201c7d01..10f72c60a1d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/CollectActionPage.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/CollectActionPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for collecting char pointers as strings (bug 373707) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepointactions; @@ -14,9 +15,16 @@ import org.eclipse.cdt.debug.core.breakpointactions.IBreakpointAction; import org.eclipse.cdt.debug.ui.breakpointactions.IBreakpointActionPage; import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.CollectAction; import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; @@ -26,7 +34,20 @@ import org.eclipse.swt.widgets.Text; */ public class CollectActionPage extends PlatformObject implements IBreakpointActionPage { + /** + * An exception to indicate that the user-specified string limit is invalid + */ + private class IllegalCollectStringLimitException extends Exception { + private static final long serialVersionUID = -2087722354642237691L; + public IllegalCollectStringLimitException(String message) { + super(message); + } + } + private Text fCollectString; + private Button fTreatCharPtrAsStrings; + private Text fTreatCharPtrAsStringsLimit; + private CollectAction fCollectAction; /** @@ -36,14 +57,73 @@ public class CollectActionPage extends PlatformObject implements IBreakpointActi Composite composite = new Composite(parent, style); composite.setLayout(new GridLayout(2, false)); + // The label asking for what to collect final Label collectLabel = new Label(composite, SWT.NONE); collectLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); collectLabel.setText(MessagesForTracepointActions.TracepointActions_Collect_Label); + // The user-specified string of what to collect fCollectString = new Text(composite, SWT.BORDER); fCollectString.setText(fCollectAction.getCollectString()); - fCollectString.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + fCollectString.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); + // An option to collect character pointers as strings + fTreatCharPtrAsStrings = new Button(composite, SWT.CHECK); + GridData gd = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1); + gd.verticalIndent = 15; + // Store the button width before we add the text as we only care about the checkbox width + int buttonWidth = fTreatCharPtrAsStrings.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; + fTreatCharPtrAsStrings.setText(MessagesForTracepointActions.TracepointActions_Collect_Strings_Label); + fTreatCharPtrAsStrings.setLayoutData(gd); + fTreatCharPtrAsStrings.setSelection(fCollectAction.getCharPtrAsStrings()); + fTreatCharPtrAsStrings.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + // Disable/enable the limit field + fTreatCharPtrAsStringsLimit.setEnabled(fTreatCharPtrAsStrings.getSelection()); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Disable/enable the limit field + fTreatCharPtrAsStringsLimit.setEnabled(fTreatCharPtrAsStrings.getSelection()); + } + }); + + // A label asking for an optional limit of bytes of collected strings + final Label limitLabel = new Label(composite, SWT.NONE); + gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); + gd.horizontalIndent = buttonWidth; + limitLabel.setLayoutData(gd); + limitLabel.setText(MessagesForTracepointActions.TracepointActions_Collect_Strings_Limit_Label); + + // A user-specified limit of bytes + fTreatCharPtrAsStringsLimit = new Text(composite, SWT.BORDER); + fTreatCharPtrAsStringsLimit.setText(getCharPtrAsStringLimit(fCollectAction.getCharPtrAsStringsLimit())); + + gd = new GridData(SWT.FILL, SWT.CENTER, false, false); + gd.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + fTreatCharPtrAsStringsLimit.setLayoutData(gd); + fTreatCharPtrAsStringsLimit.setEnabled(fTreatCharPtrAsStrings.getSelection()); + + final ControlDecoration decoration = new ControlDecoration(fTreatCharPtrAsStringsLimit, SWT.TOP | SWT.LEFT, composite ); + decoration.hide(); + fTreatCharPtrAsStringsLimit.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + try { + getCharPtrAsStringLimit(fTreatCharPtrAsStringsLimit.getText()); + decoration.hide(); + } catch (IllegalCollectStringLimitException exception) { + decoration.setImage( + FieldDecorationRegistry.getDefault().getFieldDecoration( + FieldDecorationRegistry.DEC_ERROR).getImage()); + decoration.setDescriptionText(exception.getMessage()); + decoration.show(); + } + } + }); + + return composite; } @@ -58,6 +138,14 @@ public class CollectActionPage extends PlatformObject implements IBreakpointActi @Override public void actionDialogOK() { fCollectAction.setCollectString(fCollectString.getText()); + fCollectAction.setCharPtrAsStrings(fTreatCharPtrAsStrings.getSelection()); + + try { + Integer limit = getCharPtrAsStringLimit(fTreatCharPtrAsStringsLimit.getText()); + fCollectAction.setCharPtrAsStringsLimit(limit); + } catch (IllegalCollectStringLimitException e) { + // ignore and keep old value + } } @Override @@ -66,4 +154,37 @@ public class CollectActionPage extends PlatformObject implements IBreakpointActi return createCollectActionComposite(composite, style); } + /** + * Convert the user-specified string into an integer. + * If the string is not valid, disable the limit by using null. + * @param limitStr The string provided by the user + * @return An non-negative integer limit, or null for no limit. + */ + private Integer getCharPtrAsStringLimit(String limitStr) throws IllegalCollectStringLimitException { + limitStr = limitStr.trim(); + Integer limit = null; + try { + limit = Integer.parseInt(limitStr); + if (limit < 0) { + throw new IllegalCollectStringLimitException(MessagesForTracepointActions.TracepointActions_Collect_Strings_Limit_Error); + } + } catch (NumberFormatException e) { + if (!limitStr.isEmpty()) { + // We only accept an empty string, which means no limit + throw new IllegalCollectStringLimitException(MessagesForTracepointActions.TracepointActions_Collect_Strings_Limit_Error); + } + } + return limit; + } + + /** + * Convert the integer limit into a string. + * If the string is not valid, disable the limit by using null. + * @param limit The integer limit to convert. Can be null for no limit. + * @return The limit as a string, where no limit or a negative limit is the empty string. + */ + private String getCharPtrAsStringLimit(Integer limit) { + if (limit == null || limit < 0) return ""; //$NON-NLS-1$ + return Integer.toString(limit); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/MessagesForTracepointActions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/MessagesForTracepointActions.java index 720a95260c1..03ecb9dec58 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/MessagesForTracepointActions.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/MessagesForTracepointActions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for collecting char pointers as strings (bug 373707) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepointactions; @@ -39,6 +40,9 @@ class MessagesForTracepointActions extends NLS { public static String TracepointActions_Collect_Label; public static String TracepointActions_Evaluate_Label; public static String TracepointActions_WhileStepping_Sub_Actions; + public static String TracepointActions_Collect_Strings_Label; + public static String TracepointActions_Collect_Strings_Limit_Label; + public static String TracepointActions_Collect_Strings_Limit_Error; static { // initialize resource bundle diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/messages.properties index f4e71343260..97b30e33ba3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/messages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepointactions/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2010 Ericsson and others. +# Copyright (c) 2010, 2012 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: # Ericsson - initial API and implementation +# Marc Khouzam (Ericsson) - Added support for collecting char pointers as strings (bug 373707) ############################################################################### TracepointActions_Actions_for_this_tracepoint=Actions for this tracepoint: @@ -29,3 +30,6 @@ TracepointActions_ActionDialog_Type=Action type: TracepointActions_Collect_Label=Data to collect (comma-separated list): TracepointActions_Evaluate_Label=Expressions to evaluate (comma-separated list): TracepointActions_WhileStepping_Sub_Actions=Sub-actions for While-stepping +TracepointActions_Collect_Strings_Label=Collect all character pointers as strings +TracepointActions_Collect_Strings_Limit_Label=with optional string size limit (bytes): +TracepointActions_Collect_Strings_Limit_Error=Only non-negative integers can be used. Current value will be ignored. diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java index 0d4236890e2..9508e27d78f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java @@ -159,4 +159,45 @@ public class GdbPlugin extends Plugin { return traceBuilder.toString(); } + /** + * Convenience method which returns the unique identifier of this plugin. + */ + public static String getUniqueIdentifier() { + if (getDefault() == null) { + // If the default instance is not yet initialized, + // return a static identifier. This identifier must + // match the plugin id defined in plugin.xml + return PLUGIN_ID; + } + return getDefault().getBundle().getSymbolicName(); + } + + /** + * Logs the specified status with this plug-in's log. + * + * @param status + * status to log + */ + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + /** + * Logs an internal error with the specified message. + * + * @param message + * the error message to log + */ + public static void logErrorMessage(String message) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null)); + } + + /** + * Logs an internal error with the specified throwable + * + * @param e + * the exception to be logged + */ + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e)); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/CollectAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/CollectAction.java index b69eba9985a..cf4bc8b06ef 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/CollectAction.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/CollectAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for collecting char pointers as strings (bug 373707) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.tracepointactions; @@ -21,21 +22,43 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; -import com.ibm.icu.text.MessageFormat; - /** + * Action used to tell GDB to collect different values from a tracepoint. + * It corresponds to GDB's 'collect' action. + * + * As for GDB 7.4: + * collect[/s] EXPRESSIONS + * The tracepoint collect command now takes an optional modifier "/s" + * that directs it to dereference pointer-to-character types and + * collect the bytes of memory up to a zero byte. The behavior is + * similar to what you see when you use the regular print command on a + * string. An optional integer following the "/s" sets a bound on the + * number of bytes that will be collected. + * * @since 3.0 */ public class CollectAction extends AbstractTracepointAction { private static final String COLLECT_ACTION_ID = "org.eclipse.cdt.dsf.gdb.tracepointactions.CollectAction"; //$NON-NLS-1$ + private static final String COLLECT_ACTION_ELEMENT_NAME = "collectData"; //$NON-NLS-1$ + private static final String COLLECT_STRING_ATTR = "collectString"; //$NON-NLS-1$ + private static final String COLLECT_AS_STRING_ATTR = "collectAsString"; //$NON-NLS-1$ + private static final String COLLECT_AS_STRING_LIMIT_ATTR = "collectAsStringLimit"; //$NON-NLS-1$ private String fCollectString = ""; //$NON-NLS-1$ + /** Indicates if we should ask GDB to collect character pointers as strings */ + private boolean fCharPtrAsStrings; + /** + * Optional limit of the size of the string to collect for character pointers. + * Null will indicate that no limit is to be used. + * This value should be non-negative. */ + private Integer fCharPtrAsStringsLimit; @Override public String getDefaultName() { @@ -50,6 +73,45 @@ public class CollectAction extends AbstractTracepointAction { fCollectString = str; } + /** + * Indicates if this collect action will treat character pointers as strings. + * @since 4.1 + */ + public boolean getCharPtrAsStrings() { + return fCharPtrAsStrings; + } + + /** + * Specify if this collect action should treat character pointers as strings. + * @since 4.1 + */ + public void setCharPtrAsStrings(boolean enable) { + fCharPtrAsStrings = enable; + } + + /** + * Indicates the maximum number of bytes that should be collected + * when treating character pointers as strings + * @return null if no limit is to be used + * @return a non-negative integer indicating the limit + * + * @since 4.1 + */ + public Integer getCharPtrAsStringsLimit() { + return fCharPtrAsStringsLimit; + } + + /** + * Specify the maximum number of bytes that should be collected when + * when treating character pointers as strings. + * @param limit A non-negative integer, or null of no limit should be used. + * + * @since 4.1 + */ + public void setCharPtrAsStringsLimit(Integer limit) { + fCharPtrAsStringsLimit = limit; + } + @Override public String getIdentifier() { return COLLECT_ACTION_ID; @@ -65,8 +127,12 @@ public class CollectAction extends AbstractTracepointAction { docBuilder = dfactory.newDocumentBuilder(); Document doc = docBuilder.newDocument(); - Element rootElement = doc.createElement("collectData"); //$NON-NLS-1$ - rootElement.setAttribute("collectString", fCollectString); //$NON-NLS-1$ + Element rootElement = doc.createElement(COLLECT_ACTION_ELEMENT_NAME); + + // Store the different attributes of this collect action + rootElement.setAttribute(COLLECT_STRING_ATTR, fCollectString); + rootElement.setAttribute(COLLECT_AS_STRING_ATTR, Boolean.toString(fCharPtrAsStrings)); + rootElement.setAttribute(COLLECT_AS_STRING_LIMIT_ATTR, fCharPtrAsStringsLimit == null ? "" : fCharPtrAsStringsLimit.toString()); //$NON-NLS-1$ doc.appendChild(rootElement); @@ -84,14 +150,29 @@ public class CollectAction extends AbstractTracepointAction { collectData = s.toString("UTF8"); //$NON-NLS-1$ } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } return collectData; } @Override public String getSummary() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_Collect_text, new Object[] { fCollectString }); + // Return the exact format that will be sent to GDB. + + StringBuffer collectCmd = new StringBuffer("collect "); //$NON-NLS-1$ + if (fCharPtrAsStrings) { + collectCmd.append("/s"); //$NON-NLS-1$ + if (fCharPtrAsStringsLimit != null) { + // No space between /s and the limit + collectCmd.append(fCharPtrAsStringsLimit.toString()); + } + // Now add the space before we append what to collect. + collectCmd.append(" "); //$NON-NLS-1$ + } + // Finally, actually add what to collect + collectCmd.append(fCollectString); + + return collectCmd.toString(); } @Override @@ -107,16 +188,33 @@ public class CollectAction extends AbstractTracepointAction { parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); parser.setErrorHandler(new DefaultHandler()); root = parser.parse(new InputSource(new StringReader(data))).getDocumentElement(); - fCollectString = root.getAttribute("collectString"); //$NON-NLS-1$ - if (fCollectString == null) - throw new Exception(); + + fCollectString = root.getAttribute(COLLECT_STRING_ATTR); + if (fCollectString == null) fCollectString = ""; //$NON-NLS-1$ + + String asStrings = root.getAttribute(COLLECT_AS_STRING_ATTR); + if (asStrings != null) { + fCharPtrAsStrings = Boolean.valueOf(asStrings); + } else { + fCharPtrAsStrings = false; + } + + fCharPtrAsStringsLimit = null; + String asStringsLimit = root.getAttribute(COLLECT_AS_STRING_LIMIT_ATTR); + if (asStringsLimit != null) { + try { + fCharPtrAsStringsLimit = Integer.valueOf(asStringsLimit); + } catch (NumberFormatException e) { + // leave as null to disable + } + } } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } } @Override public String toString() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_Collect_text, new Object[] { fCollectString }); + return getSummary(); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/EvaluateAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/EvaluateAction.java index da8a8a7574a..94b717451ea 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/EvaluateAction.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/EvaluateAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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,8 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Don't use translatable strings for the command summary + * since it will be send directly to GDB *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.tracepointactions; @@ -21,13 +23,12 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; -import com.ibm.icu.text.MessageFormat; - /** * @since 3.0 */ @@ -83,14 +84,15 @@ public class EvaluateAction extends AbstractTracepointAction { collectData = s.toString("UTF8"); //$NON-NLS-1$ } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } return collectData; } @Override public String getSummary() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_Evaluate_text, new Object[] { fEvalString }); + // Create command to be sent to GDB + return String.format("teval %s", fEvalString); //$NON-NLS-1$ } @Override @@ -110,12 +112,12 @@ public class EvaluateAction extends AbstractTracepointAction { if (fEvalString == null) throw new Exception(); } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } } @Override public String toString() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_Evaluate_text, new Object[] { fEvalString }); + return getSummary(); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/MessagesForTracepointActions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/MessagesForTracepointActions.java index 72ace6d2136..cbf8218f9f1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/MessagesForTracepointActions.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/MessagesForTracepointActions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Remove strings that should not be translated *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.tracepointactions; @@ -25,9 +26,6 @@ class MessagesForTracepointActions extends NLS { public static String TracepointActions_Collect_Name; public static String TracepointActions_Evaluate_Name; public static String TracepointActions_WhileStepping_Name; - public static String TracepointActions_Collect_text; - public static String TracepointActions_Evaluate_text; - public static String TracepointActions_WhileStepping_text; static { // initialize resource bundle diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/WhileSteppingAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/WhileSteppingAction.java index 8c509cd5267..f5e812f1e40 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/WhileSteppingAction.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/WhileSteppingAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2012 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,8 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Don't use translatable strings for the command summary + * since it will be send directly to GDB *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.tracepointactions; @@ -21,13 +23,12 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; -import com.ibm.icu.text.MessageFormat; - /** * @since 3.0 */ @@ -120,14 +121,15 @@ public class WhileSteppingAction extends AbstractTracepointAction { collectData = s.toString("UTF8"); //$NON-NLS-1$ } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } return collectData; } @Override public String getSummary() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_WhileStepping_text, new Object[] { fStepCount, fSubActionContent }); + // Create command to be sent to GDB + return String.format("while-stepping %s %s", fStepCount, fSubActionContent); //$NON-NLS-1$ } @Override @@ -149,12 +151,12 @@ public class WhileSteppingAction extends AbstractTracepointAction { throw new Exception(); setSubActionsContent(fSubActionNames); } catch (Exception e) { - e.printStackTrace(); + GdbPlugin.log(e); } } @Override public String toString() { - return MessageFormat.format(MessagesForTracepointActions.TracepointActions_WhileStepping_text, new Object[] { fStepCount, fSubActionContent }); + return getSummary(); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/messages.properties index 8ab0c0f533a..3d496c75aa1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/messages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/tracepointactions/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2010 Ericsson and others. +# Copyright (c) 2010, 2012 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 @@ -16,8 +16,3 @@ TracepointActions_Untitled_WhileStepping=Untitled While-Stepping Action TracepointActions_Collect_Name=Collect Action TracepointActions_Evaluate_Name=Evaluate Action TracepointActions_WhileStepping_Name=While-Stepping Action -# START NON-TRANSLATABLE -TracepointActions_Collect_text=collect {0} -TracepointActions_Evaluate_text=teval {0} -TracepointActions_WhileStepping_text=while-stepping {0} {1} -# END NON-TRANSLATABLE diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBRemoteTracepointsTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBRemoteTracepointsTest_7_0.java index 84f60e59ea5..1068854289a 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBRemoteTracepointsTest_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBRemoteTracepointsTest_7_0.java @@ -68,33 +68,33 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { IGDBLaunchConfigurationConstants.DEBUGGER_TRACEPOINT_FAST_THEN_NORMAL); } - private DsfSession fSession; - private DsfServicesTracker fServicesTracker; - private IBreakpoints fBreakpointService; + protected DsfSession fSession; + protected DsfServicesTracker fServicesTracker; + protected IBreakpoints fBreakpointService; // private ITraceControl fTraceService; - private IBreakpointsTargetDMContext fBreakpointsDmc; + protected IBreakpointsTargetDMContext fBreakpointsDmc; // private ITraceTargetDMContext fTraceTargetDmc; // private int fTotalTracingBufferSize = 0; - private static final String SOURCE_FILE = "TracepointTestApp.cc"; - private static final String METHOD_NAME = "testTracepoints"; - private static final int LINE_NUMBER_1 = 97; - private static final int LINE_NUMBER_2 = 75; - private static final int LINE_NUMBER_3 = 76; - private static final int LINE_NUMBER_4 = 85; - private static final int LINE_LOOP_2 = 109; - private static final String NO_CONDITION = ""; - private static final String NO_COMMANDS = ""; + protected static final String SOURCE_FILE = "TracepointTestApp.cc"; + protected static final String METHOD_NAME = "testTracepoints"; + protected static final int LINE_NUMBER_1 = 97; + protected static final int LINE_NUMBER_2 = 75; + protected static final int LINE_NUMBER_3 = 76; + protected static final int LINE_NUMBER_4 = 85; + protected static final int LINE_LOOP_2 = 109; + protected static final String NO_CONDITION = ""; + protected static final String NO_COMMANDS = ""; // private static final int LAST_LINE_NUMBER = 94; // // private static final int TOTAL_FRAMES_TO_BE_COLLECTED = 1 + 1 + 10 + 1 + 10000; - private final static int[] PASS_COUNTS = {12, 2, 32, 6, 128, 0, 0, 0, 0, 0, 0, 0}; - private final static String[] CONDITIONS = {"gIntVar == 543", "gBoolVar == false", "counter == 3", "counter > 4", "counter > 2 && lIntVar == 12345"}; + protected final static int[] PASS_COUNTS = {12, 2, 32, 6, 128, 0, 0, 0, 0, 0, 0, 0}; + protected final static String[] CONDITIONS = {"gIntVar == 543", "gBoolVar == false", "counter == 3", "counter > 4", "counter > 2 && lIntVar == 12345"}; - private static CollectAction[] COLLECT_ACTIONS = new CollectAction[10]; - private static EvaluateAction[] EVAL_ACTIONS = new EvaluateAction[10]; + protected static CollectAction[] COLLECT_ACTIONS = new CollectAction[10]; + protected static EvaluateAction[] EVAL_ACTIONS = new EvaluateAction[10]; // private static WhileSteppingAction[] STEPPING_ACTION_1 = new WhileSteppingAction[3]; static { @@ -248,7 +248,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { } // Clears the counters - private void clearEventCounters() { + protected void clearEventCounters() { synchronized (lock) { for (int i = 0; i < fBreakpointEvents.length; i++) { fBreakpointEvents[i] = 0; @@ -259,7 +259,7 @@ public class GDBRemoteTracepointsTest_7_0 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]; @@ -269,7 +269,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { // Suspends the thread until an event is flagged // NOTE: too simple for real life but good enough for this test suite - private void waitForBreakpointEvent() { + protected void waitForBreakpointEvent() { synchronized (lock) { while (!fBreakpointEvent) { try { @@ -291,7 +291,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { // Breakpoint service methods (to use with tracepoints). // ********************************************************************* - private IBreakpointDMContext insertBreakpoint(final IBreakpointsTargetDMContext context, + protected IBreakpointDMContext insertBreakpoint(final IBreakpointsTargetDMContext context, final Map attributes) throws InterruptedException { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor(); @@ -317,7 +317,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { return (IBreakpointDMContext)wait.getReturnInfo(); } - private void removeBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException + protected void removeBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor(); @@ -338,7 +338,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { assertTrue(wait.getMessage(), wait.isOK()); } - private void updateBreakpoint(final IBreakpointDMContext breakpoint, + protected void updateBreakpoint(final IBreakpointDMContext breakpoint, final Map delta) throws InterruptedException { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor(); @@ -360,7 +360,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { assertTrue(wait.getMessage(), wait.isOK()); } - private IBreakpointDMData getBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException + protected IBreakpointDMData getBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor(); @@ -384,7 +384,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { return (IBreakpointDMData)wait.getReturnInfo(); } - private IBreakpointDMContext[] getBreakpoints(final IBreakpointsTargetDMContext context) throws InterruptedException + protected IBreakpointDMContext[] getBreakpoints(final IBreakpointsTargetDMContext context) throws InterruptedException { final AsyncCompletionWaitor wait = new AsyncCompletionWaitor(); @@ -550,7 +550,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { // Below are the tests for the control of tracepoints. // ********************************************************************* - private IBreakpointDMContext[] fTracepoints = null; + protected IBreakpointDMContext[] fTracepoints = null; // private void checkTraceStatus(boolean supported, boolean active, int frames, // STOP_REASON_ENUM reason, Integer stoppingTracepoint) throws Throwable { @@ -592,7 +592,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { // GDB 7.0 does not support fast tracepoints, but GDB 7.2 will protected boolean fastTracepointsSupported() { return false; } - private class TracepointData { + protected class TracepointData { String sourceFile; int lineNumber; String condition; @@ -616,7 +616,7 @@ public class GDBRemoteTracepointsTest_7_0 extends BaseTestCase { } } - private void checkTracepoints(TracepointData[] dataArray) throws Throwable { + protected void checkTracepoints(TracepointData[] dataArray) throws Throwable { int numTracepoints = dataArray.length; // Fetch the tp list from the backend diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBRemoteTracepointsTest_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBRemoteTracepointsTest_7_4.java index 2c9e21aa832..23f22aee96b 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBRemoteTracepointsTest_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBRemoteTracepointsTest_7_4.java @@ -11,10 +11,18 @@ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.CollectAction; +import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager; +import org.eclipse.cdt.dsf.mi.service.MIBreakpoints; 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.GDBRemoteTracepointsTest_7_3; import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; @RunWith(BackgroundRunner.class) @@ -30,4 +38,46 @@ public class GDBRemoteTracepointsTest_7_4 extends GDBRemoteTracepointsTest_7_3 { // instruction of 4 bytes or more, instead of 5. return true; } + + /** + * This test sets the different types of tracepoints and then sets some string collection actions + */ + @Test + public void tracepointActionsWithCollectStrings() throws Throwable { + TracepointActionManager tracepointActionMgr = TracepointActionManager.getInstance(); + + CollectAction action1 = new CollectAction(); + action1.setCollectString("/s $locals"); + action1.setName("Collect string locals"); + tracepointActionMgr.addAction(action1); + + CollectAction action2 = new CollectAction(); + action2.setCollectString("/s3 $locals, $reg"); + action2.setName("Collect string locals, reg"); + tracepointActionMgr.addAction(action2); + + createTracepoints(); + + Map delta = new HashMap(); + // Set conditions for all tracepoints + delta.put(MIBreakpoints.COMMANDS, action1.getName()); + updateBreakpoint(fTracepoints[0], delta); + delta.put(MIBreakpoints.COMMANDS, action2.getName()); + updateBreakpoint(fTracepoints[1], delta); + delta.put(MIBreakpoints.COMMANDS, action1.getName()); + updateBreakpoint(fTracepoints[2], delta); + delta.put(MIBreakpoints.COMMANDS, action1.getName()); + updateBreakpoint(fTracepoints[3], delta); + delta.put(MIBreakpoints.COMMANDS, action2.getName()); + updateBreakpoint(fTracepoints[4], delta); + + ArrayList dataArray = new ArrayList(); + dataArray.add(new TracepointData(SOURCE_FILE, LINE_NUMBER_2, NO_CONDITION, 0, true, action1.toString(), false)); + dataArray.add(new TracepointData(SOURCE_FILE, LINE_NUMBER_3, NO_CONDITION, 0, true, action2.toString(), false)); + dataArray.add(new TracepointData(SOURCE_FILE, LINE_NUMBER_4, NO_CONDITION, 0, true, action1.toString(), true)); + dataArray.add(new TracepointData(SOURCE_FILE, LINE_NUMBER_1, NO_CONDITION, 0, true, action1.toString(), true)); + dataArray.add(new TracepointData(SOURCE_FILE, LINE_LOOP_2, NO_CONDITION, 0, true, action2.toString(), acceptsFastTpOnFourBytes())); + + checkTracepoints(dataArray.toArray(new TracepointData[dataArray.size()])); + } } From 64ce186a2fc8df88da09b1688000a1cb529d47b1 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Fri, 20 Apr 2012 15:44:52 -0400 Subject: [PATCH 03/14] Update org.eclipse.cdt.autotools.core plugin version to 1.1.0. --- build/org.eclipse.cdt.autotools.core/ChangeLog | 5 +++++ build/org.eclipse.cdt.autotools.core/META-INF/MANIFEST.MF | 2 +- build/org.eclipse.cdt.autotools.core/pom.xml | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/build/org.eclipse.cdt.autotools.core/ChangeLog b/build/org.eclipse.cdt.autotools.core/ChangeLog index c1697e68464..4db2797dc08 100644 --- a/build/org.eclipse.cdt.autotools.core/ChangeLog +++ b/build/org.eclipse.cdt.autotools.core/ChangeLog @@ -1,3 +1,8 @@ +2012-04-20 Jeff Johnston + + * META-INF/MANIFEST.MF: Bump up version to 1.1.0. + * pom.xml: Ditto. + 2012-04-11 Jeff Johnston Bug #375007 fix from Anna Dushistova diff --git a/build/org.eclipse.cdt.autotools.core/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.autotools.core/META-INF/MANIFEST.MF index f3e334d00e6..2cb9762176a 100644 --- a/build/org.eclipse.cdt.autotools.core/META-INF/MANIFEST.MF +++ b/build/org.eclipse.cdt.autotools.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name.0 Bundle-SymbolicName: org.eclipse.cdt.autotools.core;singleton:=true -Bundle-Version: 1.0.2.qualifier +Bundle-Version: 1.1.0.qualifier Bundle-Activator: org.eclipse.cdt.autotools.core.AutotoolsPlugin Bundle-Localization: plugin Require-Bundle: org.eclipse.ui;bundle-version="3.4.0", diff --git a/build/org.eclipse.cdt.autotools.core/pom.xml b/build/org.eclipse.cdt.autotools.core/pom.xml index f7b13545c0f..15c39039016 100644 --- a/build/org.eclipse.cdt.autotools.core/pom.xml +++ b/build/org.eclipse.cdt.autotools.core/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 1.0.2-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.cdt.autotools.core eclipse-plugin - \ No newline at end of file + From 68b6f3dc90bf72b97eb6b3ed03b8079d9365eb00 Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Mon, 23 Apr 2012 00:25:47 -0400 Subject: [PATCH 04/14] Upgrade to Tycho 0.14.1 --- build/org.eclipse.cdt.autotools.docs/pom.xml | 5 ++--- build/org.eclipse.cdt.autotools.tests/pom.xml | 5 +++-- .../pom.xml | 5 +++-- core/org.eclipse.cdt.core.tests/pom.xml | 5 +++-- core/org.eclipse.cdt.ui.tests/pom.xml | 5 +++-- .../feature.xml | 4 +--- .../feature.xml | 4 +--- .../org.eclipse.cdt.launch.remote/build.properties | 1 - doc/org.eclipse.cdt.doc.isv/pom.xml | 5 ++--- doc/org.eclipse.cdt.doc.user/pom.xml | 5 ++--- .../feature.xml | 4 +--- .../build.properties | 3 +-- pom.xml | 3 ++- .../org.eclipse.cdt.testsrunner.test/pom.xml | 14 ++++++++++++-- upc/org.eclipse.cdt.bupc-feature/feature.xml | 4 +--- windows/org.eclipse.cdt.msw-feature/feature.xml | 4 +--- 16 files changed, 38 insertions(+), 38 deletions(-) diff --git a/build/org.eclipse.cdt.autotools.docs/pom.xml b/build/org.eclipse.cdt.autotools.docs/pom.xml index 2653716ae0a..71e6d764e09 100644 --- a/build/org.eclipse.cdt.autotools.docs/pom.xml +++ b/build/org.eclipse.cdt.autotools.docs/pom.xml @@ -18,10 +18,9 @@ - - com.google.code.tycho-eclipserun-plugin + org.eclipse.tycho.extras tycho-eclipserun-plugin - ${tycho-version} + ${tycho-extras-version} -application org.eclipse.ant.core.antRunner -buildfile build-index.xml build.index diff --git a/build/org.eclipse.cdt.autotools.tests/pom.xml b/build/org.eclipse.cdt.autotools.tests/pom.xml index e924d725f96..2ee67c56a3c 100644 --- a/build/org.eclipse.cdt.autotools.tests/pom.xml +++ b/build/org.eclipse.cdt.autotools.tests/pom.xml @@ -15,13 +15,14 @@ org.eclipse.cdt.autotools.tests eclipse-test-plugin - + + diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/pom.xml b/build/org.eclipse.cdt.managedbuilder.core.tests/pom.xml index f95d8307726..eccbc93b640 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/pom.xml +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/pom.xml @@ -15,13 +15,14 @@ org.eclipse.cdt.managedbuilder.core.tests eclipse-test-plugin - + + diff --git a/core/org.eclipse.cdt.core.tests/pom.xml b/core/org.eclipse.cdt.core.tests/pom.xml index d8b56d0ea12..84bda2159b9 100644 --- a/core/org.eclipse.cdt.core.tests/pom.xml +++ b/core/org.eclipse.cdt.core.tests/pom.xml @@ -15,13 +15,14 @@ org.eclipse.cdt.core.tests eclipse-test-plugin - + + diff --git a/core/org.eclipse.cdt.ui.tests/pom.xml b/core/org.eclipse.cdt.ui.tests/pom.xml index d382d72abe2..e062a80e1a1 100644 --- a/core/org.eclipse.cdt.ui.tests/pom.xml +++ b/core/org.eclipse.cdt.ui.tests/pom.xml @@ -15,13 +15,14 @@ org.eclipse.cdt.ui.tests eclipse-test-plugin - + + diff --git a/cross/org.eclipse.cdt.build.crossgcc-feature/feature.xml b/cross/org.eclipse.cdt.build.crossgcc-feature/feature.xml index cc479d50941..25986245970 100644 --- a/cross/org.eclipse.cdt.build.crossgcc-feature/feature.xml +++ b/cross/org.eclipse.cdt.build.crossgcc-feature/feature.xml @@ -4,9 +4,7 @@ label="%featureName" version="1.1.0.qualifier" provider-name="%providerName" - plugin="org.eclipse.cdt.build.crossgcc" - license-feature="org.eclipse.cdt.license" - license-feature-version="1.0.0.qualifier"> + plugin="org.eclipse.cdt.build.crossgcc"> %description diff --git a/cross/org.eclipse.cdt.launch.remote-feature/feature.xml b/cross/org.eclipse.cdt.launch.remote-feature/feature.xml index e350efe78e4..2f54b2e2064 100644 --- a/cross/org.eclipse.cdt.launch.remote-feature/feature.xml +++ b/cross/org.eclipse.cdt.launch.remote-feature/feature.xml @@ -3,9 +3,7 @@ id="org.eclipse.cdt.launch.remote" label="%featureName" version="6.0.0.qualifier" - provider-name="%providerName" - license-feature="org.eclipse.cdt.license" - license-feature-version="1.0.0.qualifier"> + provider-name="%providerName"> %description diff --git a/cross/org.eclipse.cdt.launch.remote/build.properties b/cross/org.eclipse.cdt.launch.remote/build.properties index 2b8a8019ae9..4c7b6e43b98 100644 --- a/cross/org.eclipse.cdt.launch.remote/build.properties +++ b/cross/org.eclipse.cdt.launch.remote/build.properties @@ -18,7 +18,6 @@ bin.includes = META-INF/,\ about.ini,\ about.mappings,\ about.properties,\ - eclipse32.png,\ plugin.properties,\ plugin.xml,\ remotecdt.html,\ diff --git a/doc/org.eclipse.cdt.doc.isv/pom.xml b/doc/org.eclipse.cdt.doc.isv/pom.xml index 80815e0d4d1..84b693b24d9 100644 --- a/doc/org.eclipse.cdt.doc.isv/pom.xml +++ b/doc/org.eclipse.cdt.doc.isv/pom.xml @@ -32,10 +32,9 @@ - - com.google.code.tycho-eclipserun-plugin + org.eclipse.tycho.extras tycho-eclipserun-plugin - ${tycho-version} + ${tycho-extras-version} -application org.eclipse.ant.core.antRunner -buildfile buildDoc.xml diff --git a/doc/org.eclipse.cdt.doc.user/pom.xml b/doc/org.eclipse.cdt.doc.user/pom.xml index 58ee57aef2e..b59afdb3a86 100644 --- a/doc/org.eclipse.cdt.doc.user/pom.xml +++ b/doc/org.eclipse.cdt.doc.user/pom.xml @@ -32,10 +32,9 @@ - - com.google.code.tycho-eclipserun-plugin + org.eclipse.tycho.extras tycho-eclipserun-plugin - ${tycho-version} + ${tycho-extras-version} -application org.eclipse.ant.core.antRunner -buildfile customBuildCallbacks.xml build.index diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag-feature/feature.xml b/jtag/org.eclipse.cdt.debug.gdbjtag-feature/feature.xml index ee3fed7fba8..bdd58f8551f 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag-feature/feature.xml +++ b/jtag/org.eclipse.cdt.debug.gdbjtag-feature/feature.xml @@ -4,9 +4,7 @@ label="%featureName" version="7.0.0.qualifier" provider-name="%providerName" - image="eclipse_update_120.jpg" - license-feature="org.eclipse.cdt.license" - license-feature-version="1.0.0.qualifier"> + image="eclipse_update_120.jpg"> %description diff --git a/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties b/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties index 464efb7b44d..1e9c1d76b16 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties +++ b/memory/org.eclipse.cdt.debug.ui.memory.search/build.properties @@ -15,6 +15,5 @@ bin.includes = META-INF/,\ plugin.properties,\ .,\ plugin.xml,\ - about.html,\ - icons/ + about.html src.includes = about.html diff --git a/pom.xml b/pom.xml index 1ab4aa810e0..9c59808b016 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,8 @@ CDT Parent - 0.13.0 + 0.14.1 + 0.14.0 3.8milestones http://download.eclipse.org/eclipse/updates/${platform-version} R20110523182458 diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml index 0606be04322..34faa27f7fa 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml @@ -15,16 +15,26 @@ org.eclipse.cdt.testsrunner.test eclipse-test-plugin - + + + + + org.eclipse.tycho + tycho-compiler-plugin + + 1.6 + 1.6 + + org.eclipse.tycho tycho-surefire-plugin diff --git a/upc/org.eclipse.cdt.bupc-feature/feature.xml b/upc/org.eclipse.cdt.bupc-feature/feature.xml index 07c2c17270c..46059ab3eb4 100644 --- a/upc/org.eclipse.cdt.bupc-feature/feature.xml +++ b/upc/org.eclipse.cdt.bupc-feature/feature.xml @@ -4,9 +4,7 @@ label="%featureName" version="1.0.3.qualifier" provider-name="%providerName" - plugin="org.eclipse.cdt.managedbuilder.bupc.ui" - license-feature="org.eclipse.cdt.license" - license-feature-version="1.0.0.qualifier"> + plugin="org.eclipse.cdt.managedbuilder.bupc.ui"> %description diff --git a/windows/org.eclipse.cdt.msw-feature/feature.xml b/windows/org.eclipse.cdt.msw-feature/feature.xml index 46a446dee07..2c613f7920b 100644 --- a/windows/org.eclipse.cdt.msw-feature/feature.xml +++ b/windows/org.eclipse.cdt.msw-feature/feature.xml @@ -3,9 +3,7 @@ id="org.eclipse.cdt.msw" label="CDT Visual C++ Support" version="1.0.0.qualifier" - provider-name="Eclipse CDT" - license-feature="org.eclipse.cdt.license" - license-feature-version="1.0.0.qualifier"> + provider-name="Eclipse CDT"> %description From dd48abd247bb4113ef1f78dd6da31845985b2a72 Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Mon, 23 Apr 2012 10:50:59 -0400 Subject: [PATCH 05/14] About.txt -> ABOUT.txt. This should fix the build on case sensitive systems. --- visualizer/org.eclipse.cdt.visualizer-feature/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visualizer/org.eclipse.cdt.visualizer-feature/build.properties b/visualizer/org.eclipse.cdt.visualizer-feature/build.properties index 7a4864dbb62..daee1defe19 100755 --- a/visualizer/org.eclipse.cdt.visualizer-feature/build.properties +++ b/visualizer/org.eclipse.cdt.visualizer-feature/build.properties @@ -13,5 +13,5 @@ bin.includes = feature.xml,\ license.html,\ epl-v10.html,\ eclipse_update_120.jpg,\ - About.txt + ABOUT.txt \ No newline at end of file From eb6522badf02ad57388cf52910694769abd7f8b3 Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Mon, 23 Apr 2012 02:00:18 -0400 Subject: [PATCH 06/14] Bug 377295 - Build fails if project name contains characters [, ] Change-Id: I9f116f524bb30e064e1cdbb3588c494a450d765e Reviewed-on: https://git.eclipse.org/r/5636 Reviewed-by: Andrew Gvozdev IP-Clean: Andrew Gvozdev Tested-by: Andrew Gvozdev --- .../testplugin/AbstractBuilderTest.java | 12 +++--- .../ManagedBuildDependencyLibsTests.java | 42 +++++++++---------- .../internal/core/AdditionalInput.java | 10 +++-- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/AbstractBuilderTest.java b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/AbstractBuilderTest.java index 722fb5d7629..0b2a1c1d408 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/AbstractBuilderTest.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/AbstractBuilderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Broadcom Corporation and others. + * Copyright (c) 2011, 2012 Broadcom Corporation 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 @@ -71,11 +71,13 @@ public abstract class AbstractBuilderTest extends TestCase { Job.getJobManager().cancel(CCorePlugin.getPDOMManager()); Job.getJobManager().join(CCorePlugin.getPDOMManager(), null); - // Clean-up any projects we were using - for (IProject project : projects) { - project.delete(true, null); + if (projects != null) { + // Clean-up any projects we were using + for (IProject project : projects) { + project.delete(true, null); + } + projects.clear(); } - projects.clear(); } /** diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildDependencyLibsTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildDependencyLibsTests.java index e0bd32d4bfd..965ee5a0438 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildDependencyLibsTests.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildDependencyLibsTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 QNX Software Systems and others. + * Copyright (c) 2011, 2012 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,11 +11,9 @@ package org.eclipse.cdt.managedbuilder.core.tests; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import junit.framework.Test; -import junit.framework.TestCase; import junit.framework.TestSuite; import org.eclipse.cdt.core.model.CoreModel; @@ -28,6 +26,7 @@ import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.core.FolderInfo; import org.eclipse.cdt.managedbuilder.tcmodification.IConfigurationModification; import org.eclipse.cdt.managedbuilder.tcmodification.IToolChainModificationManager; +import org.eclipse.cdt.managedbuilder.testplugin.AbstractBuilderTest; import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -39,11 +38,10 @@ import org.eclipse.core.resources.IWorkspaceDescription; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; -public class ManagedBuildDependencyLibsTests extends TestCase { +public class ManagedBuildDependencyLibsTests extends AbstractBuilderTest { private static final String PROJ_PATH = "depLibsProjects"; private static final String MESSAGE_TAIL = " (see .log file for more details)."; @@ -60,12 +58,12 @@ public class ManagedBuildDependencyLibsTests extends TestCase { suite.addTest(new ManagedBuildDependencyLibsTests("testDepLibs")); suite.addTest(new ManagedBuildDependencyLibsTests("testDepUObjs")); + suite.addTest(new ManagedBuildDependencyLibsTests("testGetArtifactTimeStampEscapeURI_bug377295")); return suite; } private void buildProject(IProject curProject) { - IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(curProject); try { IProject[] referencedProjects = curProject.getReferencedProjects(); for(int i = 0; i < referencedProjects.length; ++i) @@ -117,20 +115,6 @@ public class ManagedBuildDependencyLibsTests extends TestCase { ManagedBuildTestHelper.removeProject(fTlib.getName()); ManagedBuildTestHelper.removeProject(fTobjs.getName()); } - - private void deleteFiles(IFolder dir, String pattern, IProgressMonitor monitor) { - List files = new ArrayList(); - findFiles(dir, pattern, files); - for(Iterator i = files.iterator(); i.hasNext(); ) { - IFile file = i.next(); - try { - file.delete(true, monitor); - } catch (CoreException e) { - e.printStackTrace(); - fail("Error deleting file " + file.getFullPath().toString() + '.' + MESSAGE_TAIL); - } - } - } private void findFiles(IResource dir, String pattern, List files) { IResource resource = null; @@ -146,7 +130,7 @@ public class ManagedBuildDependencyLibsTests extends TestCase { for(int i = 0; i < members.length; ++i) { resource = members[i]; if(resource.getType() == IResource.FOLDER) - findFiles((IFolder)resource, pattern, files); + findFiles(resource, pattern, files); else { if(resource.getName().matches(pattern)) files.add((IFile)resource); @@ -291,4 +275,20 @@ public class ManagedBuildDependencyLibsTests extends TestCase { fail("Error. This time it should build application."); } } + + // Tests that the URI used to get the time stamp of the artifact is escaped correctly + // See AdditionalInput.getArtifactTimeStamp(IToolChain toolChain) + public void testGetArtifactTimeStampEscapeURI_bug377295() throws CoreException { + setWorkspace("regressions"); + final IProject project = loadProject("helloworldC"); + IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); + IConfiguration[] configs = buildInfo.getManagedProject().getConfigurations(); + for (IConfiguration configuration : configs) { + configuration.setArtifactName("test [377295]"); + } + + project.build(IncrementalProjectBuilder.FULL_BUILD, null); + // This will trigger AdditionalInput.getArtifactTimeStamp to get called, no IllegalArgumentException should be thrown + project.build(IncrementalProjectBuilder.FULL_BUILD, null); + } } \ No newline at end of file diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java index 0ac2ec3976f..e7535c98a39 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java @@ -1,13 +1,14 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 Intel Corporation and others. + * Copyright (c) 2005, 2012 Intel Corporation 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: - * Intel Corporation - Initial API and implementation - * IBM Corporation + * Intel Corporation - Initial API and implementation + * IBM Corporation + * Marc-Andre Laperle *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; @@ -40,6 +41,7 @@ import org.eclipse.cdt.managedbuilder.internal.macros.IMacroContextInfo; import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData; import org.eclipse.cdt.managedbuilder.macros.BuildMacroException; import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.cdt.utils.EFSExtensionManager; import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver; import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; import org.eclipse.core.filesystem.EFS; @@ -380,7 +382,7 @@ public class AdditionalInput implements IAdditionalInput { } catch (BuildMacroException e) { } - URI buildArtifactURI = buildLocationURI.resolve(artifactName); + URI buildArtifactURI = EFSExtensionManager.getDefault().append(buildLocationURI, artifactName); try { IFileStore artifact = EFS.getStore(buildArtifactURI); From 383f0d289c5d46af05fa2774f96d87f12c5938d2 Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Mon, 23 Apr 2012 13:05:22 -0400 Subject: [PATCH 07/14] Fix build.properties that made testsrunner.test compile in J2SE-1.5, remove work around. --- .../org.eclipse.cdt.testsrunner.test/build.properties | 2 +- testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties index 67172946998..1a640cdd7e7 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties @@ -16,5 +16,5 @@ bin.includes = META-INF/,\ OSGI-INF/,\ test.xml,\ about.html -jre.compilation.profile = J2SE-1.5 + src.includes = about.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml index 34faa27f7fa..53b4762eea8 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml @@ -26,15 +26,6 @@ - - - org.eclipse.tycho - tycho-compiler-plugin - - 1.6 - 1.6 - - org.eclipse.tycho tycho-surefire-plugin From 10f7e547a12358c7892dcbc939df99cc03e051d5 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 24 Apr 2012 17:31:36 -0700 Subject: [PATCH 08/14] Cosmetics. --- .../cdt/internal/core/model/CElement.java | 76 ++++++++----------- .../org/eclipse/cdt/core/index/IIndex.java | 9 +-- .../internal/core/index/CPPTypedefClone.java | 2 +- .../core/pdom/dom/cpp/PDOMCPPLinkage.java | 23 +++--- .../pdom/dom/cpp/PDOMCPPUsingDeclaration.java | 5 +- ...PDOMCPPUsingDeclarationSpecialization.java | 5 +- .../refactoring/rename/RefactoringTests.java | 4 +- .../rename/RenameFunctionTests.java | 6 +- .../refactoring/rename/RenameMacroTests.java | 7 +- .../rename/RenameTemplatesTests.java | 6 +- .../tests/refactoring/rename/RenameTests.java | 8 +- .../refactoring/rename/RenameTypeTests.java | 6 +- .../rename/RenameVariableTests.java | 5 +- .../rename/TestRenameParticipant.java | 25 +++--- .../refactoring/rename/CRefactoringMatch.java | 4 +- .../rename/CRenameClassProcessor.java | 3 +- .../rename/CRenameTypeProcessor.java | 2 +- 17 files changed, 90 insertions(+), 106 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java index 7a1f3f31d24..6f83bf1a5a3 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java @@ -10,7 +10,6 @@ * Markus Schorn (Wind River Systems) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.core.model; import java.net.URI; @@ -41,7 +40,6 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.PlatformObject; public abstract class CElement extends PlatformObject implements ICElement { - public static final char CEM_ESCAPE = '\\'; public static final char CEM_CPROJECT = '='; public static final char CEM_SOURCEROOT = '/'; @@ -51,11 +49,10 @@ public abstract class CElement extends PlatformObject implements ICElement { public static final char CEM_PARAMETER = '('; public static final char CEM_ELEMENTTYPE = '#'; - protected static final CElement[] NO_ELEMENTS = new CElement[0]; + protected static final CElement[] NO_ELEMENTS = {}; + protected int fType; - protected ICElement fParent; - protected String fName; protected CElement(ICElement parent, String name, int type) { @@ -80,7 +77,6 @@ public abstract class CElement extends PlatformObject implements ICElement { return super.getAdapter(adapter); } - // setters public void setElementType (int type) { @@ -123,14 +119,7 @@ public abstract class CElement extends PlatformObject implements ICElement { @Override public URI getLocationURI() { IResource res = getUnderlyingResource(); - - if(res != null) { - return res.getLocationURI(); - } - - else { - return null; - } + return res == null ? null : res.getLocationURI(); } @Override @@ -138,8 +127,7 @@ public abstract class CElement extends PlatformObject implements ICElement { try { return getElementInfo() != null; } catch (CModelException e) { - // Do not log it, it will fil the .log alarming the user. - //CCorePlugin.log(e); + // Do not log it, otherwise it would fill the .log alarming the user. return false; } } @@ -153,7 +141,7 @@ public abstract class CElement extends PlatformObject implements ICElement { */ protected ICElement getSourceElementAtOffset(int offset) throws CModelException { if (this instanceof ISourceReference && this instanceof Parent) { - ICElement[] children = ((Parent)this).getChildren(); + ICElement[] children = ((Parent) this).getChildren(); for (ICElement aChild : children) { if (aChild instanceof ISourceReference) { ISourceReference child = (ISourceReference) aChild; @@ -162,9 +150,9 @@ public abstract class CElement extends PlatformObject implements ICElement { int endPos = startPos + range.getLength(); if (offset < endPos && offset >= startPos) { if (child instanceof Parent) { - return ((Parent)child).getSourceElementAtOffset(offset); + return ((Parent) child).getSourceElementAtOffset(offset); } - return (ICElement)child; + return (ICElement) child; } } } @@ -185,7 +173,7 @@ public abstract class CElement extends PlatformObject implements ICElement { protected ICElement[] getSourceElementsAtOffset(int offset) throws CModelException { if (this instanceof ISourceReference && this instanceof Parent) { ArrayList list = new ArrayList(); - ICElement[] children = ((Parent)this).getChildren(); + ICElement[] children = ((Parent) this).getChildren(); for (ICElement aChild : children) { if (aChild instanceof ISourceReference) { ISourceReference child = (ISourceReference) aChild; @@ -194,7 +182,7 @@ public abstract class CElement extends PlatformObject implements ICElement { int endPos = startPos + range.getLength(); if (offset < endPos && offset >= startPos) { if (child instanceof Parent) { - ICElement[] elements = ((Parent)child).getSourceElementsAtOffset(offset); + ICElement[] elements = ((Parent) child).getSourceElementsAtOffset(offset); list.addAll(Arrays.asList(elements)); } list.add(child); @@ -238,7 +226,8 @@ public abstract class CElement extends PlatformObject implements ICElement { public ICProject getCProject() { ICElement current = this; do { - if (current instanceof ICProject) return (ICProject) current; + if (current instanceof ICProject) + return (ICProject) current; } while ((current = current.getParent()) != null); return null; } @@ -285,7 +274,7 @@ public abstract class CElement extends PlatformObject implements ICElement { } String lhsName= lhs.getElementName(); String rhsName= rhs.getElementName(); - if( lhsName == null || rhsName == null || lhsName.length() != rhsName.length() || + if (lhsName == null || rhsName == null || lhsName.length() != rhsName.length() || !lhsName.equals(rhsName)) { return false; } @@ -311,7 +300,7 @@ public abstract class CElement extends PlatformObject implements ICElement { public CElementInfo getElementInfo (IProgressMonitor monitor) throws CModelException { CModelManager manager = CModelManager.getDefault(); - CElementInfo info = (CElementInfo)manager.getInfo(this); + CElementInfo info = (CElementInfo) manager.getInfo(this); if (info != null) { return info; } @@ -326,7 +315,7 @@ public abstract class CElement extends PlatformObject implements ICElement { } public String toDebugString() { - return getElementName() + " " + getTypeString(); //$NON-NLS-1$ + return getElementName() + " " + getTypeString(); //$NON-NLS-1$ } // util @@ -367,11 +356,11 @@ public abstract class CElement extends PlatformObject implements ICElement { case C_FIELD: return "C_FIELD"; //$NON-NLS-1$ case C_METHOD: - return "C_METHOD"; //$NON-NLS-1$ + return "C_METHOD"; //$NON-NLS-1$ case C_NAMESPACE: - return "C_NAMESPACE"; //$NON-NLS-1$ + return "C_NAMESPACE"; //$NON-NLS-1$ case C_USING: - return "C_USING"; //$NON-NLS-1$ + return "C_USING"; //$NON-NLS-1$ case C_VCONTAINER: return "C_CONTAINER"; //$NON-NLS-1$ case C_BINARY: @@ -411,7 +400,7 @@ public abstract class CElement extends PlatformObject implements ICElement { */ public IOpenable getOpenableParent() { if (fParent instanceof IOpenable) { - return (IOpenable)fParent; + return (IOpenable) fParent; } return null; } @@ -426,7 +415,8 @@ public abstract class CElement extends PlatformObject implements ICElement { * if successful, or false if an error is encountered while determining * the structure of this element. */ - protected abstract void generateInfos(CElementInfo info, Map newElements, IProgressMonitor monitor) throws CModelException; + protected abstract void generateInfos(CElementInfo info, Map newElements, + IProgressMonitor monitor) throws CModelException; /** * Open a IOpenable that is known to be closed (no check for @@ -441,13 +431,14 @@ public abstract class CElement extends PlatformObject implements ICElement { if (info == null) { info = newElements.get(this); } - if (info == null) { // a source ref element could not be opened - // close any buffer that was opened for the openable parent + if (info == null) { + // A source ref element could not be opened. + // Close any buffer that was opened for the openable parent. Iterator iterator = newElements.keySet().iterator(); while (iterator.hasNext()) { ICElement element = iterator.next(); if (element instanceof Openable) { - ((Openable)element).closeBuffer(); + ((Openable) element).closeBuffer(); } } throw newNotPresentException(); @@ -455,7 +446,6 @@ public abstract class CElement extends PlatformObject implements ICElement { if (!hadTemporaryCache) { manager.putInfos(this, newElements); } - } finally { if (!hadTemporaryCache) { manager.resetTemporaryCache(); @@ -463,7 +453,6 @@ public abstract class CElement extends PlatformObject implements ICElement { } } - /** * @see ICElement */ @@ -519,17 +508,14 @@ public abstract class CElement extends PlatformObject implements ICElement { return Util.combineHashCodes(elem.getElementName().hashCode(), parent.hashCode()); } - /* - * Test to see if two objects are identical + /** + * Checks if two objects are identical * Subclasses should override accordingly */ public boolean isIdentical(CElement otherElement){ return this.equals(otherElement); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.model.ICElement#accept(org.eclipse.cdt.core.model.ICElementVisitor) - */ @Override public void accept(ICElementVisitor visitor) throws CoreException { // Visit me, return right away if the visitor doesn't want to visit my children @@ -538,15 +524,13 @@ public abstract class CElement extends PlatformObject implements ICElement { // If I am a Parent, visit my children if (this instanceof IParent) { - ICElement [] children = ((IParent)this).getChildren(); - for (int i = 0; i < children.length; ++i) + ICElement [] children = ((IParent) this).getChildren(); + for (int i = 0; i < children.length; ++i) { children[i].accept(visitor); + } } } - /* - * @see org.eclipse.cdt.core.model.ICElement#getHandleIdentifier() - */ @Override public String getHandleIdentifier() { return getHandleMemento(); @@ -569,7 +553,7 @@ public abstract class CElement extends PlatformObject implements ICElement { * @param buff the buffer building the memento string */ public void getHandleMemento(StringBuilder buff) { - ((CElement)getParent()).getHandleMemento(buff); + ((CElement) getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, getElementName()); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java index 283652b41fe..87a8b947dd6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java @@ -82,8 +82,7 @@ public interface IIndex { * index.acquireReadLock(); * try { * .... - * } - * finally { + * } finally { * index.releaseReadLock(); * } * @@ -113,8 +112,7 @@ public interface IIndex { * try { * timestamp= index.getLastWriteAccess(); * binding= index.findBinding(...); - * } - * finally { + * } finally { * index.releaseReadLock(); * } * ... @@ -126,8 +124,7 @@ public interface IIndex { * } * String name= binding.getName(); * ... - * } - * finally { + * } finally { * index.releaseReadLock(); * } */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CPPTypedefClone.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CPPTypedefClone.java index 47d06d5b46a..4f3428d02ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CPPTypedefClone.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CPPTypedefClone.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Bryan Wilkinson (QNX) - Initial API and implementation + * Bryan Wilkinson (QNX) - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.core.index; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 0ca965e8261..03e07663c86 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -336,7 +336,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return null; if (binding instanceof ICPPSpecialization) { - IBinding specialized = ((ICPPSpecialization)binding).getSpecializedBinding(); + IBinding specialized = ((ICPPSpecialization) binding).getSpecializedBinding(); PDOMBinding pdomSpecialized= addBinding(specialized, null); if (pdomSpecialized == null) return null; @@ -371,11 +371,11 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } else if (binding instanceof ICPPConstructor) { if (parent instanceof PDOMCPPClassType || parent instanceof PDOMCPPClassSpecialization) { - pdomBinding = new PDOMCPPConstructor(this, parent, (ICPPConstructor)binding); + pdomBinding = new PDOMCPPConstructor(this, parent, (ICPPConstructor) binding); } } else if (binding instanceof ICPPMethod) { if (parent instanceof PDOMCPPClassType || parent instanceof PDOMCPPClassSpecialization) { - pdomBinding = new PDOMCPPMethod(this, parent, (ICPPMethod)binding); + pdomBinding = new PDOMCPPMethod(this, parent, (ICPPMethod) binding); } } else if (binding instanceof ICPPFunction) { pdomBinding = new PDOMCPPFunction(this, parent, (ICPPFunction) binding, true); @@ -397,7 +397,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } } else if (binding instanceof ITypedef) { - pdomBinding = new PDOMCPPTypedef(this, parent, (ITypedef)binding); + pdomBinding = new PDOMCPPTypedef(this, parent, (ITypedef) binding); } if (pdomBinding != null) { @@ -611,7 +611,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return adaptBinding(null, inputBinding, includeLocal ? FILE_LOCAL_REC_DUMMY : null); } - private final PDOMBinding adaptBinding(final PDOMNode parent, IBinding inputBinding, long[] fileLocalRecHolder) throws CoreException { + private final PDOMBinding adaptBinding(final PDOMNode parent, IBinding inputBinding, long[] fileLocalRecHolder) + throws CoreException { if (cannotAdapt(inputBinding)) { return null; } @@ -639,7 +640,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { final Long key = record + CACHE_BASES; PDOMCPPNamespace[] result= (PDOMCPPNamespace[]) getPDOM().getCachedResult(key); if (result == null) { - List nslist = PDOMCPPNamespace.collectInlineNamespaces(getDB(), getLinkage(), record+FIRST_NAMESPACE_CHILD_OFFSET); + List nslist = PDOMCPPNamespace.collectInlineNamespaces(getDB(), + getLinkage(), record + FIRST_NAMESPACE_CHILD_OFFSET); if (nslist == null) { result= new PDOMCPPNamespace[0]; } else { @@ -651,9 +653,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } /** - * Find the equivalent binding, or binding place holder within this PDOM + * Finds the equivalent binding, or binding placeholder within this PDOM. */ - private final PDOMBinding doAdaptBinding(PDOMNode parent, IBinding binding, long[] fileLocalRecHolder) throws CoreException { + private final PDOMBinding doAdaptBinding(PDOMNode parent, IBinding binding, long[] fileLocalRecHolder) + throws CoreException { if (parent == null) { parent= adaptOrAddParent(false, binding); } @@ -935,9 +938,6 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage#getUsingDirectives() - */ @Override public ICPPUsingDirective[] getUsingDirectives(PDOMFile file) throws CoreException { long rec= file.getLastUsingDirectiveRec(); @@ -1025,7 +1025,6 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { public PDOMBinding addTypeBinding(IBinding type) throws CoreException { return addBinding(type, null); } - @Override public IType unmarshalType(ITypeMarshalBuffer buffer) throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java index 888d4713d27..dc777af3e20 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Sergey Prigogin (Google) - initial API and implementation - * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -33,7 +33,6 @@ import org.eclipse.core.runtime.CoreException; * @see ICPPUsingDeclaration */ class PDOMCPPUsingDeclaration extends PDOMCPPBinding implements ICPPUsingDeclaration { - private static final int TARGET_BINDING = PDOMCPPBinding.RECORD_SIZE + 0; // Using declarations for functions may have multiple delegates. We model such case // by creating a chain of PDOMCPPUsingDeclaration objects linked by NEXT_DELEGATE field. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java index 2a305683c4f..953057620fc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn (Wind River Systems) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -67,7 +67,7 @@ class PDOMCPPUsingDeclarationSpecialization extends PDOMCPPSpecialization implem @Override public IBinding[] getDelegates() { if (delegates == null) { - PDOMNodeLinkedList list= new PDOMNodeLinkedList(getLinkage(), record+TARGET_BINDINGS); + PDOMNodeLinkedList list= new PDOMNodeLinkedList(getLinkage(), record+ TARGET_BINDINGS); final List result= new ArrayList(); try { list.accept(new IPDOMVisitor() { @@ -78,6 +78,7 @@ class PDOMCPPUsingDeclarationSpecialization extends PDOMCPPSpecialization implem } return true; } + @Override public void leave(IPDOMNode node) { } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RefactoringTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RefactoringTests.java index c49939ad739..9ce5fe8f045 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RefactoringTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RefactoringTests.java @@ -49,7 +49,7 @@ public class RefactoringTests extends BaseTestFramework { super.setUp(); CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER); fBufferSize= FileCharSequenceProvider.BUFFER_SIZE; - FileCharSequenceProvider.BUFFER_SIZE= 1024*4; + FileCharSequenceProvider.BUFFER_SIZE= 1024 * 4; } @Override @@ -65,7 +65,7 @@ public class RefactoringTests extends BaseTestFramework { protected void assertTotalChanges(int numChanges, int potChanges, int commentCh, Change changes) throws Exception { - int count[]= {0,0,0}; + int count[]= { 0, 0, 0 }; if (changes != null) { countChanges(changes, count); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameFunctionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameFunctionTests.java index 8d4fbaf1742..dbcadd68663 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameFunctionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameFunctionTests.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.ui.tests.refactoring.rename; @@ -21,12 +21,14 @@ import org.eclipse.ltk.core.refactoring.RefactoringStatus; public class RenameFunctionTests extends RenameTests { - public RenameFunctionTests(String name) { + public RenameFunctionTests(String name) { super(name); } + public static Test suite(){ return suite(true); } + public static Test suite( boolean cleanup ) { TestSuite suite = new TestSuite(RenameFunctionTests.class); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMacroTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMacroTests.java index dd5c7874575..8c2478c4e8b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMacroTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMacroTests.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.ui.tests.refactoring.rename; @@ -24,9 +24,11 @@ public class RenameMacroTests extends RenameTests { public RenameMacroTests(String name) { super(name); } + public static Test suite(){ return suite(true); } + public static Test suite( boolean cleanup ) { TestSuite suite = new TestSuite(RenameMacroTests.class); if (cleanup) { @@ -34,8 +36,7 @@ public class RenameMacroTests extends RenameTests { } return suite; } - - + public void testMacroRename() throws Exception { StringWriter writer = new StringWriter(); writer.write("#define HALLO x \n"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java index 326072ac480..1adde370a20 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java @@ -6,9 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ - package org.eclipse.cdt.ui.tests.refactoring.rename; import java.io.StringWriter; @@ -28,9 +27,11 @@ public class RenameTemplatesTests extends RenameTests { public RenameTemplatesTests(String name) { super(name); } + public static Test suite(){ return suite(true); } + public static Test suite( boolean cleanup ) { TestSuite suite = new TestSuite(RenameTemplatesTests.class); if (cleanup) { @@ -39,7 +40,6 @@ public class RenameTemplatesTests extends RenameTests { return suite; } - public void testClassTemplate() throws Exception { StringWriter writer = new StringWriter(); writer.write("template \n"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTests.java index 978507cb480..93c3c673ff7 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTests.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.ui.tests.refactoring.rename; @@ -31,7 +31,6 @@ import org.eclipse.cdt.internal.ui.refactoring.rename.TextSearchWrapper; * @author markus.schorn@windriver.com */ public class RenameTests extends RefactoringTests { - private static final IProgressMonitor NPM = new NullProgressMonitor(); public RenameTests(String name) { @@ -58,7 +57,7 @@ public class RenameTests extends RefactoringTests { return change; } - fail ("Input check on "+ newName + " failed. "+rs.getEntryMatchingSeverity(RefactoringStatus.ERROR) ); //$NON-NLS-1$ //$NON-NLS-2$ + fail ("Input check on " + newName + " failed. "+rs.getEntryMatchingSeverity(RefactoringStatus.ERROR) ); //$NON-NLS-1$ //$NON-NLS-2$ //rs.getFirstMessage(RefactoringStatus.ERROR) is not the message displayed in //the UI for renaming a method to a constructor, the first message which is only //a warning is shown in the UI. If you click preview, then the error and the warning @@ -153,8 +152,7 @@ public class RenameTests extends RefactoringTests { } @Override - protected IFile importFile(String fileName, String contents) - throws Exception { + protected IFile importFile(String fileName, String contents) throws Exception { IFile result= super.importFile(fileName, contents); waitForIndexer(); return result; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java index ed5621fdd6f..bc6464046c5 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java @@ -6,9 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ - package org.eclipse.cdt.ui.tests.refactoring.rename; import java.io.StringWriter; @@ -38,8 +37,7 @@ public class RenameTypeTests extends RenameTests { } return suite; } - - + public void testClassNameConflicts() throws Exception { createCppFwdDecls("cpp_fwd.hh"); //$NON-NLS-1$ createCppDefs("cpp_def.hh"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameVariableTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameVariableTests.java index ff65483d6f9..6ef0899cd2a 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameVariableTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameVariableTests.java @@ -6,9 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ - package org.eclipse.cdt.ui.tests.refactoring.rename; import java.io.StringWriter; @@ -28,9 +27,11 @@ public class RenameVariableTests extends RenameTests { public RenameVariableTests(String name) { super(name); } + public static Test suite(){ return suite(true); } + public static Test suite( boolean cleanup ) { TestSuite suite = new TestSuite(RenameVariableTests.class); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/TestRenameParticipant.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/TestRenameParticipant.java index 09c972267d0..5ad7cfecb86 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/TestRenameParticipant.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/TestRenameParticipant.java @@ -6,20 +6,24 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation ******************************************************************************/ - package org.eclipse.cdt.ui.tests.refactoring.rename; -import org.eclipse.core.runtime.*; -import org.eclipse.ltk.core.refactoring.*; -import org.eclipse.ltk.core.refactoring.participants.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +import org.eclipse.ltk.core.refactoring.participants.RenameArguments; +import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; public class TestRenameParticipant extends RenameParticipant { - private static Object sElement= null; - private static RenameArguments sArguments= null; - private static int sConditionCheck= 0; - private static int sCreateChange= 0; + private static Object sElement; + private static RenameArguments sArguments; + private static int sConditionCheck; + private static int sCreateChange; public static int getConditionCheckCount() { return sConditionCheck; @@ -40,7 +44,8 @@ public class TestRenameParticipant extends RenameParticipant { public static void reset() { sElement= null; sArguments= null; - sConditionCheck= sCreateChange= 0; + sConditionCheck= 0; + sCreateChange= 0; } @Override diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactoringMatch.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactoringMatch.java index 63cc8decf52..96690fba923 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactoringMatch.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactoringMatch.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; @@ -63,7 +63,7 @@ public class CRefactoringMatch { return fFile; } public void setASTInformation(int val) { - switch(fAstInformation) { + switch (fAstInformation) { case AST_REFERENCE: case AST_REFERENCE_OTHER: case AST_REFEREENCE_CONFLICTING: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java index 222d6de2ba5..07a56aa5bc8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; @@ -20,7 +20,6 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; - /** * Processor adding constructor and destructor to the bindings to be renamed. */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameTypeProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameTypeProcessor.java index 97c094a4590..99fb91fd273 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameTypeProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameTypeProcessor.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; From c7be1163514fee663d90df4ff3b6a37a8c1968fa Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 24 Apr 2012 18:24:05 -0700 Subject: [PATCH 09/14] Bug 332895 - Rename does not change using-declarations --- .../refactoring/rename/RenameTypeTests.java | 84 ++++++++++++------- .../ui/refactoring/rename/ASTManager.java | 36 +++++--- 2 files changed, 76 insertions(+), 44 deletions(-) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java index bc6464046c5..cefa810daeb 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTypeTests.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 Wind River Systems, Inc. + * Copyright (c) 2005, 2012 Wind River Systems, Inc. * 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: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.ui.tests.refactoring.rename; @@ -27,13 +28,15 @@ public class RenameTypeTests extends RenameTests { public RenameTypeTests(String name) { super(name); } - public static Test suite(){ + + public static Test suite() { return suite(true); } - public static Test suite( boolean cleanup ) { + + public static Test suite(boolean cleanup) { TestSuite suite = new TestSuite(RenameTypeTests.class); if (cleanup) { - suite.addTest( new RefactoringTests("cleanupProject") ); //$NON-NLS-1$ + suite.addTest(new RefactoringTests("cleanupProject")); //$NON-NLS-1$ } return suite; } @@ -73,7 +76,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -415,7 +418,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -753,7 +756,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -1077,7 +1080,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ @@ -1174,7 +1177,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -1491,7 +1494,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" int w1; vv1.v++; \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.c", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.c", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ @@ -1578,7 +1581,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" int w3; v3 v; \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -1835,7 +1838,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" int w1; enum v1 v; \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.c", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.c", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ @@ -1923,7 +1926,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" } \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ int offset2= contents.indexOf("v2"); //$NON-NLS-1$ @@ -2174,7 +2177,7 @@ public class RenameTypeTests extends RenameTests { writer.write(" int w1; v1 v; \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.c", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.c", contents); //$NON-NLS-1$ int offset1= contents.indexOf("v1"); //$NON-NLS-1$ @@ -2246,7 +2249,7 @@ public class RenameTypeTests extends RenameTests { status= checkConditions(cpp, offset1, "un_member"); //$NON-NLS-1$ assertRefactoringOk(status); } - + public void testRenameClass() throws Exception { StringWriter writer = new StringWriter(); writer.write("class String \n"); //$NON-NLS-1$ @@ -2255,42 +2258,61 @@ public class RenameTypeTests extends RenameTests { writer.write(" String(); \n"); //$NON-NLS-1$ writer.write(" String(const String &other); \n"); //$NON-NLS-1$ writer.write(" ~String(); \n"); //$NON-NLS-1$ - writer.write(" String &operator=( const String &other ); \n"); //$NON-NLS-1$ + writer.write(" String &operator=(const String &other); \n"); //$NON-NLS-1$ writer.write("}; \n"); //$NON-NLS-1$ - writer.write(" String::String(){} \n"); //$NON-NLS-1$ - writer.write(" String::String(const String &other){}; \n"); //$NON-NLS-1$ - writer.write(" String::~String(){}; \n"); //$NON-NLS-1$ - writer.write(" String& String::operator=( const String &other ) \n"); //$NON-NLS-1$ - writer.write(" {return *this;} \n"); //$NON-NLS-1$ + writer.write(" String::String() {} \n"); //$NON-NLS-1$ + writer.write(" String::String(const String &other) {}; \n"); //$NON-NLS-1$ + writer.write(" String::~String() {}; \n"); //$NON-NLS-1$ + writer.write(" String& String::operator=(const String &other) \n"); //$NON-NLS-1$ + writer.write(" {return *this;} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ - int offset1= contents.indexOf("String"); //$NON-NLS-1$ + int offset= contents.indexOf("String"); //$NON-NLS-1$ // conflicting renamings - RefactoringStatus status= checkConditions(cpp, offset1, "CString"); //$NON-NLS-1$ + RefactoringStatus status= checkConditions(cpp, offset, "CString"); //$NON-NLS-1$ assertRefactoringOk(status); - Change ch= getRefactorChanges(cpp, offset1, "CString"); //$NON-NLS-1$ + Change ch= getRefactorChanges(cpp, offset, "CString"); //$NON-NLS-1$ assertTotalChanges(countOccurrences(contents, "String"), ch); //$NON-NLS-1$ } - + + public void testUsingDeclaration_332895() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("namespace ns { \n"); //$NON-NLS-1$ + writer.write("typedef int MyType; \n"); //$NON-NLS-1$ + writer.write("} \n"); //$NON-NLS-1$ + writer.write(" \n"); //$NON-NLS-1$ + writer.write("using ns::MyType; \n"); //$NON-NLS-1$ + writer.write("MyType a; \n"); //$NON-NLS-1$ + String contents = writer.toString(); + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ + + int offset= contents.indexOf("MyType"); //$NON-NLS-1$ + + RefactoringStatus status= checkConditions(cpp, offset, "YourType"); //$NON-NLS-1$ + assertRefactoringOk(status); + Change ch= getRefactorChanges(cpp, offset, "YourType"); //$NON-NLS-1$ + assertTotalChanges(countOccurrences(contents, "MyType"), ch); //$NON-NLS-1$ + } + public void testBug72888() throws Exception { StringWriter writer = new StringWriter(); writer.write("class MyEx {}; \n"); //$NON-NLS-1$ writer.write("void someFunc() { \n"); //$NON-NLS-1$ - writer.write(" throw MyEx(); \n"); //$NON-NLS-1$ + writer.write(" throw MyEx(); \n"); //$NON-NLS-1$ writer.write("}; \n"); //$NON-NLS-1$ writer.write("int main(){ \n"); //$NON-NLS-1$ - writer.write(" try{ \n"); //$NON-NLS-1$ + writer.write(" try { \n"); //$NON-NLS-1$ writer.write(" someFunc(); \n"); //$NON-NLS-1$ writer.write(" } catch(MyEx &e) {} \n"); //$NON-NLS-1$ writer.write(" return 0; \n"); //$NON-NLS-1$ writer.write("} \n"); //$NON-NLS-1$ String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ + IFile cpp= importFile("test.cpp", contents); //$NON-NLS-1$ int offset = contents.indexOf("MyEx") ; //$NON-NLS-1$ Change changes = getRefactorChanges(cpp, offset, "xx"); //$NON-NLS-1$ - assertTotalChanges( 3, changes ); + assertTotalChanges(3, changes); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java index 6d1da8aa5b6..4b9e55372c6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2005, 2012 Wind River Systems, Inc. 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 @@ -97,6 +97,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexName; @@ -1208,18 +1209,27 @@ public class ASTManager implements IDisposable { } else { final IASTTranslationUnit tu = name.getTranslationUnit(); final IIndex index= tu != null ? tu.getIndex() : null; - for (IBinding renameBinding : fValidBindings) { - try { - int cmp0= isSameBinding(index, binding, renameBinding); - if (cmp0 != FALSE) { - cmp= cmp0; - } - if (cmp0 == TRUE) { - break; - } - } catch (DOMException e) { - handleDOMException(name.getTranslationUnit(), e, status); - cmp= UNKNOWN; + IBinding[] bindings = binding instanceof ICPPUsingDeclaration ? + ((ICPPUsingDeclaration) binding).getDelegates() : new IBinding[] { binding }; + // When a 'using' declaration has multiple delegate bindings and only some of them + // are being renamed, to preserve correctness of the code we would have to split + // the 'using' declaration into two separate ones. We currently don't do that and + // rename the 'using' declaration if at least one of its delegate bindings is being + // renamed. + outer: for (IBinding b : bindings) { + for (IBinding renameBinding : fValidBindings) { + try { + int cmp0= isSameBinding(index, b, renameBinding); + if (cmp0 != FALSE) { + cmp= cmp0; + } + if (cmp0 == TRUE) { + break outer; + } + } catch (DOMException e) { + handleDOMException(name.getTranslationUnit(), e, status); + cmp= UNKNOWN; + } } } } From efe3dd4be6ab048411a623112dcae093d78fd329 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 24 Apr 2012 22:58:22 -0400 Subject: [PATCH 10/14] Bug 330974: If the user selects multiple nodes in the debug view most debug commands are disabled Change-Id: I51d15347fd28ee550e9bd2b75c61e904e75b4c8b Reviewed-on: https://git.eclipse.org/r/5650 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../dsf/gdb/service/GDBRunControl_7_0_NS.java | 299 +- .../dsf/gdb/service/GDBRunControl_7_2_NS.java | 4 +- .../data/launch/src/MultiThreadRunControl.cc | 76 + .../dsf/gdb/framework/ServiceEventWaitor.java | 29 +- .../cdt/tests/dsf/gdb/framework/SyncUtil.java | 23 +- .../GDBMultiNonStopRunControlTest_7_0.java | 4022 +++++++++++++++++ .../dsf/gdb/tests/tests_7_0/Suite_7_0.java | 1 + .../gdb/tests/tests_7_0/Suite_Remote_7_0.java | 1 + .../GDBMultiNonStopRunControlTest_7_1.java | 30 + .../dsf/gdb/tests/tests_7_1/Suite_7_1.java | 1 + .../gdb/tests/tests_7_1/Suite_Remote_7_1.java | 1 + .../GDBMultiNonStopRunControlTest_7_2.java | 30 + .../dsf/gdb/tests/tests_7_2/Suite_7_2.java | 1 + .../gdb/tests/tests_7_2/Suite_Remote_7_2.java | 1 + .../GDBMultiNonStopRunControlTest_7_3.java | 30 + .../dsf/gdb/tests/tests_7_3/Suite_7_3.java | 1 + .../gdb/tests/tests_7_3/Suite_Remote_7_3.java | 1 + .../GDBMultiNonStopRunControlTest_7_4.java | 30 + .../dsf/gdb/tests/tests_7_4/Suite_7_4.java | 1 + .../gdb/tests/tests_7_4/Suite_Remote_7_4.java | 1 + .../debug/ui/actions/DsfCommandRunnable.java | 61 +- .../debug/ui/actions/DsfResumeCommand.java | 66 +- .../debug/ui/actions/DsfSuspendCommand.java | 68 +- .../dsf/debug/service/IMultiRunControl.java | 134 + 24 files changed, 4844 insertions(+), 68 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java create mode 100644 dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 60eb549a3e8..d8eb3adaac6 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -9,14 +9,18 @@ * Wind River Systems - initial API and implementation * Ericsson AB - Modified for handling of multiple threads * Indel AG - [369622] fixed moveToLine using MinGW + * Marc Khouzam (Ericsson) - Support for operations on multiple execution contexts (bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -42,6 +46,7 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent; import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; @@ -104,7 +109,7 @@ import org.osgi.framework.BundleContext; * sync with the service state. * @since 1.1 */ -public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService +public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, IMultiRunControl, ICachingService { @Immutable private static class ExecutionData implements IExecutionDMData2 { @@ -396,7 +401,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo private void doInitialize(final RequestMonitor rm) { register(new String[]{ IRunControl.class.getName(), IRunControl2.class.getName(), - IMIRunControl.class.getName()}, + IMIRunControl.class.getName(), + IMultiRunControl.class.getName() }, new Hashtable()); fConnection = getServicesTracker().getService(ICommandControlService.class); fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); @@ -1878,4 +1884,293 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo } return result; } + + /////////////////////////////////////////////////////////////////////////// + // IMultiRunControl implementation + /////////////////////////////////////////////////////////////////////////// + + // Although multi-process in only supported for GDB >= 7.2, it is simpler + // to code for the multi-process case all the time, since it is a superset + // of the single-process case. + + /////////////////////////////////////////////////////////////////////////// + // Multi-resume implementation: + // + // If one or more more threads of one or many processes are selected, we want to + // resume each thread (once). + // + // If one or more more processes are selected, we want to resume each process (once). + // + // If a process is selected along with one or more threads of that same process, + // what does the user want us to do? Selecting the process will resume all its + // threads, but what do we do with the selected threads? Why are they + // selected? In an attempt to be user friendly, lets assume that the user + // wants to resume the entire process, so we ignore the selected threads part of that + // process since they will be resumed anyway. + // + // The same logic applies to multi-suspend. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToResumeList = extractContextsForOperation(contexts); + + // If any of the threads or processes can be resumed, we allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (doCanResume(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that could be resumed. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToResumeList = extractContextsForOperation(contexts); + + // If any of the threads or processes cannot be resumed, we don't allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (!doCanResume(execDmc)) { + rm.done(false); + return; + } + } + + // Everything can be resumed + rm.done(true); + } + + /** + * {@inheritDoc} + * + * For GDB, a separate resume command will be sent, one for each context + * that can be resumed. + * @since 4.1 + */ + @Override + public void resume(IExecutionDMContext[] contexts, RequestMonitor rm) { + assert contexts != null; + + List execDmcToResumeList = extractContextsForOperation(contexts); + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + int count = 0; + + // Perform resume operation on each thread or process that can be resumed + for (IExecutionDMContext execDmc : execDmcToResumeList) { + if (doCanResume(execDmc)) { + count++; + resume(execDmc, crm); + } + } + + crm.setDoneCount(count); + } + + /////////////////////////////////////////////////////////////////////////// + // Multi-suspend implementation: + // see details of the multi-resume implementation above. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + // If any of the threads or processes can be suspended, we allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (doCanSuspend(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that could be suspended. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + if (fRunControlOperationsEnabled == false) { + rm.done(false); + return; + } + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + // If any of the threads or processes cannot be suspended, we don't allow + // the user to perform the operation. + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (!doCanSuspend(execDmc)) { + rm.done(false); + return; + } + } + + // Everything can be suspended + rm.done(true); + } + + /** @since 4.1 */ + @Override + public void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + List execDmcSuspendedList = extractContextsForOperation(contexts); + + // Look for any thread or process that is suspended + for (IExecutionDMContext execDmc : execDmcSuspendedList) { + if (isSuspended(execDmc)) { + rm.done(true); + return; + } + } + + // Didn't find anything that was suspended. + rm.done(false); + } + + /** @since 4.1 */ + @Override + public void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + assert contexts != null; + + List execDmcSuspendedList = extractContextsForOperation(contexts); + + // Look for any thread or process that is not suspended + for (IExecutionDMContext execDmc : execDmcSuspendedList) { + if (!isSuspended(execDmc)) { + rm.done(false); + return; + } + } + + // Everything is suspended. + rm.done(true); + } + + /** + * {@inheritDoc} + * + * For GDB, a separate suspend command will be sent, one for each context + * that can be suspended. + * @since 4.1 + */ + @Override + public void suspend(IExecutionDMContext[] contexts, RequestMonitor rm) { + assert contexts != null; + + List execDmcToSuspendList = extractContextsForOperation(contexts); + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + int count = 0; + + // Perform resume operation on each thread or process that can be resumed + for (IExecutionDMContext execDmc : execDmcToSuspendList) { + if (doCanSuspend(execDmc)) { + count++; + suspend(execDmc, crm); + } + } + + crm.setDoneCount(count); + } + + /////////////////////////////////////////////////////////////////////////// + // Multi-step implementation. Not implemented yet. See bug 330974. + /////////////////////////////////////////////////////////////////////////// + + /** @since 4.1 */ + @Override + public void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** @since 4.1 */ + @Override + public void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$ + } + + /** + * Removes duplicates from the list of execution contexts, in case the same thread + * or process is present more than once. + * + * Also, remove any thread that is part of a process that is also present. This is + * because an operation on the process will affect all its threads anyway. + */ + private List extractContextsForOperation(IExecutionDMContext[] contexts) { + // Remove duplicate contexts by using a set + Set specifiedExedDmcSet = new HashSet(Arrays.asList(contexts)); + + // A list that ignores threads for which the process is also present + List execDmcForOperationList = new ArrayList(specifiedExedDmcSet.size()); + + // Check for the case of a process selected along with some of its threads + for (IExecutionDMContext execDmc : specifiedExedDmcSet) { + if (execDmc instanceof IContainerDMContext) { + // This is a process: it is automatically part of our list + execDmcForOperationList.add(execDmc); + } else { + // Get the process for this thread + IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class); + // Check if that process is also present + if (specifiedExedDmcSet.contains(containerDmc) == false) { + // This thread does not belong to a process that is selected, so we keep it. + execDmcForOperationList.add(execDmc); + } + } + } + return execDmcForOperationList; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java index 97d14197095..faabbe0d4b2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Ericsson and others. + * Copyright (c) 2011, 2012 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 @@ -18,6 +18,7 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl2; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; @@ -72,6 +73,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS register(new String[]{ IRunControl.class.getName(), IRunControl2.class.getName(), IMIRunControl.class.getName(), + IMultiRunControl.class.getName(), GDBRunControl_7_0_NS.class.getName(), GDBRunControl_7_2_NS.class.getName(), }, diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc new file mode 100644 index 00000000000..f30714744ea --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThreadRunControl.cc @@ -0,0 +1,76 @@ +#ifdef __MINGW32__ + #include // MinGW has no POSIX support; use MSVC runtime +#else + #include +#endif +#include +#include +#include "Sleep.h" + +#ifdef __MINGW32__ +typedef unsigned int TID; +#else +typedef pthread_t TID; +#endif + +// Set a breakpoint here so that both threads stop. +void firstBreakpoint(int id) +{ + printf("First breakpoint method from thread %d\n", id); +} + + +#ifdef __MINGW32__ +unsigned int __stdcall PrintHello(void *threadid) +#else +void *PrintHello(void *threadId) +#endif +{ + int tId = (int)threadId; + firstBreakpoint(tId); // Stop a first time + + SLEEP(1); // Keep state running a little + + firstBreakpoint(tId); // Stop a second time + + SLEEP(3); // Resuming past this will give us a running thread + +#ifdef __MINGW32__ + return 0; +#else + pthread_exit(NULL); +#endif +} + + +int main(int argc, char *argv[]) +{ + TID thread; + int tId = 1; // Break at main will stop here: we have a single thread stopped + + SLEEP(1); // When resuming past here, we have a single thread running + +#ifdef __MINGW32__ + uintptr_t rc = _beginthreadex(NULL, 0, PrintHello, (void*)tId, 0, &thread); + if (rc == 0) + { + printf("ERROR; _beginthreadex() failed. errno = %d\n", errno); + exit(-1); + } +#else + int rc = pthread_create(&thread, NULL, PrintHello, (void *)tId); + if (rc) + { + printf("ERROR; return code from pthread_create() is %d\n", rc); + exit(-1); + } +#endif + + firstBreakpoint(0); + + SLEEP(1); // Resuming past this will make this thread run, while we stop the second thread + + SLEEP(3); // Resuming past this will make this thread run, while we also run the second thread + + return 0; +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java index 379679aadba..be375f9c9c1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Ericsson and others. + * Copyright (c) 2007, 2012 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,9 +7,13 @@ * * Contributors: * Ericsson - Initial Implementation + * Marc Khouzam (Ericsson) - Add support to receive multiple events *******************************************************************************/ package org.eclipse.cdt.tests.dsf.gdb.framework; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.ExecutionException; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; @@ -17,7 +21,7 @@ import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; import org.eclipse.core.runtime.Platform; -/* +/** * This class provides a way to wait for an asynchronous ServerEvent * to occur. The user of this class specifies which event is of * interest . waitForEvent() can then be called to block until the event occurs or @@ -40,7 +44,9 @@ public class ServiceEventWaitor { /* The type of event to wait for */ private Class fEventTypeClass; private DsfSession fSession; - private V fEvent; + + // Queue of events. This allows to receive multiple events and keep them. + private List fEventQueue = Collections.synchronizedList(new LinkedList()); /** * Trace option for wait metrics @@ -59,7 +65,6 @@ public class ServiceEventWaitor { assert eventClass != null; fSession = session; fEventTypeClass = eventClass; - fEvent = null; Runnable runnable = new Runnable() { @Override public void run() { @@ -102,10 +107,9 @@ public class ServiceEventWaitor { long startMs = System.currentTimeMillis(); - // The event might have already been received - if (fEvent == null) { + if (fEventQueue.isEmpty()) { wait(timeout); - if (fEvent == null) { + if (fEventQueue.isEmpty()) { throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName()); } } @@ -159,14 +163,7 @@ public class ServiceEventWaitor { } } - // Mark that we have consumed the event. - // This will allow to wait for the next similar event. - // For example, for a restart, there could be more than one - // stopped event, and we need to wait for the second one. - V event = fEvent; - fEvent = null; - - return event; + return fEventQueue.remove(0); } /* @@ -177,7 +174,7 @@ public class ServiceEventWaitor { public void eventDispatched(V event) { if (fEventTypeClass.isAssignableFrom(event.getClass())) { synchronized(this) { - fEvent = event; + fEventQueue.add(event); notifyAll(); } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java index e7173ceb179..fb078685198 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java @@ -593,17 +593,17 @@ public class SyncUtil { } /** - * Utility method to return the execution DM context. + * Utility method to return all thread execution contexts. */ @ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()") - public static IMIExecutionDMContext getExecutionContext(final int threadIndex) throws InterruptedException { + public static IMIExecutionDMContext[] getExecutionContexts() throws InterruptedException { assert !fProcessesService.getExecutor().isInExecutorThread(); final IContainerDMContext containerDmc = SyncUtil.getContainerContext(); - Query query = new Query() { + Query query = new Query() { @Override - protected void execute(final DataRequestMonitor rm) { + protected void execute(final DataRequestMonitor rm) { fProcessesService.getProcessesBeingDebugged( containerDmc, new ImmediateDataRequestMonitor() { @@ -612,10 +612,7 @@ public class SyncUtil { if (isSuccess()) { IDMContext[] threads = getData(); Assert.assertNotNull("invalid return value from service", threads); - Assert.assertTrue("unexpected number of threads", threadIndex < threads.length); - IDMContext thread = threads[threadIndex]; - Assert.assertNotNull("unexpected thread context type ", thread); - rm.setData((IMIExecutionDMContext)thread); + rm.setData((IMIExecutionDMContext[])threads); } else { rm.setStatus(getStatus()); } @@ -633,6 +630,16 @@ public class SyncUtil { } return null; } + /** + * Utility method to return a specific execution DM context. + */ + @ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()") + public static IMIExecutionDMContext getExecutionContext(int threadIndex) throws InterruptedException { + IMIExecutionDMContext[] threads = getExecutionContexts(); + Assert.assertTrue("unexpected number of threads", threadIndex < threads.length); + Assert.assertNotNull("unexpected thread context type ", threads[threadIndex]); + return threads[threadIndex]; + } /** * Check if the restart operation is supported diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java new file mode 100644 index 00000000000..466aa3c776b --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java @@ -0,0 +1,4022 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +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.IMultiRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; +import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; +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.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.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_0 extends BaseTestCase { + + private DsfServicesTracker fServicesTracker; + + private IMultiRunControl fMultiRun; + + /* + * Path to executable + */ + private static final String EXEC_PATH = "data/launch/bin/"; + /* + * Name of the executable + */ + private static final String EXEC_NAME = "MultiThreadRunControl.exe"; + + @Before + public void init() throws Exception { + final DsfSession session = getGDBLaunch().getSession(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + fServicesTracker = + new DsfServicesTracker(TestsPlugin.getBundleContext(), + session.getId()); + fMultiRun = fServicesTracker.getService(IMultiRunControl.class); + } + }; + session.getExecutor().submit(runnable).get(); + } + + + @After + public void tearDown() { + fServicesTracker.dispose(); + } + + @BeforeClass + public static void beforeClassMethod() { + setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, + EXEC_PATH + EXEC_NAME); + + // Multi run control only makes sense for non-stop mode + setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, true); + } + + private abstract class AsyncRunnable { + public abstract void run(DataRequestMonitor drm); + }; + + private V runAsyncCall(final AsyncRunnable runnable) { + return runAsyncCall(runnable, false); + } + + private V runAsyncCall(final AsyncRunnable runnable, boolean expectExecutionException) { + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + runnable.run(rm); + } + }; + + V result = null; + try { + fMultiRun.getExecutor().execute(query); + result = query.get(500, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + fail(e.getMessage()); + } catch (ExecutionException e) { + if (expectExecutionException) { + return null; + } + fail(e.getCause().getMessage()); + } catch (TimeoutException e) { + fail(e.getMessage()); + } + + if (expectExecutionException) { + fail("Didn't get the expected execution exception"); + } + + return result; + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with one thread which is stopped. + */ + @Test + public void testStateOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with one thread which is running. + */ + @Test + public void testStateOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads which are both stopped. + */ + @Test + public void testStateTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads, one of which is stopped and the other running. + */ + @Test + public void testStateTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected to not be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that not all threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * with two threads which are both running. + */ + @Test + public void testStateTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(threads, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(threads, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(threads, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(threads, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(threads, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(threads, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the resume operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + */ + @Test + public void testResumeOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with one thread which is running. + */ + @Test + public void testResumeOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + */ + @Test + public void testResumeTwoThreadsStoppedResumeOne() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads[0], drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + + // Also confirm that only one threads is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected some threads to be suspended, but found none", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected not to find all threads suspended, but did", result); + + // Make sure no other running event arrives + try { + eventWaitorRunning.waitForEvent(500); + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two stopped threads. Both threads + * are resumed. + */ + @Test + public void testResumeTwoThreadsStoppedResumeTwo() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation first thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation second thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testResumeTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + */ + @Test + public void testResumeTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(threads, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + */ + @Test + public void testSuspendOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with one thread which is running. + */ + @Test + public void testSuspendOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + */ + @Test + public void testSuspendTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testSuspendTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Only one + * thread will be suspended. + */ + @Test + public void testSuspendTwoThreadsRunningSuspendOne() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads[0], drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + + // Also confirm that some but not all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(threads, drm); + } + }); + assertTrue("expected some threads to be suspended, but found none", result); + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertFalse("expected that not all threads are suspended, but they are", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no other stopped event arrives + fail("Got an unexpected stopped event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * will be suspended + */ + @Test + public void testSuspendTwoThreadsRunningSuspendTwo() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(threads, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all threads are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + */ + @Test + public void testStepNotImplemented() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(threads, type, drm); + } + }, true /* Not implemented yet*/); + } + + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process. + // This should be done with multi-process but we are not quite setup for it. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is stopped. + */ + @Test + public void testStateProcessOneThreadStopped() throws Throwable { + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected to find all processes suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is running. + */ + @Test + public void testStateProcessOneThreadRunning() throws Throwable { + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + */ + @Test + public void testStateProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + */ + @Test + public void testStateProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but can't", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + */ + @Test + public void testStateProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IContainerDMContext[] processes = + new IContainerDMContext[] { SyncUtil.getContainerContext() }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(processes, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(processes, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(processes, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(processes, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(processes, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(processes, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process and a thread. + // Because the thread is part of the process, it should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is stopped. + * We also select the thread. + */ + @Test + public void testStateProcessThreadOneThreadStopped() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all processes suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but cannot", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with one thread which is running. + * We also select the thread. + */ + @Test + public void testStateProcessThreadOneThreadRunning() throws Throwable { + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + // Resume the program to check thread while it is running + SyncUtil.resume(); + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no thread suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to not be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + * We also select the thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = + new IExecutionDMContext[] { SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select the first thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select the second thread. + */ + @Test + public void testStateProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + * We also select both threads + */ + @Test + public void testStateProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the run-state of the process and both threads. + // Because the threads are part of the process, they should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both stopped. + * We also select both threads. + */ + @Test + public void testStateProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to suspend some, but can", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected to find all threads suspended but didn't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some threads suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step all, but can't", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no thread stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads, one of which is stopped and the other running. + * We also select both threads. + */ + @Test + public void testStateProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to resume some, but cannot", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended but they are not", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertTrue("expected to find some processes suspended but didn't", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertTrue("expected to be able to step some, but can't", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + /** + * Test canResume*, canSuspend*, isSuspended*, canStep*, isStepping* + * on the process with two threads which are both running. + * We also select both threads + */ + @Test + public void testStateProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 2); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), threads[0], threads[1] }; + + Boolean result; + + // canResume calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeAll(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canResumeSome(execDmcs, drm); + } + }); + assertFalse("expected not to be able to resume some, but can", result); + + // canSuspend calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendAll(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend all, but cannot", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canSuspendSome(execDmcs, drm); + } + }); + assertTrue("expected to be able to suspend some, but cannot", result); + + // isSuspended calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertFalse("expected that no threads are suspended but they are", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected to find no threads suspended but did", result); + + // canStep calls + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepAll(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step all, but can", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.canStepSome(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected not to be able to step some, but can", result); + } + + // isStepping calls + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingAll(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSteppingSome(execDmcs, drm); + } + }, true /* Not implemented yet*/); + // assertFalse("expected to find no process stepping but did", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the multi resume operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + */ + @Test + public void testResumeProcessOneThreadStopped() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation process resumed + + // Also confirm that process is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with one thread which is running. + */ + @Test + public void testResumeProcessOneThreadRunning() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + // No error should be thrown, the call should ignore running processes + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + */ + @Test + public void testResumeProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testResumeProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + */ + @Test + public void testResumeProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(processes, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + */ + @Test + public void testSuspendProcessOneThreadStopped() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended processes should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); +} + + /** + * Test suspend of multiple contexts with one thread which is running. + */ + @Test + public void testSuspendProcessOneThreadRunning() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(processes, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + */ + @Test + public void testSuspendProcessTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + */ + @Test + public void testSuspendProcessTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + */ + @Test + public void testSuspendProcessTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(processes, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(processes, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + */ + @Test + public void testStepProcessNotImplemented() throws Throwable { + final IExecutionDMContext[] processes = new IExecutionDMContext[] { + SyncUtil.getContainerContext() }; + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(processes, type, drm); + } + }, true /* Not implemented yet*/); + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the different operations on the process and a thread. + // Because the thread is part of the process, it should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with one thread which is stopped. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadOneThreadStopped() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // Wait for confirmation process resumed + + // Also confirm that process is running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with one thread which is running. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadOneThreadRunning() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running processes + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Confirm that all threads are still running + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no contexts to be suspended, but found some", result); + + try { + eventWaitor.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the second thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + * We select the process and the first thread. + */ + @Test + public void testResumeProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with one thread which is stopped. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadOneThreadStopped() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected a single thread but got " + threads.length, threads.length == 1); + + // No error should be thrown, the already suspended processes should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all threads are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with one thread which is running. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadOneThreadRunning() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + // Resume the program to get thread running + SyncUtil.resume(); + + // Confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // Thread should interrupt + + // Confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two stopped threads. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStoppedAndRunning_1() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and the second thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsStoppedAndRunning_2() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the step operation on multiple threads + ////////////////////////////////////////////////////////////////////// + + /** + * Test that the feature is not implemented. Once this fails, we will + * know we have new tests to write to test the feature. + * We select the process and the first thread. + */ + @Test + public void testStepProcessThreadNotImplemented() throws Throwable { + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0) }; + + for (final IRunControl.StepType type : IRunControl.StepType.values()) { + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.step(execDmcs, type, drm); + } + }, true /* Not implemented yet*/); + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the different operations on the process and both threads. + // Because the threads are part of the process, they should be ignored, + // and the results should be as if only the process was selected. + ////////////////////////////////////////////////////////////////////// + + /** + * Test resume of multiple contexts with two stopped threads. Only one thread + * is resumed. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that one thread resumed + eventWaitorRunning.waitForEvent(100); // Wait for confirmation that second thread resumed + + // Also confirm that all processes are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + eventWaitorRunning.waitForEvent(100); // Wait for confirmation one thread resumed + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no process to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no other running event arrives + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + /** + * Test resume of multiple contexts with two running threads. + * We select the process and both threads. + */ + @Test + public void testResumeProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final ServiceEventWaitor eventWaitorRunning = + new ServiceEventWaitor(fMultiRun.getSession(), MIRunningEvent.class); + + // No error should be thrown, the call should ignore running threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.resume(execDmcs, drm); + } + }); + + // Also confirm that all threads are running + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedSome(execDmcs, drm); + } + }); + assertFalse("expected no threads to be suspended, but found some", result); + + try { + eventWaitorRunning.waitForEvent(500); // Make sure no running events arrive + fail("Got an unexpected running event"); + } catch (Exception e) { + // Timeout expected. Success. + } + } + + ////////////////////////////////////////////////////////////////////// + // Tests for verifying the suspend operation on processes + ////////////////////////////////////////////////////////////////////// + + /** + * Test suspend of multiple contexts with two stopped threads. + * We select the process and both threads. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsStopped() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the already suspended threads should be ignored + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + // Also confirm that all processes are still suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are still suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two threads, one which is stopped + * while the other is running. + * We select the process and both threads. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsStoppedAndRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitorStopped = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + eventWaitorStopped.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitorStopped.waitForEvent(2000); // Wait for first thread to stop + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + // No error should be thrown, the call should ignore the suspended threads + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitorStopped.waitForEvent(100); // Wait for confirmation one thread stopped + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected all processes to be suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected all threads to be suspended, but they are not", result); + } + + /** + * Test suspend of multiple contexts with two running threads. Both threads + * should be suspended by suspending the process. + * We select the process and the first thread. + */ + @Test + public void testSuspendProcessThreadsTwoThreadsRunning() throws Throwable { + + // Run program until both threads are stopped + SyncUtil.addBreakpoint("firstBreakpoint", false); + + final ServiceEventWaitor eventWaitor = + new ServiceEventWaitor(fMultiRun.getSession(), MIStoppedEvent.class); + + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + eventWaitor.waitForEvent(2000); // Wait for second thread to stop + + // Now resume program again and wait for one of the two threads to stop + SyncUtil.resume(); + eventWaitor.waitForEvent(2000); // Wait for first thread to stop + + // Now resume the thread again to have both running + SyncUtil.resume(); + + final IExecutionDMContext[] execDmcs = new IExecutionDMContext[] { + SyncUtil.getContainerContext(), SyncUtil.getExecutionContext(0), SyncUtil.getExecutionContext(1) }; + + final IMIExecutionDMContext[] threads = SyncUtil.getExecutionContexts(); + assertTrue("Expected two threads but got " + threads.length, threads.length == 2); + + runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.suspend(execDmcs, drm); + } + }); + + eventWaitor.waitForEvent(100); // confirm one thread was suspended + eventWaitor.waitForEvent(100); // confirm the other thread was suspended + + // Also confirm that all processes are suspended + Boolean result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(execDmcs, drm); + } + }); + assertTrue("expected that all processes are suspended, but they are not", result); + + // Also confirm that all threads are suspended + result = runAsyncCall(new AsyncRunnable() { + @Override public void run(DataRequestMonitor drm) { + fMultiRun.isSuspendedAll(threads, drm); + } + }); + assertTrue("expected that all threads are suspended, but they are not", result); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java index 68d0e6843f1..faadc9de1c0 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_0.class, PostMortemCoreTest_7_0.class, CommandTimeoutTest_7_0.class, + GDBMultiNonStopRunControlTest_7_0.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java index d267a011a74..b53eeecdc91 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class, CommandTimeoutTest_7_0.class, + GDBMultiNonStopRunControlTest_7_0.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java new file mode 100644 index 00000000000..d93090b1102 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/GDBMultiNonStopRunControlTest_7_1.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +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.tests_7_0.GDBMultiNonStopRunControlTest_7_0; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_1 extends GDBMultiNonStopRunControlTest_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_1/Suite_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java index 75b9b161c61..b6dcace2a34 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_1.class, PostMortemCoreTest_7_1.class, CommandTimeoutTest_7_1.class, + GDBMultiNonStopRunControlTest_7_1.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java index 980446d4e95..f35a838208f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class, CommandTimeoutTest_7_1.class, + GDBMultiNonStopRunControlTest_7_1.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java new file mode 100644 index 00000000000..ce6fb15c1ef --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/GDBMultiNonStopRunControlTest_7_2.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +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.tests_7_1.GDBMultiNonStopRunControlTest_7_1; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_2 extends GDBMultiNonStopRunControlTest_7_1 { + @BeforeClass + public static void beforeClassMethod_7_2() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_2); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java index 800fe29a252..890f25c7b0f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_2.class, PostMortemCoreTest_7_2.class, CommandTimeoutTest_7_2.class, + GDBMultiNonStopRunControlTest_7_2.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java index 32f2a1e7b89..f53d3f2721f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class, CommandTimeoutTest_7_2.class, + GDBMultiNonStopRunControlTest_7_2.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java new file mode 100644 index 00000000000..aaeb4fe0f3a --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/GDBMultiNonStopRunControlTest_7_3.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3; + + +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_2.GDBMultiNonStopRunControlTest_7_2; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_3 extends GDBMultiNonStopRunControlTest_7_2 { + @BeforeClass + public static void beforeClassMethod_7_3() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_3); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java index 65e39402046..c4101852bce 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_3.class, PostMortemCoreTest_7_3.class, CommandTimeoutTest_7_3.class, + GDBMultiNonStopRunControlTest_7_3.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java index 63e9e39e29a..7db9786fd57 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class, CommandTimeoutTest_7_3.class, + GDBMultiNonStopRunControlTest_7_3.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java new file mode 100644 index 00000000000..1e74a7546e5 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/GDBMultiNonStopRunControlTest_7_4.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial implementation of Test cases + *******************************************************************************/ +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4; + + +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.GDBMultiNonStopRunControlTest_7_3; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + + +/** + * Tests IMultiRunControl class for Non-stop multi-threaded application. + */ +@RunWith(BackgroundRunner.class) +public class GDBMultiNonStopRunControlTest_7_4 extends GDBMultiNonStopRunControlTest_7_3 { + @BeforeClass + public static void beforeClassMethod_7_4() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java index d2c7ea43ec1..b00aa75337c 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningNonStopTest_7_4.class, PostMortemCoreTest_7_4.class, CommandTimeoutTest_7_4.class, + GDBMultiNonStopRunControlTest_7_4.class, Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java index f76a836d040..0467dd4b46f 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java @@ -41,6 +41,7 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class, CommandTimeoutTest_7_4.class, + GDBMultiNonStopRunControlTest_7_4.class, Suite_Sessionless_Tests.class /* Add your test class here */ }) diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java index a79fa6e4f5e..7b1426fee03 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,9 +7,13 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multiple selection (bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -29,11 +33,18 @@ import org.eclipse.debug.core.commands.IDebugCommandRequest; */ @Immutable public abstract class DsfCommandRunnable extends DsfRunnable { - private final IExecutionDMContext fContext; + private final IExecutionDMContext[] fContexts; private final DsfServicesTracker fTracker; private final IDebugCommandRequest fRequest; - public IExecutionDMContext getContext() { return fContext; } + // For backwards compatibility, keep this method that returns the first selection. This method + // is meaningful when we only support a single selection. + public IExecutionDMContext getContext() { return (fContexts != null && fContexts.length > 0) ? fContexts[0] : null; } + /** + * Return all selected contexts. + * @since 2.3 + */ + public IExecutionDMContext[] getContexts() { return fContexts; } public IRunControl getRunControl() { return fTracker.getService(IRunControl.class); } @@ -42,8 +53,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable { * @since 1.1 */ public SteppingController getSteppingController() { - if (fContext != null) { - return (SteppingController) fContext.getAdapter(SteppingController.class); + if (fContexts != null && fContexts.length > 0) { + return (SteppingController) fContexts[0].getAdapter(SteppingController.class); } return null; } @@ -56,15 +67,33 @@ public abstract class DsfCommandRunnable extends DsfRunnable { } public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) { - fTracker = servicesTracker; - if (element instanceof IDMVMContext) { - IDMVMContext vmc = (IDMVMContext)element; - fContext = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class); - } else { - fContext = null; - } - - fRequest = request; + this(servicesTracker, new Object[] { element }, request); + } + + /** @since 2.3 */ + public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object[] elements, IDebugCommandRequest request) { + fTracker = servicesTracker; + fRequest = request; + + // Extract all selected execution contexts, using a set to avoid duplicates. Duplicates will + // happen if multiple stack frames of the same thread are selected. + Set execDmcSet = new HashSet(request.getElements().length); + for (Object element : request.getElements()) { + if (element instanceof IDMVMContext) { + IDMVMContext vmc = (IDMVMContext)element; + IExecutionDMContext execDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class); + if (execDmc != null) { + // We have a thread or a process + execDmcSet.add(execDmc); + } + } + } + + if (execDmcSet.size() == 0) { + fContexts = null; + } else { + fContexts = execDmcSet.toArray(new IExecutionDMContext[execDmcSet.size()]); + } } @Override @@ -73,8 +102,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable { fRequest.done(); return; } - if (getContext() == null) { - fRequest.setStatus(makeError("Selected object does not support run control.", null)); //$NON-NLS-1$ + if (getContexts() == null || getContexts().length == 0) { + fRequest.setStatus(makeError("Selected objects do not support run control.", null)); //$NON-NLS-1$ } else if (getRunControl() == null || getSteppingController() == null) { fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$ } else { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java index 10e7c464039..44f089339ca 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,16 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -43,17 +45,42 @@ public class DsfResumeCommand implements IResumeHandler { @Override public void canExecute(final IEnabledStateRequest request) { - if (request.getElements().length != 1) { - request.setEnabled(false); - request.done(); + if (request.getElements().length == 1) { + canExecuteSingle(request); return; } + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.setEnabled(false); + request.done(); + return; + } + + // Check if some of the selections can be resumed + multiRun.canResumeSome( + getContexts(), + new ImmediateDataRequestMonitor() { + @Override + protected void handleCompleted() { + request.setEnabled(isSuccess() && getData()); + request.done(); + } + }); + } + }); + } + + private void canExecuteSingle(final IEnabledStateRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().canResume( getContext(), - new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { + new ImmediateDataRequestMonitor() { @Override protected void handleCompleted() { request.setEnabled(isSuccess() && getData()); @@ -66,17 +93,32 @@ public class DsfResumeCommand implements IResumeHandler { @Override public boolean execute(final IDebugCommandRequest request) { - if (request.getElements().length != 1) { - request.done(); - return false; + if (request.getElements().length == 1) { + executeSingle(request); + return false; } + + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.done(); + return; + } + multiRun.resume(getContexts(), new ImmediateRequestMonitor()); + } + }); + return false; + } + + private void executeSingle(IDebugCommandRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().resume(getContext(), new RequestMonitor(fExecutor, null)); } }); - return false; } - } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java index ebc32610586..30a9f538e4e 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,16 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IMultiRunControl; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -42,17 +44,42 @@ public class DsfSuspendCommand implements ISuspendHandler { @Override public void canExecute(final IEnabledStateRequest request) { - if (request.getElements().length != 1) { - request.setEnabled(false); - request.done(); + if (request.getElements().length == 1) { + canExecuteSingle(request); return; } + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.setEnabled(false); + request.done(); + return; + } + + // Check if some of the selections can be suspended + multiRun.canSuspendSome( + getContexts(), + new ImmediateDataRequestMonitor() { + @Override + protected void handleCompleted() { + request.setEnabled(isSuccess() && getData()); + request.done(); + } + }); + } + }); + } + + private void canExecuteSingle(final IEnabledStateRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().canSuspend( getContext(), - new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { + new ImmediateDataRequestMonitor() { @Override protected void handleCompleted() { request.setEnabled(isSuccess() && getData()); @@ -65,17 +92,32 @@ public class DsfSuspendCommand implements ISuspendHandler { @Override public boolean execute(final IDebugCommandRequest request) { - if (request.getElements().length != 1) { - request.done(); - return false; + if (request.getElements().length == 1) { + executeSingle(request); + return false; } - + + // Handle multi-selection + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) { + @Override public void doExecute() { + final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class); + if (multiRun == null) { + // No multi run control service: multi selection not allowed + request.done(); + return; + } + + multiRun.suspend(getContexts(), new ImmediateRequestMonitor()); + } + }); + return false; + } + + private void executeSingle(IDebugCommandRequest request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { getRunControl().suspend(getContext(), new RequestMonitor(fExecutor, null)); } }); - return false; } - } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java new file mode 100644 index 00000000000..ed3f9359a8b --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IMultiRunControl.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.service; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; + +/** + * This interface provides the ability to perform run control operations on multiple contexts. + * + * @see org.eclipse.cdt.dsf.debug.service.IRunControl + * + * @since 2.3 + */ +public interface IMultiRunControl extends IRunControl +{ + /** + * Check if at least one of the specified contexts can be resumed + * @param context List of execution contexts that want to be resumed + * @param rm Request monitor returning: + * true if at least one of the specified contexts can be resumed + * false if none of the specified contexts can be resumed + */ + void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be resumed + * @param context List of execution contexts that want to be resumed + * @param rm Request monitor returning: + * true if all of the specified contexts can be resumed + * false if any of the specified contexts cannot be resumed + */ + void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if at least one of the specified contexts can be suspended + * @param context List of execution contexts that want to be suspended + * @param rm Request monitor returning: + * true if at least one of the specified contexts can be suspended + * false if none of the specified contexts can be suspended + */ + void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be suspended + * @param context List of execution contexts that want to be suspended + * @param rm Request monitor returning: + * true if all of the specified contexts can be suspended + * false if any of the specified contexts cannot be suspended + */ + void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts is suspended. + * @param context List of execution contexts that are to be checked for being suspended + * @param rm Request monitor returning: + * true if any of the specified contexts is suspended, false otherwise + */ + void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts are suspended. + * @param context List of execution contexts that are to be checked for being suspended + * @param rm Request monitor returning: + * true if all of the specified contexts are suspended, false otherwise + */ + void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts can be stepped using stepType + * @param context List of execution contexts that want to be stepped + * @param stepStype The type of step to be used. + * @param rm Request monitor returning: + * true if any of the specified contexts can be stepped + * false if none of the specified contexts can be stepped + */ + void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts can be stepped using stepType + * @param context List of execution contexts that want to be stepped + * @param stepStype The type of step to be used. + * @param rm Request monitor returning: + * true if all of the specified contexts can be stepped + * false if any of the specified contexts cannot be stepped + */ + void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor rm); + + /** + * Check if any of the specified contexts is currently stepping. + * @param context List of execution contexts that are to be checked for stepping + * @param rm Request monitor returning: + * true if any of the specified contexts is stepping, false otherwise + */ + void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Check if all of the specified contexts are currently stepping. + * @param context List of execution contexts that are to be checked for stepping + * @param rm Request monitor returning: + * true if all of the specified contexts are stepping, false otherwise + */ + void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor rm); + + /** + * Request that all specified contexts be resumed. Only contexts that are in a + * state that can be resumed will be affected, others will be ignored. + * @param context List of execution contexts that are to be resumed + */ + void resume(IExecutionDMContext[] contexts, RequestMonitor rm); + + /** + * Request that all specified contexts be suspended. Only contexts that are in a + * state that can be suspended will be affected, others will be ignored. + * @param context List of execution contexts that are to be suspended + */ + void suspend(IExecutionDMContext[] contexts, RequestMonitor rm); + + /** + * Request that all specified context be stepped using stepType. Only contexts + * that are in a state that can be stepped will be affected, others will be ignored. + * @param context List of execution contexts that are to be stepped + * @param stepStype The type of step to be used. + */ + void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm); +} \ No newline at end of file From bde03774f293e5c5de443cd32104d43542f412be Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Wed, 25 Apr 2012 13:18:30 -0400 Subject: [PATCH 11/14] Bug 330974: Need to set the version of GDB for the new tests. --- .../tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java index 466aa3c776b..31d8ba38f37 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/GDBMultiNonStopRunControlTest_7_0.java @@ -37,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.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; @@ -86,7 +87,9 @@ public class GDBMultiNonStopRunControlTest_7_0 extends BaseTestCase { } @BeforeClass - public static void beforeClassMethod() { + public static void beforeClassMethod_7_0() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_0); + setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME); From ba5775f033ceab847c43042bb83a5a20af830d7c Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Wed, 25 Apr 2012 13:28:06 -0700 Subject: [PATCH 12/14] Bug 372551. Fixed semantics of ErrorParserManager (e.g. getErrorParserAvailableIds()) get by removing knowledge of contexts from internal data structures (introduced in previous change set). Change-Id: Ia1ff68841f3b494a209e8cdf45325d640fd74ddf Reviewed-on: https://git.eclipse.org/r/5656 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../AbstractExternalToolBasedChecker.java | 4 +- .../schema/ErrorParser.exsd | 16 +- .../eclipse/cdt/core/ErrorParserContext.java | 32 --- .../eclipse/cdt/core/ErrorParserManager.java | 67 +++---- .../ErrorParserExtensionManager.java | 184 ++++++++---------- .../eclipse/cdt/ui/newui/ErrorParsTab.java | 2 +- 6 files changed, 114 insertions(+), 191 deletions(-) delete mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java index 6797af3a3ca..20b7b29ce9c 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.codan.core.cxx.externaltool; -import static org.eclipse.cdt.core.ErrorParserContext.CODAN; - import java.net.URI; import org.eclipse.cdt.codan.core.CodanRuntime; @@ -127,7 +125,7 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi private ErrorParserManager createErrorParserManager(InvocationParameters parameters) { IProject project = parameters.getActualFile().getProject(); URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory()); - return new ErrorParserManager(project, workingDirectory, this, getParserIDs(), CODAN); + return new ErrorParserManager(project, workingDirectory, this, getParserIDs()); } /** diff --git a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd index d2709fa6939..5067911232e 100644 --- a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd +++ b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd @@ -153,24 +153,18 @@ Use this element to specify the context where an error parser can be used. If none is specified, a default context type will be "build". -An error parser can be assigned to more than one context type. For example, an error parser can have two "context" elements, one for "build" and one for "codan". +An example of context type is "build". Only error parsers in this context are used to parse build output. You can see these error parsers in the "C/C++" > "Build" > "Settings" preference page. + +An error parser can be assigned to more than one context type. Clients contributing error parsers are free to define their own context types. - + - The type of context where an error parser can be used. Valid values are "build" and "codan". + The type of context where an error parser can be used. - - - - - - - - diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java deleted file mode 100644 index cbfefa9ba99..00000000000 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012 Google, Inc 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: - * Alex Ruiz (Google) - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.core; - -/** - * Indicates the context in which {@link org.eclipse.cdt.core.IErrorParser}s can be - * used. - * - * @since 5.4 - */ -public class ErrorParserContext { - public static final int BUILD = 1 << 0; - public static final int CODAN = 1 << 1; - - public static int getValue(String text) { - if ("build".equals(text)) { //$NON-NLS-1$ - return BUILD; - } - if ("codan".equals(text)) { //$NON-NLS-1$ - return CODAN; - } - throw new IllegalArgumentException("Unknown context value: " + text); //$NON-NLS-1$ - } -} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java index eca556d38dc..3dc57672c5e 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java @@ -11,11 +11,10 @@ * James Blackburn (Broadcom) - Bug 247838 * Andrew Gvozdev (Quoin Inc) * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Alex Ruiz (Google) *******************************************************************************/ package org.eclipse.cdt.core; -import static org.eclipse.cdt.core.ErrorParserContext.BUILD; - import java.io.IOException; import java.io.OutputStream; import java.net.URI; @@ -68,6 +67,11 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, */ public final static char ERROR_PARSER_DELIMITER = ';'; + /** + * @since 5.4 + */ + public static final String BUILD_CONTEXT = "build"; //$NON-NLS-1$ + private int nOpens; private int lineCounter=0; @@ -75,7 +79,7 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, private final IMarkerGenerator fMarkerGenerator; private Map fErrorParsers; - private final ArrayList fErrors; + private final List fErrors; private final Vector fDirectoryStack; private final URI fBaseDirectoryURI; @@ -149,28 +153,11 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, * @since 5.1 */ public ErrorParserManager(IProject project, URI baseDirectoryURI, IMarkerGenerator markerGenerator, String[] parsersIDs) { - this(project, baseDirectoryURI, markerGenerator, parsersIDs, BUILD); - } - - /** - * URI based constructor. - * - * @param project - project being built. - * @param baseDirectoryURI - absolute location URI of working directory of where the build is performed. - * @param markerGenerator - marker generator able to create markers. - * @param parsersIDs - array of error parsers' IDs. - * @param context - context where the error parser will be used. Valid values are defined by - * {@link ErrorParserContext}. - * @see ErrorParserContext - * @since 5.4 - */ - public ErrorParserManager(IProject project, URI baseDirectoryURI, - IMarkerGenerator markerGenerator, String[] parsersIDs, int context) { fProject = project; fMarkerGenerator = markerGenerator; fDirectoryStack = new Vector(); fErrors = new ArrayList(); - enableErrorParsers(parsersIDs, context); + enableErrorParsers(parsersIDs); if (baseDirectoryURI != null) { fBaseDirectoryURI = baseDirectoryURI; @@ -182,13 +169,13 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, } } - private void enableErrorParsers(String[] parsersIDs, int context) { - if (parsersIDs == null) { - parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds(); + private void enableErrorParsers(String[] parserIDs) { + if (parserIDs == null) { + parserIDs = ErrorParserExtensionManager.getDefaultErrorParserIds(); } - fErrorParsers = new LinkedHashMap(parsersIDs.length); - for (String parsersID : parsersIDs) { - IErrorParser errorParser = getErrorParserCopy(parsersID, context); + fErrorParsers = new LinkedHashMap(parserIDs.length); + for (String parsersID : parserIDs) { + IErrorParser errorParser = getErrorParserCopy(parsersID); if (errorParser!=null) { fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} ); } @@ -375,7 +362,7 @@ outer: } catch (Exception e){ String id = ""; //$NON-NLS-1$ if (parser instanceof IErrorParserNamed) { - id = ((IErrorParserNamed)parser).getId(); + id = ((IErrorParserNamed) parser).getId(); } @SuppressWarnings("nls") String message = "Errorparser " + id + " failed parsing line [" + lineToParse + "]"; @@ -832,6 +819,16 @@ outer: return ErrorParserExtensionManager.getErrorParserAvailableIds(); } + /** + * @param context - indicates the context in which an error parser can be used. + * @return available error parsers ID, which include contributed through extension and user- + * defined ones from workspace, that can be used in the given context. + * @since 5.4 + */ + public static String[] getErrorParserAvailableIdsInContext(String context) { + return ErrorParserExtensionManager.getErrorParserAvailableIdsInContext(context); + } + /** * @return IDs of error parsers contributed through error parser extension point. * @since 5.2 @@ -870,20 +867,6 @@ outer: return ErrorParserExtensionManager.getErrorParserCopy(id, false); } - /** - * @param id - ID of error parser - * @param context - context where the error parser will be used. Valid values are defined by - * {@link ErrorParserContext}. - * @return cloned copy of error parser or {@code null}. - * Note that {@link ErrorParserNamedWrapper} returns shallow copy with the same instance - * of underlying error parser. - * @see ErrorParserContext - * @since 5.4 - */ - public static IErrorParserNamed getErrorParserCopy(String id, int context) { - return ErrorParserExtensionManager.getErrorParserCopy(id, false, context); - } - /** * @param id - ID of error parser * @return cloned copy of error parser as defined by its extension point or {@code null}. diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java index e2ec9d561de..dfdbf9120e4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java @@ -11,12 +11,14 @@ *******************************************************************************/ package org.eclipse.cdt.internal.errorparsers; -import static org.eclipse.cdt.core.ErrorParserContext.BUILD; - import java.net.URI; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -25,7 +27,6 @@ import java.util.Set; import java.util.TreeSet; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.ErrorParserContext; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.IErrorParser; import org.eclipse.cdt.core.IErrorParserNamed; @@ -33,7 +34,6 @@ import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper; import org.eclipse.cdt.core.errorparsers.RegexErrorParser; import org.eclipse.cdt.core.errorparsers.RegexErrorPattern; -import org.eclipse.cdt.internal.core.Pair; import org.eclipse.cdt.internal.core.XmlUtil; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.runtime.CoreException; @@ -71,7 +71,6 @@ public class ErrorParserExtensionManager { private static final String ATTR_POINT = "point"; //$NON-NLS-1$ private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ - private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$ private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$ private static final String ATTR_FILE = "file-expr"; //$NON-NLS-1$ @@ -85,10 +84,9 @@ public class ErrorParserExtensionManager { private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$ private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$ - // Key: error parser id. Value: pair of error parser and contexts value - private static final LinkedHashMap> fExtensionErrorParsers = new LinkedHashMap>(); - // Key: error parser id. Value: pair of error parser and contexts value - private static final LinkedHashMap> fAvailableErrorParsers = new LinkedHashMap>(); + private static final LinkedHashMap fExtensionErrorParsers = new LinkedHashMap(); + private static final LinkedHashMap fAvailableErrorParsers = new LinkedHashMap(); + private static final Map> fErrorParserContexts = new HashMap>(); private static LinkedHashMap fUserDefinedErrorParsers = null; private static List fDefaultErrorParserIds = null; @@ -121,18 +119,6 @@ public class ErrorParserExtensionManager { } } - private static class ErrorParserAndContextComparator implements Comparator> { - private static final ErrorParserComparator DELEGATE = new ErrorParserComparator(); - - @Override - public int compare(Pair pair1, - Pair pair2) { - IErrorParserNamed parser1 = pair1.first; - IErrorParserNamed parser2 = pair2.first; - return DELEGATE.compare(parser1, parser2); - } - } - static { loadUserDefinedErrorParsers(); loadDefaultErrorParserIds(); @@ -223,13 +209,12 @@ public class ErrorParserExtensionManager { * @noreference This method is not intended to be referenced by clients. */ synchronized public static void loadErrorParserExtensions() { - Set> sortedErrorParsers = - new TreeSet>(new ErrorParserAndContextComparator()); + Set sortedErrorParsers = new TreeSet(new ErrorParserComparator()); loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers); fExtensionErrorParsers.clear(); - for (Pair pair : sortedErrorParsers) { - fExtensionErrorParsers.put(pair.first.getId(), pair); + for (IErrorParserNamed errorParser : sortedErrorParsers) { + fExtensionErrorParsers.put(errorParser.getId(), errorParser); } recalculateAvailableErrorParsers(); } @@ -240,8 +225,7 @@ public class ErrorParserExtensionManager { * @param registry - extension registry * @param errorParsers - resulting set of error parsers */ - private static void loadErrorParserExtensions(IExtensionRegistry registry, - Set> errorParsers) { + private static void loadErrorParserExtensions(IExtensionRegistry registry, Set errorParsers) { errorParsers.clear(); IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID); if (extension != null) { @@ -255,9 +239,8 @@ public class ErrorParserExtensionManager { if (cfgEl.getName().equals(ELEM_ERRORPARSER)) { IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl); if (errorParser!=null) { - Pair configured = - configureErrorParser(errorParser, cfgEl); - errorParsers.add(configured); + configureErrorParser(errorParser, cfgEl); + errorParsers.add(errorParser); } } } @@ -278,50 +261,42 @@ public class ErrorParserExtensionManager { List ids = new ArrayList(); if (fDefaultErrorParserIds!=null) { for (String id : fDefaultErrorParserIds) { - Pair pair = null; IErrorParserNamed errorParser = null; if (fUserDefinedErrorParsers!=null) { errorParser = fUserDefinedErrorParsers.get(id); } - if (errorParser != null) { - pair = errorParserForBuild(errorParser); - } else { - pair = fExtensionErrorParsers.get(id); + if (errorParser==null) { + errorParser = fExtensionErrorParsers.get(id); } - if (pair != null) { - fAvailableErrorParsers.put(id, pair); + if (errorParser!=null) { + fAvailableErrorParsers.put(id, errorParser); ids.add(id); } } } // then the rest in the order defined by comparator - Set> sortedErrorParsers = - new TreeSet>(new ErrorParserAndContextComparator()); + Set sortedErrorParsers = new TreeSet(new ErrorParserComparator()); if (fUserDefinedErrorParsers!=null) { for (String id : fUserDefinedErrorParsers.keySet()) { if (!ids.contains(id)) { IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id); - sortedErrorParsers.add(errorParserForBuild(errorParser)); + sortedErrorParsers.add(errorParser); } } } for (String id : fExtensionErrorParsers.keySet()) { if (!ids.contains(id)) { - Pair pair = fExtensionErrorParsers.get(id); - sortedErrorParsers.add(pair); + IErrorParserNamed errorParser = fExtensionErrorParsers.get(id); + sortedErrorParsers.add(errorParser); } } - for (Pair pairs : sortedErrorParsers) { - fAvailableErrorParsers.put(pairs.first.getId(), pairs); + for (IErrorParserNamed errorParser : sortedErrorParsers) { + fAvailableErrorParsers.put(errorParser.getId(), errorParser); } } - private static Pair errorParserForBuild(IErrorParserNamed errorParser) { - return new Pair(errorParser, ErrorParserContext.BUILD); - } - /** * Serialize error parsers in workspace level storage. * @@ -576,8 +551,7 @@ public class ErrorParserExtensionManager { * @param cfgEl - extension configuration element * @throws CoreException */ - private static Pair configureErrorParser( - IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException { + private static void configureErrorParser(IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException { String id = cfgEl.getAttribute(ATTR_ID); if (id!=null && id.length()>0) errorParser.setId(id); @@ -602,33 +576,39 @@ public class ErrorParserExtensionManager { } } } - int contexts = contextTypes(cfgEl); - return new Pair(errorParser, contexts); + findContexts(id, cfgEl); } /** - * Returns a bit mask of contexts where an error parser can be used. Valid values for context - * are defined in {@link ErrorParserContext}. + * Finds the contexts where an error parser can be used. Clients determine whether the found + * context values are valid. * + * @param errorParserId the error parser id. * @param errorParserElement represents an "errorparser" element in the extension point * "org.eclipse.cdt.core.ErrorParser". - * @return the contexts in which an error parser can be used, or - * {@link ErrorParserContext#BUILD BUILD} is none is specified. - * @see ErrorParserContext */ - private static int contextTypes(IConfigurationElement errorParserElement) { + private static void findContexts(String errorParserId, IConfigurationElement errorParserElement) { + Set contexts = fErrorParserContexts.get(errorParserId); IConfigurationElement[] contextElements = errorParserElement.getChildren(ELEM_CONTEXT); if (contextElements.length == 0) { - return BUILD; + return; + } + boolean newContextCreated = false; + if (contexts == null) { + contexts = new HashSet(); + newContextCreated = true; } - int contexts = 0; for (IConfigurationElement contextElement : contextElements) { - String contextType = contextElement.getAttribute(ATTR_TYPE); - contexts = contexts | ErrorParserContext.getValue(contextType); + String context = contextElement.getAttribute(ATTR_TYPE); + if (context != null) { + contexts.add(context); + } + } + if (newContextCreated && !contexts.isEmpty()) { + fErrorParserContexts.put(errorParserId, contexts); } - return contexts; } - + /** * Return error parser as stored in internal list. * @@ -639,8 +619,7 @@ public class ErrorParserExtensionManager { * @return internal instance of error parser */ public static IErrorParser getErrorParserInternal(String id) { - Pair pair = fAvailableErrorParsers.get(id); - IErrorParserNamed errorParser = pair.first; + IErrorParserNamed errorParser = fAvailableErrorParsers.get(id); if (errorParser instanceof ErrorParserNamedWrapper) return ((ErrorParserNamedWrapper) errorParser).getErrorParser(); return errorParser; @@ -685,25 +664,14 @@ public class ErrorParserExtensionManager { * from workspace */ public static String[] getErrorParserAvailableIds() { - return getErrorParserIds(fAvailableErrorParsers, BUILD); + return fAvailableErrorParsers.keySet().toArray(new String[fAvailableErrorParsers.size()]); } /** * @return IDs of error parsers contributed through error parser extension point. */ public static String[] getErrorParserExtensionIds() { - return getErrorParserIds(fExtensionErrorParsers, BUILD); - } - - private static String[] getErrorParserIds( - Map> parsers, int context) { - List ids = new ArrayList(); - for (Map.Entry> entry : parsers.entrySet()) { - if (isInContext(entry.getValue(), context)) { - ids.add(entry.getKey()); - } - } - return ids.toArray(new String[ids.size()]); + return fExtensionErrorParsers.keySet().toArray(new String[fExtensionErrorParsers.size()]); } /** @@ -748,7 +716,7 @@ public class ErrorParserExtensionManager { */ public static String[] getDefaultErrorParserIds() { if (fDefaultErrorParserIds == null) { - return getErrorParserIds(fAvailableErrorParsers, BUILD); + return fAvailableErrorParsers.keySet().toArray(new String[fAvailableErrorParsers.size()]); } return fDefaultErrorParserIds.toArray(new String[fDefaultErrorParserIds.size()]); } @@ -760,26 +728,8 @@ public class ErrorParserExtensionManager { * shallow copy with the same instance of underlying error parser. */ public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) { - return getErrorParserCopy(id, isExtension, BUILD); - } + IErrorParserNamed errorParser = isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id); - /** - * @param id - ID of error parser - * @param isExtension - if {@code true} get unmodified copy of error parser defined as extension - * @param context - context where the error parser will be used. Valid values are defined by - * {@link ErrorParserContext}. - * @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns - * shallow copy with the same instance of underlying error parser. - * @see ErrorParserContext - */ - public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension, - int context) { - Pair pair = - isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id); - if (pair == null || !isInContext(pair, context)) { - return null; - } - IErrorParserNamed errorParser = pair.first; try { if (errorParser instanceof RegexErrorParser) { return (RegexErrorParser) ((RegexErrorParser) errorParser).clone(); @@ -791,8 +741,38 @@ public class ErrorParserExtensionManager { } return errorParser; } - - private static boolean isInContext(Pair pair, int context) { - return (pair.second & context) != 0; + + /** + * @param context - indicates the context in which an error parser can be used. + * @return available error parsers ID, which include contributed through extension and user- + * defined ones from workspace, that can be used in the given context. + */ + public static String[] getErrorParserAvailableIdsInContext(String context) { + List ids = new ArrayList(); + for (String id : fAvailableErrorParsers.keySet()) { + if (getErrorParserContexts(id).contains(context)) { + ids.add(id); + } + } + return ids.toArray(new String[ids.size()]); + } + + /** + * Returns all the contexts of the error parser with the given ID. Contexts are {@code String} + * values belonging to an error parser, defined as part the "errorparser" extension point + * element. + *

+ * If an error parser does not have an explicit context, it is assumed that the error parser + * can be used in the "build" context. + *

+ * @param id the id of the error parser. + * @return the contexts of the error parser with the given ID. + */ + private static Collection getErrorParserContexts(String id) { + Set contexts = fErrorParserContexts.get(id); + if (contexts == null) { + return Collections.singletonList(ErrorParserManager.BUILD_CONTEXT); + } + return contexts; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java index e9fcb0cf1a3..fe692d14e27 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java @@ -244,7 +244,7 @@ public class ErrorParsTab extends AbstractCPropertyTab { } fAvailableErrorParsers.clear(); fOptionsPageMap.clear(); - for (String id : ErrorParserManager.getErrorParserAvailableIds()) { + for (String id : ErrorParserManager.getErrorParserAvailableIdsInContext(ErrorParserManager.BUILD_CONTEXT)) { IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(id); fAvailableErrorParsers.put(id, errorParser); initializeOptionsPage(id); From 755d3975a6c0c4610667db2849f31e1102c5b3e4 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 26 Apr 2012 10:13:11 +0200 Subject: [PATCH 13/14] Bug 376246: Name resolution in catch handler of function definition. --- .../cdt/core/parser/tests/ast2/AST2CPPTests.java | 8 ++++++++ .../core/dom/parser/cpp/semantics/CPPVisitor.java | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 26a291eb121..2b808fa58a9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -9592,4 +9592,12 @@ public class AST2CPPTests extends AST2BaseTest { assertSame(calls[calls.length - 1] + " and " + calls[calls.length - 2] + " resolve to different functions", functions[calls.length - 1], functions[calls.length - 2]); } + + // void f(int x) try { + // } catch(...) { + // (void)x; + // } + public void testParentScopeOfCatchHandler_376246() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 36a9f6d23cf..a144e5dc880 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -13,11 +13,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*; import java.util.ArrayList; import java.util.Arrays; @@ -1264,7 +1260,11 @@ public class CPPVisitor extends ASTQueries { } else if (parent instanceof IASTStatement) { scope = getContainingScope((IASTStatement) parent); } else if (parent instanceof IASTFunctionDefinition) { - IASTFunctionDeclarator fnDeclarator = ((IASTFunctionDefinition) parent).getDeclarator(); + final IASTFunctionDefinition fdef = (IASTFunctionDefinition) parent; + if (statement instanceof ICPPASTCatchHandler) + return fdef.getScope(); + + IASTFunctionDeclarator fnDeclarator = fdef.getDeclarator(); IASTName name = findInnermostDeclarator(fnDeclarator).getName(); if (name instanceof ICPPASTQualifiedName) { IASTName[] ns = ((ICPPASTQualifiedName) name).getNames(); From ff6444f9b8306ca65ebb97de02ace35a2ff69e6c Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 26 Apr 2012 11:55:34 +0200 Subject: [PATCH 14/14] Bug 377457: Name resolution for exception specification. --- .../eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java | 9 +++++++++ .../core/dom/parser/cpp/semantics/CPPVisitor.java | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 2b808fa58a9..14929e23c70 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -9600,4 +9600,13 @@ public class AST2CPPTests extends AST2BaseTest { public void testParentScopeOfCatchHandler_376246() throws Exception { parseAndCheckBindings(); } + + // struct MyClass { + // struct MyException {}; + // void doSomething() throw(MyException); + // }; + // void MyClass::doSomething() throw (MyException) {} + public void testScopeOfExceptionSpecification_377457() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index a144e5dc880..af69d010bf4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -982,7 +982,8 @@ public class CPPVisitor extends ASTQueries { node= node.getParent(); } continue; - } else if (prop == ICPPASTFunctionDeclarator.TRAILING_RETURN_TYPE) { + } else if (prop == ICPPASTFunctionDeclarator.TRAILING_RETURN_TYPE || + prop == ICPPASTFunctionDeclarator.EXCEPTION_TYPEID) { IScope result = scopeViaFunctionDtor((ICPPASTFunctionDeclarator) node.getParent()); if (result != null) return result;