blob: b58003c53fca2e3bcc1c9f6f3a2bf606b05aab65 [file] [log] [blame]
/**
* Copyright (c) 2009, 2014 THALES GLOBAL SERVICES 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:
* Obeo - Initial API and implementation
*/
package org.eclipse.sirius.tests.swtbot.support.api;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import junit.framework.TestCase;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.gmf.runtime.diagram.ui.editparts.AbstractBorderedShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DescriptionCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.TextEditPart;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.sirius.business.api.dialect.DialectManager;
import org.eclipse.sirius.business.api.preferences.SiriusPreferencesKeys;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.sirius.common.tools.internal.resource.ResourceSyncClientNotifier;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DiagramPackage;
import org.eclipse.sirius.diagram.DiagramPlugin;
import org.eclipse.sirius.diagram.tools.api.preferences.SiriusDiagramCorePreferences;
import org.eclipse.sirius.diagram.tools.api.preferences.SiriusDiagramPreferencesKeys;
import org.eclipse.sirius.diagram.tools.internal.preferences.SiriusDiagramInternalPreferencesKeys;
import org.eclipse.sirius.diagram.ui.business.internal.dialect.DiagramDialectUIServices;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramEdgeEditPart;
import org.eclipse.sirius.diagram.ui.provider.DiagramUIPlugin;
import org.eclipse.sirius.diagram.ui.tools.api.preferences.SiriusDiagramUiPreferencesKeys;
import org.eclipse.sirius.diagram.ui.tools.internal.actions.style.ResetStylePropertiesToDefaultValuesAction;
import org.eclipse.sirius.diagram.ui.tools.internal.preferences.SiriusDiagramUiInternalPreferencesKeys;
import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
import org.eclipse.sirius.tests.support.api.EclipseTestsSupportHelper;
import org.eclipse.sirius.tests.support.api.TestCaseCleaner;
import org.eclipse.sirius.tests.support.api.TestsUtil;
import org.eclipse.sirius.tests.swtbot.support.api.business.UIDiagramRepresentation.ZoomLevel;
import org.eclipse.sirius.tests.swtbot.support.api.business.UILocalSession;
import org.eclipse.sirius.tests.swtbot.support.api.business.UIPerspective;
import org.eclipse.sirius.tests.swtbot.support.api.business.UIProject;
import org.eclipse.sirius.tests.swtbot.support.api.business.UIResource;
import org.eclipse.sirius.tests.swtbot.support.api.condition.OperationRedoneCondition;
import org.eclipse.sirius.tests.swtbot.support.api.condition.OperationUndoneCondition;
import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusDiagramEditor;
import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusHelper;
import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotVSMEditor;
import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotVSMHelper;
import org.eclipse.sirius.tests.swtbot.support.api.perspective.DesignerPerspectives;
import org.eclipse.sirius.tests.swtbot.support.api.view.DesignerViews;
import org.eclipse.sirius.tests.swtbot.support.utils.SWTBotCommonHelper;
import org.eclipse.sirius.tests.swtbot.support.utils.SWTBotUtils;
import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
import org.eclipse.sirius.viewpoint.description.RepresentationDescription;
import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.swtbot.eclipse.finder.matchers.WidgetMatcherFactory;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.eclipse.gef.finder.SWTBotGefTestCase;
import org.eclipse.swtbot.eclipse.gef.finder.widgets.SWTBotGefEditPart;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.utils.ClassUtils;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ErrorEditorPart;
import org.hamcrest.Matcher;
import org.junit.Assert;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* Wrapper for several UI* classes to handle ui management in tests. If needed,
* new setup operations can be done in
* {@link #onSetUpBeforeClosingWelcomePage()} overridden method.
*
* {@link #onSetUpAfterOpeningDesignerPerspective()} allows developer to add
* extra behavior after opening designer perspective.
*
* @author dlecan
*/
@SuppressWarnings("restriction")
public abstract class AbstractSiriusSwtBotGefTestCase extends SWTBotGefTestCase {
static {
SWTBotPreferences.TIMEOUT = 10000;
}
/**
* Models dir.
*/
protected static final String MODELS_DIR = "Models";
/** Test project name. */
protected static final String TEMP_PROJECT_NAME = "DesignerTestProject";
private static final String EN_US = "EN_US";
private static final String SET_STYLE_TO_WORKSPACE_IMAGE = "Set style to workspace image";
private static final String POINT = ".";
private static final String EDIT_MENU_NAME = "Edit";
private static boolean fFullScreen = true;
/**
* Designer perspective.
*/
protected UIPerspective designerPerspective = new UIPerspective(bot);
/**
* Designer perspective.
*/
protected DesignerPerspectives designerPerspectives = new DesignerPerspectives(bot);
/** . */
protected DesignerViews designerViews = new DesignerViews(bot);
/**
* Designer project.
*/
protected UIProject designerProject;
/**
* The Session Resource wrapper.
*/
protected UIResource sessionAirdResource;
/**
* The Session Tree item wrapper.
*/
protected UILocalSession localSession;
/**
* The DialectEditor (opened on representation creation) wrapper.
*/
protected SWTBotSiriusDiagramEditor editor;
/**
* The reported errors.
*/
protected LinkedHashMultimap<String, IStatus> errors;
private boolean defaultEnableAnimatedZoom;
private boolean defaultEnableAnimatedLayout;
/**
* HashMaps to store the initial values of preferences before changes.
*/
private final HashMap<String, Object> oldValueDiagramPreferences = new HashMap<String, Object>();
private final HashMap<String, Object> oldValueDiagramUIPreferences = new HashMap<String, Object>();
private final HashMap<String, Object> oldValueSiriusPreferences = new HashMap<String, Object>();
private final HashMap<String, Object> oldValueSiriusUIPreferences = new HashMap<String, Object>();
private final HashMap<String, Object> oldPlatformUIPreferences = new HashMap<String, Object>();
/**
* The unchaught exceptions handler.
*/
private UncaughtExceptionHandler exceptionHandler;
/**
* The platform error listener.
*/
private ILogListener logListener;
private boolean errorCatchActive;
/**
* {@inheritDoc}
*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
PlatformUI.getWorkbench().getWorkbenchWindows()[0].getShell().setFullScreen(AbstractSiriusSwtBotGefTestCase.fFullScreen);
}
});
/* Init error log and uncauht exception handlers */
errors = LinkedHashMultimap.create();
initErrorLoggers();
System.out.println("Setup of " + this.getClass().getName() + AbstractSiriusSwtBotGefTestCase.POINT + getName() + "()");
try {
super.setUp();
// Disable the animated zoom and the animated arrange to save time
UIThreadRunnable.syncExec(new VoidResult() {
@Override
public void run() {
IPreferenceStore preferenceStore = DiagramUIPlugin.getPlugin().getPreferenceStore();
defaultEnableAnimatedZoom = preferenceStore.getBoolean(IPreferenceConstants.PREF_ENABLE_ANIMATED_ZOOM);
preferenceStore.setValue(IPreferenceConstants.PREF_ENABLE_ANIMATED_ZOOM, false);
defaultEnableAnimatedLayout = preferenceStore.getBoolean(IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT);
preferenceStore.setValue(IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT, false);
// Set the auto-refresh to false because it's historically
// the
// default value
DefaultScope.INSTANCE.getNode(SiriusPlugin.ID).putBoolean(SiriusPreferencesKeys.PREF_AUTO_REFRESH.name(), true);
InstanceScope.INSTANCE.getNode(SiriusPlugin.ID).putBoolean(SiriusPreferencesKeys.PREF_AUTO_REFRESH.name(), getAutoRefreshMode());
}
});
// If you need another name, override getProjectName()
designerProject = designerPerspective.createProject(getProjectName());
onSetUpBeforeClosingWelcomePage();
closeWelcomePage();
// Set up a no ui callback for auto migration
// SiriusEditPlugin.getPlugin().setUiCallback(new
// UiCallBackWithoutMigrationNotification(SiriusEditPlugin.getPlugin().getUiCallback()));
// Open Design perspective
designerPerspectives.openModelingPerspective();
onSetUpAfterOpeningDesignerPerspective();
// CHECKSTYLE:OFF
} catch (Throwable e) {
takeScreenshot("-after-setup");
// Call the tear down to clean the environment (not done by JUnit if
// setup failed)
try {
failureTearDown();
} catch (Exception secondException) {
// CHECKSTYLE:ON
// Ignore this secondException, because the first is the more
// important
}
if (e instanceof Exception) {
throw (Exception) e;
} else {
throw new RuntimeException(e);
}
}
}
/**
* Define the auto refresh mode to use during this tests.
*
* @return the auto refresh mode.
*/
protected boolean getAutoRefreshMode() {
return false;
}
/**
* Get the project name to create.
*
* @return Project name.
*/
protected String getProjectName() {
return AbstractSiriusSwtBotGefTestCase.TEMP_PROJECT_NAME;
}
/**
* Do something before closing welcome page during setup.
*
* @throws Exception
* Error.
*/
protected void onSetUpBeforeClosingWelcomePage() throws Exception {
// Default, nothing
}
/**
* Do something after opening designer perspective, just before executing
* test.
*
* @throws Exception
* Error.
*/
protected void onSetUpAfterOpeningDesignerPerspective() throws Exception {
// Default, nothing
}
/**
* Close all opened editors without saving. A waitAllUiEvents is called to
* wait the closing of editors that is run by Eclipse in asyncExec.
*/
protected void closeAllEditors() {
bot.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
for (int i = 0; i < PlatformUI.getWorkbench().getWorkbenchWindows().length; i++) {
for (int j = 0; j < PlatformUI.getWorkbench().getWorkbenchWindows()[i].getPages().length; j++) {
PlatformUI.getWorkbench().getWorkbenchWindows()[i].getPages()[j].closeAllEditors(false);
}
}
}
});
// wait ui events according to editor
SWTBotUtils.waitAllUiEvents();
}
private void closeAllSessions() {
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
for (final Session sess : Sets.newLinkedHashSet(SessionManager.INSTANCE.getSessions())) {
if (sess.isOpen()) {
sess.save(new NullProgressMonitor());
try {
Job.getJobManager().join(ResourceSyncClientNotifier.FAMILY, new NullProgressMonitor());
} catch (OperationCanceledException e) {
TestCase.fail(e.getLocalizedMessage());
} catch (InterruptedException e) {
TestCase.fail(e.getLocalizedMessage());
}
sess.close(new NullProgressMonitor());
}
}
}
});
}
/**
* Close the Welcome Page.
*/
protected void closeWelcomePage() {
Matcher<IWorkbenchPartReference> matcher = WidgetMatcherFactory.withPartName("Welcome");
List<SWTBotView> views = bot.views(matcher);
for (SWTBotView swtBotView : views) {
swtBotView.close();
}
}
/**
* Request an explicit refresh of the current diagram.
*/
protected void manualRefresh() {
if (TestsUtil.isDynamicTabbar()) {
bot.toolbarButtonWithTooltip(DiagramDialectUIServices.REFRESH_DIAGRAM).click();
} else {
// Use context menu instead of tabbar
new SWTBotSiriusDiagramEditor(bot.activeEditor().getReference(), bot).clickContextMenu("Refresh");
}
SWTBotUtils.waitProgressMonitorClose("Progress Information");
}
/**
* {@inheritDoc}
*
* runtTest() method is overridden to allow to take a screenshot just after
* test execution and before tearDown operation. As tearDown closes diagram
* and session, after it, screenshots don't show any interesting things.
*/
@Override
// CHECKSTYLE:OFF
// Need Throwable type by contract
protected void runTest() throws Throwable {
try {
super.runTest();
} catch (Throwable running) {
// CHECKSTYLE:ON
takeScreenshot("-before-tearDown");
throw running;
}
}
/**
* Helper used by {@link #runTest()}.
*
* @param suffix
* The suffix of the screenshot to create
* @see #runTest()
*/
public void takeScreenshot(CharSequence suffix) {
String fileName = "screenshots/screenshot-" + ClassUtils.simpleClassName(getClass()) + AbstractSiriusSwtBotGefTestCase.POINT + getName() + suffix + AbstractSiriusSwtBotGefTestCase.POINT
+ SWTBotPreferences.SCREENSHOT_FORMAT.toLowerCase();
new File("screenshots").mkdirs(); //$NON-NLS-1$
SWTUtils.captureScreenshot(fileName);
}
/**
* Open error log.
*/
protected void openErrorLogViewByAPI() {
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
try {
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("org.eclipse.pde.runtime.LogView");
} catch (PartInitException e) {
TestCase.fail("Unable to open errorLog view : " + e.getMessage());
}
}
});
}
/**
* Get the number of Status in the error log at the time of the call.
*
* @return the number of Status in the error log at the time of the call
*/
public int getNbStatusInErrorLog() {
openErrorLogViewByAPI();
SWTBotView logViewBot = bot.viewByTitle("Error Log");
logViewBot.show();
SWTBotTree tree = logViewBot.bot().tree();
int nbStatus = tree.getAllItems().length;
logViewBot.close();
return nbStatus;
}
/**
* Assert the editor is not an error one, close it before failing if it is
* to avoid breaking further tests.
*
* @param message
* : message on failure.
* @param activeEditor
* the editor to check.
*/
protected void assertEditorIsNotError(String message, SWTBotEditor activeEditor) {
IEditorPart editorPart = activeEditor.getReference().getEditor(false);
boolean isError = editorPart instanceof ErrorEditorPart;
if (isError) {
activeEditor.close();
}
TestCase.assertFalse(message, isError);
}
/**
* Undo with shortcut CTRL+z, at the end of this method execution, the
* operation undo is finished.
*/
protected void undo() {
Assert.assertTrue(editor != null);
ICondition condition = new OperationUndoneCondition();
bot.activeEditor();
String savedKeyboardLayout = SWTBotPreferences.KEYBOARD_LAYOUT;
SWTBotPreferences.KEYBOARD_LAYOUT = AbstractSiriusSwtBotGefTestCase.EN_US;
editor.getCanvas().pressShortcut(SWT.CTRL, 'z');
SWTBotPreferences.KEYBOARD_LAYOUT = savedKeyboardLayout;
bot.waitUntil(condition);
}
/**
* Undo using the command stack of the editing domain of the current
* session.
*
* @param session
* current session to undo last action.
*/
protected void undo(Session session) {
session.getTransactionalEditingDomain().getCommandStack().undo();
}
/**
* Undo the command named cmdName with the menu Edit.
*
* @param cmdName
* the command to undo
*/
protected void undo(String cmdName) {
bot.menu(AbstractSiriusSwtBotGefTestCase.EDIT_MENU_NAME).menu("Undo " + cmdName).click();
}
/**
* Redo with shortcut CTRL+y, at the end of this method execution, the
* operation redo is finished.
*/
protected void redo() {
Assert.assertTrue(editor != null);
ICondition condition = new OperationRedoneCondition();
bot.activeEditor();
String savedKeyboardLayout = SWTBotPreferences.KEYBOARD_LAYOUT;
SWTBotPreferences.KEYBOARD_LAYOUT = AbstractSiriusSwtBotGefTestCase.EN_US;
if (System.getProperty("os.name").equals("Linux") && (TestsUtil.isJuno3Platform() || TestsUtil.isEclipse4xPlatform())) {
editor.getCanvas().pressShortcut(SWT.SHIFT | SWT.CTRL, 'z');
} else {
editor.getCanvas().pressShortcut(SWT.CTRL, 'y');
}
SWTBotPreferences.KEYBOARD_LAYOUT = savedKeyboardLayout;
bot.waitUntil(condition);
}
/**
* Redo the command named cmdName with the menu Edit.
*
* @param cmdName
* the command to redo
*/
protected void redo(String cmdName) {
bot.menu(AbstractSiriusSwtBotGefTestCase.EDIT_MENU_NAME).menu("Redo " + cmdName).click();
}
/**
* Redo using the command stack of the editing domain of the current
* session.
*
* @param session
* current session to redo last action.
*/
protected void redo(Session session) {
session.getTransactionalEditingDomain().getCommandStack().redo();
}
/**
* Cancel the custom style.
*/
protected void launchCancelCustomStyle() {
bot.buttonWithTooltip("Cancel custom style").click();
}
/**
* Change a boolean preference and store the old value. It will be
* automatically reset during tear down.
*
* TO CALL ONLY ONCE PER TEST (set up + test)
*
* @param preferenceKey
* The key of the preference.
* @param newValue
* The new value.
*/
protected void changeDiagramPreference(String preferenceKey, Boolean newValue) {
assertNoDiagramUIPreferenceChangedinDiagramCoreStore(preferenceKey);
boolean oldValue = Platform.getPreferencesService().getBoolean(DiagramPlugin.ID, preferenceKey, false, null);
oldValueDiagramPreferences.put(preferenceKey, oldValue);
IEclipsePreferences diagramCorePreferences = InstanceScope.INSTANCE.getNode(DiagramPlugin.ID);
diagramCorePreferences.putBoolean(preferenceKey, newValue);
boolean valueToCheck = Platform.getPreferencesService().getBoolean(DiagramPlugin.ID, preferenceKey, false, null);
TestCase.assertEquals(getErrorMessage(preferenceKey, DiagramPlugin.ID), newValue.booleanValue(), valueToCheck);
}
/**
* Restore this preference to its initial value. Should be called after
* {@link #changeDiagramPreference(String, Boolean)} of
* {@link #changeDiagramPreference(String, Integer)} to have effect.
*
* @param preferenceKey
* The key of the preference.
*/
protected void resetDiagramPreference(String preferenceKey) {
IEclipsePreferences diagramCorePreferences = InstanceScope.INSTANCE.getNode(DiagramPlugin.ID);
resetDiagramPreference(preferenceKey, diagramCorePreferences);
}
/**
* Restore this preference to its initial value. Should be called after
* {@link #changeDiagramPreference(String, Boolean)} of
* {@link #changeDiagramPreference(String, Integer)} to have effect.
*
* @param preferenceKey
* The key of the preference.
* @param diagramCorePreferences
* The {@link IEclipsePreferences} to use.
*/
private void resetDiagramPreference(String preferenceKey, IEclipsePreferences diagramCorePreferences) {
Object initialValue = oldValueDiagramPreferences.get(preferenceKey);
if (initialValue instanceof Boolean) {
diagramCorePreferences.putBoolean(preferenceKey, (Boolean) initialValue);
} else if (initialValue instanceof Integer) {
diagramCorePreferences.putInt(preferenceKey, (Integer) initialValue);
}
}
/**
* Change a boolean preference and store the old value. It will be
* automatically reset during tear down.
*
* TO CALL ONLY ONCE PER TEST (set up + test)
*
* @param preferenceKey
* The key of the preference.
* @param newValue
* The new value.
*/
protected void changeDiagramUIPreference(final String preferenceKey, final Boolean newValue) {
assertNoDiagramCorePreferenceChangedinDiagramUIStore(preferenceKey);
final IPreferenceStore prefs = DiagramUIPlugin.getPlugin().getPreferenceStore();
oldValueDiagramUIPreferences.put(preferenceKey, prefs.getBoolean(preferenceKey));
UIThreadRunnable.syncExec(new VoidResult() {
@Override
public void run() {
prefs.setValue(preferenceKey, newValue);
}
});
}
/**
* Restore this preference to its initial value. Should be called after
* {@link #changeDiagramUIPreference(String, Boolean)} of
* {@link #changeDiagramUIPreference(String, Integer)} to have effect.
*
* @param preferenceKey
* The key of the preference.
*/
protected void resetDiagramUIPreference(String preferenceKey) {
IPreferenceStore diagramUIPreferences = DiagramUIPlugin.getPlugin().getPreferenceStore();
resetDiagramUIPreference(preferenceKey, diagramUIPreferences);
}
/**
* Restore this preference to its initial value. Should be called after
* {@link #changeDiagramUIPreference(String, Boolean)} of
* {@link #changeDiagramUIPreference(String, Integer)} to have effect.
*
* @param preferenceKey
* The key of the preference.
* @param diagramUIPreferences
* The {@link IPreferenceStore} to use.
*/
private void resetDiagramUIPreference(String preferenceKey, IPreferenceStore diagramUIPreferences) {
Object initialValue = oldValueDiagramUIPreferences.get(preferenceKey);
if (initialValue instanceof Boolean) {
diagramUIPreferences.setValue(preferenceKey, (Boolean) initialValue);
} else if (initialValue instanceof Integer) {
diagramUIPreferences.setValue(preferenceKey, (Integer) initialValue);
}
}
/**
* Change a boolean preference and store the old value. It will be
* automatically reset during tear down.
*
* TO CALL ONLY ONCE PER TEST (set up + test)
*
* @param preferenceKey
* The key of the preference.
* @param newValue
* The new value.
*/
protected void changeSiriusPreference(String preferenceKey, Boolean newValue) {
boolean oldValue = Platform.getPreferencesService().getBoolean(SiriusPlugin.ID, preferenceKey, false, null);
oldValueSiriusPreferences.put(preferenceKey, oldValue);
IEclipsePreferences corePreferences = InstanceScope.INSTANCE.getNode(SiriusPlugin.ID);
corePreferences.putBoolean(preferenceKey, newValue);
boolean valueToCheck = Platform.getPreferencesService().getBoolean(SiriusPlugin.ID, preferenceKey, false, null);
TestCase.assertEquals(getErrorMessage(preferenceKey, SiriusPlugin.ID), newValue.booleanValue(), valueToCheck);
}
/**
* Change a boolean preference and store the old value. It will be
* automatically reset during tear down.
*
* TO CALL ONLY ONCE PER TEST (set up + test)
*
* @param preferenceKey
* The key of the preference.
* @param newValue
* The new value.
*/
protected void changeSiriusUIPreference(String preferenceKey, Boolean newValue) {
assertNoSiriusCorePreferenceChangedinSiriusUIStore(preferenceKey);
IPreferenceStore viewpointUIPrefs = SiriusEditPlugin.getPlugin().getPreferenceStore();
oldValueSiriusUIPreferences.put(preferenceKey, viewpointUIPrefs.getBoolean(preferenceKey));
viewpointUIPrefs.setValue(preferenceKey, newValue);
}
/**
* Change a boolean preference and store the old value to reset it after the
* test.
*
* @param preferenceKey
* The key of the preference.
* @param newValue
* The new value.
*/
protected void changePlatformUIPreference(String preferenceKey, Boolean newValue) {
IPreferenceStore viewpointUIPrefs = PlatformUI.getPreferenceStore();
oldPlatformUIPreferences.put(preferenceKey, viewpointUIPrefs.getBoolean(preferenceKey));
viewpointUIPrefs.setValue(preferenceKey, newValue);
}
private void assertNoSiriusCorePreferenceChangedinSiriusUIStore(String preferenceKey) {
Collection<SiriusPreferencesKeys> coreKeys = Lists.newArrayList(SiriusPreferencesKeys.values());
Function<SiriusPreferencesKeys, String> prefToName = new Function<SiriusPreferencesKeys, String>() {
@Override
public String apply(SiriusPreferencesKeys input) {
return input.name();
}
};
TestCase.assertFalse("The DesignerPreferenceKey named " + preferenceKey + " should not be modified in the UI store.",
Lists.newArrayList(Iterables.transform(coreKeys, prefToName)).contains(preferenceKey));
}
private void assertNoDiagramCorePreferenceChangedinDiagramUIStore(String preferenceKey) {
Collection<String> coreKeys = Lists.newArrayList();
for (SiriusDiagramInternalPreferencesKeys key : SiriusDiagramInternalPreferencesKeys.values()) {
coreKeys.add(key.name());
}
for (SiriusDiagramPreferencesKeys key : SiriusDiagramPreferencesKeys.values()) {
coreKeys.add(key.name());
}
coreKeys.add(SiriusDiagramCorePreferences.PREF_ENABLE_OVERRIDE);
coreKeys.add(SiriusDiagramCorePreferences.PREF_LINE_STYLE);
assertFalse("The Diagram core preference named " + preferenceKey + " should not be modified in the Diagram UI store.", coreKeys.contains(preferenceKey));
}
private void assertNoDiagramUIPreferenceChangedinDiagramCoreStore(String preferenceKey) {
Collection<String> uiKeys = Lists.newArrayList();
for (SiriusDiagramUiInternalPreferencesKeys key : SiriusDiagramUiInternalPreferencesKeys.values()) {
uiKeys.add(key.name());
}
for (SiriusDiagramUiPreferencesKeys key : SiriusDiagramUiPreferencesKeys.values()) {
uiKeys.add(key.name());
}
assertFalse("The Diagram UI preference named " + preferenceKey + " should not be modified in the Diagram core store.", uiKeys.contains(preferenceKey));
}
private String getErrorMessage(String preferenceKey, String pluginId) {
return "The " + preferenceKey + " preference value was not changed for plugin " + pluginId;
}
/**
* Delete the selected element if possible.
*/
protected void deleteSelectedElement() {
SWTBotMenu deleteMenu = checkDeleteMenuEnablement(true);
deleteMenu.click();
}
/**
* Delete the selected element from diagram if possible.
*/
protected void deleteFromDiagram() {
String savedKeyboardLayout = SWTBotPreferences.KEYBOARD_LAYOUT;
SWTBotPreferences.KEYBOARD_LAYOUT = AbstractSiriusSwtBotGefTestCase.EN_US;
editor.getCanvas().pressShortcut(SWT.CTRL | SWT.SHIFT, 'd');
SWTBotPreferences.KEYBOARD_LAYOUT = savedKeyboardLayout;
SWTBotUtils.waitAllUiEvents();
}
/**
* Delete the selected element if possible.
*
* @param expected
* expected value of the delete menu.
* @return the delete bot menu.
*/
protected SWTBotMenu checkDeleteMenuEnablement(boolean expected) {
SWTBotMenu deleteMenu = bot.menu(AbstractSiriusSwtBotGefTestCase.EDIT_MENU_NAME).menu("Delete");
String errorMessage = expected ? "Delete menu should be enabled" : "Delete menu was not enabled";
TestCase.assertEquals(errorMessage, expected, deleteMenu.isEnabled());
return deleteMenu;
}
/**
* Toggle Active view/editor maximize. If possible call directly
* {@link #maximizeEditor(SWTBotSiriusDiagramEditor)} and
* {@link #restoreEditor(SWTBotSiriusDiagramEditor)}, they are faster
* because they use directly Eclipse API.
*/
protected void maximizeEditor() {
bot.menu("Window").menu("Navigation").menu("Maximize Active View or Editor").click();
}
/**
* Maximize view/editor maximize using the eclipse API.
*
* @param swtBotDesignerEditor
* The editor to maximize
*/
protected void maximizeEditor(SWTBotSiriusDiagramEditor swtBotDesignerEditor) {
swtBotDesignerEditor.maximize();
}
/**
* Press zoom in button.
*
* @param swtBotDesignerEditor
* The current editor
*/
protected void pressZoomInButton(SWTBotSiriusDiagramEditor swtBotDesignerEditor) {
pressZoomInButton(swtBotDesignerEditor, 1);
}
/**
* Press "pressCount" times on zoom in button.
*
* @param swtBotDesignerEditor
* The current editor
* @param pressCount
* the number of times to press zoom in
*/
protected void pressZoomInButton(SWTBotSiriusDiagramEditor swtBotDesignerEditor, int pressCount) {
for (int i = 1; i <= pressCount; i++) {
if (TestsUtil.isDynamicTabbar()) {
// 2 possible values for this tooltip according to the target
// platform
// No common constant was found, so we try with both possible
// values
try {
swtBotDesignerEditor.bot().toolbarButtonWithTooltip("Zoom In (Ctrl++)").click();
} catch (WidgetNotFoundException e) {
swtBotDesignerEditor.bot().toolbarButtonWithTooltip("Zoom In (Ctrl+=)").click();
}
} else {
double currentZoom = GraphicalHelper.getZoom((IGraphicalEditPart) ((DiagramRootEditPart) swtBotDesignerEditor.rootEditPart().part()).getContents());
swtBotDesignerEditor.zoom(ZoomLevel.createNextZoomInLevel(currentZoom));
}
}
}
/**
* Press zoom out button.
*
* @param swtBotDesignerEditor
* The current editor
*/
protected void pressZoomOutButton(SWTBotSiriusDiagramEditor swtBotDesignerEditor) {
pressZoomOutButton(swtBotDesignerEditor, 1);
}
/**
* Press "pressCount" times on zoom out button.
*
* @param swtBotDesignerEditor
* The current editor
* @param pressCount
* the number of times to press zoom in
*/
protected void pressZoomOutButton(SWTBotSiriusDiagramEditor swtBotDesignerEditor, int pressCount) {
for (int i = 1; i <= pressCount; i++) {
if (TestsUtil.isDynamicTabbar()) {
swtBotDesignerEditor.bot().toolbarButtonWithTooltip("Zoom Out (Ctrl+-)").click();
} else {
double currentZoom = GraphicalHelper.getZoom((IGraphicalEditPart) ((DiagramRootEditPart) swtBotDesignerEditor.rootEditPart().part()).getContents());
swtBotDesignerEditor.zoom(ZoomLevel.createNextZoomOutLevel(currentZoom));
}
}
}
/**
* Restore the size of the view/editor using the eclipse API.
*
* @param swtBotDesignerEditor
* The editor to restore
*/
protected void restoreEditor(SWTBotSiriusDiagramEditor swtBotDesignerEditor) {
swtBotDesignerEditor.restore();
}
/***
* Do a arrange all of the current diagram.
*
* @return the menu of the ArrangeAll action
*/
protected SWTBotMenu arrangeAll() {
// Give the focus to the editor
editor.setFocus();
// Select the diagram itself
editor.select(editor.mainEditPart());
// Launch the arrange via the menu bar
SWTBotMenu arrangeAllMenutBot = bot.menu("Diagram").menu("Arrange").menu("All").click();
SWTBotUtils.waitAllUiEvents();
return arrangeAllMenutBot;
}
/**
* Get all the representation with the given representation description
* name.
*
* @param session
* The session containing the searched representations.
* @param representationDescriptionName
* the name of the representation description. <code>null</code>
* is not excepted.
* @return a {@link Collection} with all representations retrieved.
*/
protected Collection<DRepresentation> getRepresentations(final Session session, final String representationDescriptionName) {
final Collection<DRepresentation> allRepresentations = DialectManager.INSTANCE.getAllRepresentations(session);
final Collection<DRepresentation> representations = new HashSet<DRepresentation>();
for (final DRepresentation representation : allRepresentations) {
final RepresentationDescription desc = DialectManager.INSTANCE.getDescription(representation);
if (desc != null && representationDescriptionName.equals(desc.getName())) {
representations.add(representation);
}
}
return representations;
}
/**
* Return the first representation with the given representation description
* name and representation name.
*
* @param session
* The session containing the searched representations.
* @param representationDescriptionName
* the name of the representation description. <code>null</code>
* is not excepted.
* @param representationName
* the name of the representation
* @return the first corresponding representation
*/
protected final DRepresentation getRepresentationWithName(Session session, String representationDescriptionName, final String representationName) {
try {
final DRepresentation existingRepresentation = Iterables.find(getRepresentations(session, representationDescriptionName), new Predicate<DRepresentation>() {
@Override
public boolean apply(DRepresentation input) {
return input.getName().equals(representationName);
}
});
return existingRepresentation;
} catch (NoSuchElementException e) {
throw new NoSuchElementException("No representation found in session with \"" + representationName + "\" as representation name and with \"" + representationDescriptionName
+ "\" as representation description name.");
}
}
/**
* Open the first diagram with the given diagram description name and
* diagram name.
*
* @param session
* The session containing the searched representations.
* @param diagramDescriptionName
* the name of the diagram description. <code>null</code> is not
* excepted.
* @param diagramName
* the name of the diagram
* @param expectedRepresentationClass
* the expected type of representation to found
* @return the editor of the first corresponding diagram
* @deprecated To replace by
* {@link #openRepresentation(Session, String, String, Class)}
*/
@Deprecated
protected SWTBotSiriusDiagramEditor openDiagram(Session session, String diagramDescriptionName, final String diagramName, Class<? extends DRepresentation> expectedRepresentationClass) {
return openDiagram(session, diagramDescriptionName, diagramName, expectedRepresentationClass, false);
}
/**
* Open the first representation with the given representation description
* name and representation name.
*
* @param session
* The session containing the searched representations.
* @param diagramDescriptionName
* the name of the diagram description. <code>null</code> is not
* excepted.
* @param diagramName
* the name of the diagram
* @param expectedRepresentationClass
* the expected type of representation to found
* @param disableSnapToGridOnThisEditor
* true if the snapToGrid must be disable for this editor, false
* otherwise
* @return the editor of the first corresponding diagram
* @deprecated To replace by
* {@link #openRepresentation(Session, String, String, Class, boolean)}
*/
@Deprecated
protected SWTBotSiriusDiagramEditor openDiagram(Session session, String diagramDescriptionName, final String diagramName, Class<? extends DRepresentation> expectedRepresentationClass,
boolean disableSnapToGridOnThisEditor) {
assertTrue("This method is only able to deal with diagrams.", DiagramPackage.Literals.DDIAGRAM.getInstanceClass().isAssignableFrom(expectedRepresentationClass));
SWTBotEditor diagramEditor = openRepresentation(session, diagramDescriptionName, diagramName, expectedRepresentationClass, disableSnapToGridOnThisEditor);
assertTrue(diagramEditor instanceof SWTBotSiriusDiagramEditor);
return (SWTBotSiriusDiagramEditor) diagramEditor;
}
/**
* Open the first representation with the given representation description
* name and representation name.
*
* @param session
* The session containing the searched representations.
* @param representationDescriptionName
* the name of the representation description. <code>null</code>
* is not excepted.
* @param representationName
* the name of the representation
* @param expectedRepresentationClass
* the expected type of representation to found
* @return the editor of the first corresponding representation
*/
protected SWTBotEditor openRepresentation(Session session, String representationDescriptionName, final String representationName, Class<? extends DRepresentation> expectedRepresentationClass) {
return openRepresentation(session, representationDescriptionName, representationName, expectedRepresentationClass, false);
}
/**
* Open the first representation with the given representation description
* name and representation name.
*
* @param session
* The session containing the searched representations.
* @param representationDescriptionName
* the name of the representation description. <code>null</code>
* is not excepted.
* @param representationName
* the name of the representation
* @param expectedRepresentationClass
* the expected type of representation to found
* @param disableSnapToGridOnThisEditor
* true if the snapToGrid must be disable for this editor, false
* otherwise
* @return the editor of the first corresponding representation
*/
protected SWTBotEditor openRepresentation(Session session, String representationDescriptionName, final String representationName, Class<? extends DRepresentation> expectedRepresentationClass,
boolean disableSnapToGridOnThisEditor) {
// Get the diagram with this name
DRepresentation representation = getRepresentationWithName(session, representationDescriptionName, representationName);
TestCase.assertTrue("This representation should be a " + expectedRepresentationClass.getSimpleName(), expectedRepresentationClass.isInstance(representation));
// Open the corresponding editor
IEditorPart editorPart = DialectUIManager.INSTANCE.openEditor(session, representation, new NullProgressMonitor());
SWTBotUtils.waitAllUiEvents();
// Get the corresponding SWtBotEditor
SWTBotEditor swtBotEditor = null;
if (DDiagram.class.isAssignableFrom(expectedRepresentationClass)) {
swtBotEditor = SWTBotSiriusHelper.getSiriusDiagramEditor(editorPart.getTitle());
if (disableSnapToGridOnThisEditor) {
((SWTBotSiriusDiagramEditor) swtBotEditor).disableSnapToGrid();
}
} else {
swtBotEditor = SWTBotSiriusHelper.getSiriusEditor(editorPart.getTitle());
}
return swtBotEditor;
}
/**
* Get the widget bot corresponding to the button to set a workspace image
* on a selected node. If tabbar parameter at true, get the button of the
* tabbar, else get the button of the Appearance tab on the properties view.
*
* @param tabbar
* if tabbar parameter at true, get the button of the tabbar,
* else get the button of the Appearance tab on the properties
* view
* @param enabled
* true to check if the button must be enable, false to check if
* it shouldn't be enabled
* @return the widget bot corresponding to the button to set a workspace
* image on a selected node
*/
protected AbstractSWTBot<? extends Widget> getSetStyleToWorkspaceImageButton(boolean tabbar, boolean enabled) {
AbstractSWTBot<? extends Widget> wkpImageButton = null;
if (tabbar) {
wkpImageButton = getSetStyleToWorkspaceImageButtonFromTabbar();
} else {
wkpImageButton = getSetStyleToWorkspaceImageButtonFromAppearanceTab();
}
TestCase.assertNotNull("Can't find the SetStyleToWorkspaceImage button in the " + (tabbar ? "tabbar" : "Appearance tab"), wkpImageButton);
TestCase.assertEquals("The SetStyleToWorkspaceImage button should be " + (enabled ? "enabled" : "disabled"), enabled, wkpImageButton.isEnabled());
return wkpImageButton;
}
/**
* Get the widget bot corresponding to the button to
* "Reset style properties to default" on a selected node/edge. If tabbar
* parameter at true, get the button of the tabbar, else get the button of
* the Appearance tab on the properties view.
*
* @param tabbar
* if tabbar parameter at true, get the button of the tabbar,
* else get the button of the Appearance tab on the properties
* view
* @param enabled
* true to check if the button must be enable, false to check if
* it shouldn't be enabled
* @return the widget bot corresponding to the button to
* "Reset style properties to default" on a selected node/edge
*/
protected AbstractSWTBot<? extends Widget> getResetStylePropertiesToDefaultValuesButton(boolean tabbar, boolean enabled) {
AbstractSWTBot<? extends Widget> resetStylePropertiesToDefaultValuesButton = null;
if (!tabbar) {
resetStylePropertiesToDefaultValuesButton = getResetStylePropertiesToDefaultValuesButtonFromAppearanceTab();
} else {
resetStylePropertiesToDefaultValuesButton = getResetStylePropertiesToDefaultValuesButtonFromTabbar();
}
TestCase.assertNotNull("Can't find the \"" + ResetStylePropertiesToDefaultValuesAction.ACTION_NAME + "\" button in the " + (tabbar ? "tabbar" : "Appearance tab"),
resetStylePropertiesToDefaultValuesButton);
TestCase.assertEquals("The \"" + ResetStylePropertiesToDefaultValuesAction.ACTION_NAME + "\" button should be " + (enabled ? "enabled" : "disabled"), enabled,
resetStylePropertiesToDefaultValuesButton.isEnabled());
return resetStylePropertiesToDefaultValuesButton;
}
private SWTBotToolbarButton getSetStyleToWorkspaceImageButtonFromTabbar() {
return getTabbarButton(AbstractSiriusSwtBotGefTestCase.SET_STYLE_TO_WORKSPACE_IMAGE);
}
/**
* Returns the button allowing to reset the style to default from the
* tabbar.
*
* @return the button allowing to reset the style to default from the tabbar
*/
protected SWTBotToolbarButton getResetStylePropertiesToDefaultValuesButtonFromTabbar() {
return getTabbarButton(ResetStylePropertiesToDefaultValuesAction.ACTION_NAME);
}
private SWTBotButton getSetStyleToWorkspaceImageButtonFromAppearanceTab() {
return getSectionButton(3, AbstractSiriusSwtBotGefTestCase.SET_STYLE_TO_WORKSPACE_IMAGE);
}
/**
* Click on the specified button.
*
* @param button
* the specified button
*/
protected void click(AbstractSWTBot<? extends Widget> button) {
if (button instanceof SWTBotToolbarButton) {
((SWTBotToolbarButton) button).click();
} else if (button instanceof SWTBotButton) {
((SWTBotButton) button).click();
}
}
/**
* Returns the button allowing to reset the style to default from the
* appearance section.
*
* @return the button allowing to reset the style to default from the
* appearance section
*/
protected SWTBotButton getResetStylePropertiesToDefaultValuesButtonFromAppearanceTab() {
SWTBotButton resetStylePropertiesToDefaultValuesButtonFromAppearanceTab = null;
int buttonIndex = 4;
editor.show();
editor.setFocus();
ISelection selection = editor.getSelection();
if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
if (structuredSelection.getFirstElement() instanceof AbstractDiagramEdgeEditPart) {
buttonIndex = 3;
}
}
resetStylePropertiesToDefaultValuesButtonFromAppearanceTab = getSectionButton(buttonIndex, ResetStylePropertiesToDefaultValuesAction.ACTION_NAME);
return resetStylePropertiesToDefaultValuesButtonFromAppearanceTab;
}
/**
* Returns the button from the 'Appearance' section at the given index, that
* should have the given tooltip.
*
* @param index
* the index of the button to get from the 'Appearance' section
* @param tooltip
* the expected tooltip for this button
* @return the button from the 'Appearance' section at the given index, that
* should have the given tooltip
*/
protected SWTBotButton getSectionButton(int index, String tooltip) {
SWTBot propertiesBot = bot.viewByTitle("Properties").bot();
bot.viewByTitle("Properties").setFocus();
SWTBotSiriusHelper.selectPropertyTabItem("Appearance");
SWTBotButton button = propertiesBot.buttonInGroup("Fonts and Colors:", index);
TestCase.assertNotNull(button);
// get button from index and check requested tool-tip allows to check
// position
TestCase.assertEquals(tooltip, button.getToolTipText());
return button;
}
private SWTBotToolbarButton getTabbarButton(String tooltip) {
editor.show();
SWTBot tabbarBot = editor.bot();
SWTBotToolbarButton button = tabbarBot.toolbarButtonWithTooltip(tooltip);
TestCase.assertNotNull("No button found with tooltip \"" + tooltip + "\"", button);
return button;
}
private void initErrorLoggers() {
logListener = new ILogListener() {
@Override
public void logging(IStatus status, String plugin) {
if (status.getSeverity() == IStatus.ERROR) {
if (!"org.eclipse.ui.views.properties.tabbed".equals(status.getPlugin())
&& status.getMessage() != null
&& !status
.getMessage()
.startsWith(
"Contributor org.eclipse.ui.navigator.ProjectExplorer cannot be created., exception: org.eclipse.core.runtime.CoreException: Plug-in \"org.eclipse.ui.navigator.resources\" was unable to instantiate class \"org.eclipse.ui.internal.navigator.resources.workbench.TabbedPropertySheetTitleProvider\".")) {
errorOccurs(status, plugin);
}
}
}
};
Platform.addLogListener(logListener);
exceptionHandler = new UncaughtExceptionHandler() {
private final String sourcePlugin = "Uncaught exception";
@Override
public void uncaughtException(Thread t, Throwable e) {
IStatus status = new Status(IStatus.ERROR, sourcePlugin, sourcePlugin, e);
errorOccurs(status, sourcePlugin);
}
};
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
setErrorCatchActive(true);
}
private void disposeErrorLoggers() {
if (logListener != null) {
Platform.removeLogListener(logListener);
}
}
/**
* check if an error occurs.
*
* @return true if an error occurs.
*/
protected synchronized boolean doesAnErrorOccurs() {
if (errors != null) {
return errors.values().size() != 0;
}
return false;
}
/**
* check if an error catch is active.
*
* @return true if an error catch is active.
*/
protected synchronized boolean isErrorCatchActive() {
return errorCatchActive;
}
private synchronized void errorOccurs(IStatus status, String sourcePlugin) {
if (errorCatchActive) {
errors.put(sourcePlugin, status);
}
}
/**
* Activate or deactivate the external error detection: the test will fail
* in an error is logged or uncaught.
*
* @param errorCatchActive
* boolean to indicate if we activate or deactivate the external
* error detection
*/
protected synchronized void setErrorCatchActive(boolean errorCatchActive) {
this.errorCatchActive = errorCatchActive;
}
private void checkErrors() {
/* an exception occurs in another thread */
/*
* TODO : skip checkErrors when we are in a shouldSkipUnreliableTests
* mode. We have some unwanted resource notifications during the
* teardown on jenkins.
*/
if (!TestsUtil.shouldSkipUnreliableTests() && doesAnErrorOccurs()) {
Assert.fail(getErrorLoggersMessage());
}
}
/**
* Compute an error message from the detected errors.
*
* @return the error message.
*/
protected synchronized String getErrorLoggersMessage() {
StringBuilder log1 = new StringBuilder();
String br = "\n";
String testName = getClass().getName();
log1.append("Error(s) raised during test : " + testName).append(br);
for (Entry<String, Collection<IStatus>> entry : errors.asMap().entrySet()) {
String reporter = entry.getKey();
log1.append(". Log Plugin : " + reporter).append(br);
for (IStatus status : entry.getValue()) {
log1.append(" . " + getSeverity(status) + " from plugin:" + status.getPlugin() + ", message: " + status.getMessage() + ", exception: " + status.getException()).append(br);
appendStackTrace(log1, br, status);
}
log1.append(br);
}
return log1.toString();
}
private void appendStackTrace(StringBuilder log1, String br, IStatus status) {
PrintWriter pw = null;
String stacktrace = null;
if (status.getException() != null) {
try {
StringWriter sw = new StringWriter();
pw = new PrintWriter(sw);
// CHECKSTYLE:OFF
status.getException().printStackTrace(pw);
// CHECKSTYLE:ON
stacktrace = sw.toString();
} finally {
if (pw != null) {
pw.close();
}
if (stacktrace == null) {
stacktrace = status.getException().toString();
}
log1.append(" . Stack trace: " + stacktrace).append(br);
}
}
}
private String getSeverity(IStatus status) {
String severity;
switch (status.getSeverity()) {
case IStatus.OK:
severity = "Ok";
break;
case IStatus.INFO:
severity = "Info";
break;
case IStatus.WARNING:
severity = "Warning";
break;
case IStatus.CANCEL:
severity = "Cancel";
break;
case IStatus.ERROR:
severity = "Error";
break;
default:
severity = "Unspecified";
}
return severity;
}
// Cannot be overriden, we are trying to preserve and cleanup workspace for
// next tests
private void failureTearDown() throws Exception {
try {
SWTBotUtils.waitAllUiEvents();
// Close an eventual popup if the test failed and a popup remain
// opened
if (bot != null) {
/*
* replace shells() by this code to avoid a
* WidgetNotFoundException: The widget {null} was disposed.
*/
Shell[] shells = bot.getFinder().getShells();
ArrayList<SWTBotShell> result = new ArrayList<SWTBotShell>();
for (Shell shell : shells) {
if (!shell.isDisposed()) {
result.add(new SWTBotShell(shell));
}
}
final SWTBotShell[] foundShells = result.toArray(new SWTBotShell[] {});
for (final SWTBotShell swtBotShell : foundShells) {
// Close all opened windows except Eclipse
if (swtBotShell.isOpen()) {
for (IWorkbenchWindow w : PlatformUI.getWorkbench().getWorkbenchWindows()) {
if (swtBotShell.widget != w.getShell()) {
swtBotShell.close();
}
}
}
}
}
SWTBotUtils.waitAllUiEvents();
// Close all opened editors without saving before session closing to
// avoid ui events managed to late provoking exceptions for example
// because the session is already closed on ui event execution
closeAllEditors();
SWTBotUtils.waitAllUiEvents();
closeAllSessions();
SWTBotUtils.waitAllUiEvents();
Job.getJobManager().join(ResourceSyncClientNotifier.FAMILY, new NullProgressMonitor());
bot.closeAllEditors();
// Let the following loop delete the project.
designerProject = null;
SWTBotUtils.waitAllUiEvents();
// Delete projects created by the tests
for (final IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
designerPerspective.deleteProject(project.getName());
}
disposeErrorLoggers();
} finally {
// Reset the preferences changed during the test with the method
// changePreference. This is done in the finally block in case of
// ConcurrentModificationException during closeAllSession.
resetPreferences();
// Wait all ui events. Indeed, if we don't wait, the access to
// preferenceStore cause some NPE because the editor is not dispose
// :
// java.lang.NullPointerException
// at
// org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor$PropertyChangeListener.propertyChange(DiagramDocumentEditor.java:1661)
SWTBotUtils.waitAllUiEvents();
UIThreadRunnable.syncExec(new VoidResult() {
@Override
public void run() {
IPreferenceStore preferenceStore = DiagramUIPlugin.getPlugin().getPreferenceStore();
preferenceStore.setValue(IPreferenceConstants.PREF_ENABLE_ANIMATED_ZOOM, defaultEnableAnimatedZoom);
preferenceStore.setValue(IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT, defaultEnableAnimatedLayout);
}
});
setErrorCatchActive(false);
checkErrors();
}
}
private void resetPreferences() {
// Reset the preferences changed during the test with the method
// changePreference. This is done in the finally block in case of
// ConcurrentModificationException during closeAllSession.
IEclipsePreferences diagamCorePreferences = InstanceScope.INSTANCE.getNode(DiagramPlugin.ID);
for (String key : oldValueDiagramPreferences.keySet()) {
resetDiagramPreference(key, diagamCorePreferences);
}
IPreferenceStore diagramUIPreferences = DiagramUIPlugin.getPlugin().getPreferenceStore();
for (String key : oldValueDiagramUIPreferences.keySet()) {
resetDiagramUIPreference(key, diagramUIPreferences);
}
boolean currentUiPreference = diagramUIPreferences.getBoolean(SiriusDiagramUiPreferencesKeys.PREF_OLD_UI.name());
if (currentUiPreference) {
System.out.println("This test has not reset the oldUiPreference : " + this.getClass().getName() + " (it is currently true).");
}
IPreferenceStore platformPrefs = PlatformUI.getPreferenceStore();
for (String key : oldPlatformUIPreferences.keySet()) {
platformPrefs.setValue(key, (Boolean) oldPlatformUIPreferences.get(key));
}
IPreferenceStore viewpointUIPrefs = SiriusEditPlugin.getPlugin().getPreferenceStore();
for (String key : oldValueSiriusUIPreferences.keySet()) {
viewpointUIPrefs.setValue(key, (Boolean) oldValueSiriusUIPreferences.get(key));
}
IEclipsePreferences corePreferences = InstanceScope.INSTANCE.getNode(SiriusPlugin.ID);
for (String key : oldValueSiriusPreferences.keySet()) {
corePreferences.putBoolean(key, (Boolean) oldValueSiriusPreferences.get(key));
}
}
/**
* Open viewpoint specification model.
*
* @param viewpointSpecificationModel
* the name of viewpoint specification model (.odesing)
* @return odesignEditor
*/
public SWTBotVSMEditor openViewpointSpecificationModel(String viewpointSpecificationModel) {
SWTBotCommonHelper.openEditor(getProjectName(), viewpointSpecificationModel);
SWTBotVSMEditor odesignEditor = SWTBotVSMHelper.getVSMEditorContainingName(viewpointSpecificationModel);
odesignEditor.setFocus();
return odesignEditor;
}
/***
* Copy file to test run project.
*
* @param pluginId
* corresponding to project name containing data for test
* @param dataUnitDir
* the path of the directory containing datas
* @param fileNames
* the files to copy
*/
protected void copyFileToTestProject(String pluginId, String dataUnitDir, final String... fileNames) {
for (final String fileName : fileNames) {
EclipseTestsSupportHelper.INSTANCE.copyFile(pluginId, dataUnitDir + fileName, getProjectName() + "/" + fileName);
}
}
/**
* Explore the current {@link SWTBotSiriusDiagramEditor} edit part children
* recursively to find out a {@link TextEditPart} with the expected label.
*
* @param label
* the label of the expected {@link TextEditPart}
* @return a {@link TextEditPart} with the expected label if existing, null
* otherwise
*/
public SWTBotGefEditPart findTextEditPart(String label) {
return findTextEditPart(editor.rootEditPart(), label);
}
/**
* Explore the {@link SWTBotSiriusDiagramEditor} edit part children
* recursively to find out a {@link TextEditPart} with the expected label.
*
* @param designerEditor
* the current {@link SWTBotSiriusDiagramEditor} to look for a
* {@link TextEditPart}
* @param label
* the label of the expected {@link TextEditPart}
* @return a {@link TextEditPart} with the expected label if existing, null
* otherwise
*/
public SWTBotGefEditPart findTextEditPart(SWTBotSiriusDiagramEditor designerEditor, String label) {
return findTextEditPart(designerEditor.rootEditPart(), label);
}
/**
* Explore the {@link SWTBotGefEditPart} children recursively to find out a
* {@link TextEditPart} with the expected label.
*
* @param parent
* the {@link SWTBotGefEditPart} parent to start exploration
* @param label
* the label of the expected {@link TextEditPart}
* @return a {@link TextEditPart} with the expected label if existing, null
* otherwise
*/
public SWTBotGefEditPart findTextEditPart(SWTBotGefEditPart parent, String label) {
SWTBotGefEditPart result = null;
if (parent.part() instanceof TextEditPart) {
TextEditPart textEditPart = (TextEditPart) parent.part();
DescriptionCompartmentEditPart descriptionCompartmentEditPart = Iterables.getOnlyElement(Iterables.filter(textEditPart.getChildren(), DescriptionCompartmentEditPart.class));
if (descriptionCompartmentEditPart.getFigure() instanceof WrappingLabel && label.equals(((WrappingLabel) descriptionCompartmentEditPart.getFigure()).getText())) {
result = parent;
}
} else {
for (SWTBotGefEditPart child : parent.children()) {
SWTBotGefEditPart childrenResult = findTextEditPart(child, label);
if (childrenResult != null) {
return childrenResult;
}
}
}
return result;
}
/**
* Change the default font.
*
* @param fontName
* the font name to set as default.
* @return the previous default font name.
*/
protected String changeDefaultFontName(String fontName) {
IPreferenceStore preferenceStore = (IPreferenceStore) DiagramUIPlugin.DIAGRAM_PREFERENCES_HINT.getPreferenceStore();
FontData fontData = PreferenceConverter.getFontData(preferenceStore, IPreferenceConstants.PREF_DEFAULT_FONT);
// Get the actual font.
String oldName = fontData.getName();
// Change the font.
fontData.setName(fontName);
PreferenceConverter.setDefault(preferenceStore, IPreferenceConstants.PREF_DEFAULT_FONT, fontData);
return oldName;
}
/**
* Scan contained figures to find the background color of a figure typed as
* figureClass.
*
* @param editPart
* EditPart containing the figures that need investigation
* @param figureClass
* expected figure type
* @return the background color of the figure if found, null otherwise
*/
protected Color getFigureBackgroundColor(AbstractBorderedShapeEditPart editPart, Class<? extends Figure> figureClass) {
IFigure figure = editPart.getFigure();
if (figureClass.isInstance(figure)) {
return figure.getBackgroundColor();
} else {
return getFigureBackgroundColor(figure, figureClass);
}
}
/**
* Scan contained figures to find the background color of a figure typed as
* figureClass.
*
* @param parentFigure
* {@link Figure} containing the figures that need investigation
* @param figureClass
* expected figure type
* @return the background color of the figure if found, null otherwise
*/
protected Color getFigureBackgroundColor(IFigure parentFigure, Class<? extends Figure> figureClass) {
Iterable<? extends Figure> filter = Iterables.filter(parentFigure.getChildren(), figureClass);
if (Iterables.size(filter) == 1) {
return Iterables.getOnlyElement(filter).getBackgroundColor();
}
Color backgroundColor = null;
for (IFigure childFigure : Iterables.filter(parentFigure.getChildren(), IFigure.class)) {
backgroundColor = getFigureBackgroundColor(childFigure, figureClass);
if (backgroundColor != null) {
break;
}
}
return backgroundColor;
}
/**
* {@inheritDoc}
*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void tearDown() throws Exception {
failureTearDown();
new TestCaseCleaner(this).clearAllFields();
super.tearDown();
setErrorCatchActive(false);
}
}