blob: 5bf517b091bea6f706d9472d1be0387c5602db04 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Obeo
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.tests.swtbot.editor.vsm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.commands.common.CommandException;
import org.eclipse.core.resources.IProject;
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.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.sirius.tests.support.api.EclipseTestsSupportHelper;
import org.eclipse.sirius.tests.support.api.ICondition;
import org.eclipse.sirius.tests.support.api.TestsUtil;
import org.eclipse.sirius.tests.swtbot.Activator;
import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusHelper;
import org.eclipse.sirius.ui.tools.internal.views.modelexplorer.ModelExplorerView;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.eclipse.ui.IEditorReference;
/**
* Test the service implementation navigation from VSM service call in
* interpreted expressions.
*
* @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
*
*
*/
public class ServiceNavigationTest extends AbstractContentAssistTest {
private final class JavaEditorOpenedCondition implements ICondition {
private boolean javaEditorOpened;
/**
* @param javaEditorOpened
* true if the Java editor should be opened at some point.
* False it should never be opened.
*/
public JavaEditorOpenedCondition(boolean javaEditorOpened) {
this.javaEditorOpened = javaEditorOpened;
}
@Override
public boolean test() throws Exception {
SWTBotEditor activeEditor = bot.activeEditor();
IEditorReference reference = activeEditor.getReference();
return (javaEditorOpened && "org.eclipse.jdt.ui.CompilationUnitEditor".equals(reference.getId()))
|| (!javaEditorOpened && !"org.eclipse.jdt.ui.CompilationUnitEditor".equals(reference.getId()));
}
@Override
public String getFailureMessage() {
return "Java editor has not been opened";
}
}
private static final String BASIC_SERVICE_JAVA = "BasicService.java";
private static final String BASIC_SERVICE_JAVA2 = "BasicService2.java";
private static final String PATH = "data/unit/editor/vsm/completion/";
private static final String VSM_PROJECT_NAME = "org.eclipse.sirius.test.design";
private static final String VSM = "test2.odesign";
/**
*
*/
private static final String TESTED_ODESIGN_NAME = "new" + VSM;
private SWTBotView propertiesBot;
private SWTBotTreeItem diagramRepresentationDescription;
@Override
protected void onSetUpBeforeClosingWelcomePage() throws Exception {
super.onSetUpBeforeClosingWelcomePage();
final IWorkspaceDescription description = ResourcesPlugin.getWorkspace().getDescription();
description.setAutoBuilding(false);
ResourcesPlugin.getWorkspace().setDescription(description);
// Wait the end of the current build and/or refresh.
waitJobsBuildOrRefresh();
}
@Override
protected void onSetUpAfterOpeningDesignerPerspective() throws Exception {
setErrorCatchActive(false);
// Load the target platform, if not already done, to allow compilation
// of the java services
TestsUtil.setTargetPlatform(Activator.PLUGIN_ID);
}
/**
* Initialize the context by copying new resources and waiting all build
* process.
*
* @exception InterruptedException
* if this thread is interrupted while waiting
* @exception OperationCanceledException
* if the progress monitor is canceled while waiting
* @exception CoreException
* In case of problem during setting workspace description to
* disable auto build.
* @throws CommandException
*/
private void initContext(List<String> nodes, boolean selectPropertyField) throws InterruptedException, OperationCanceledException, CoreException, CommandException {
designerPerspectives.openSiriusPerspective();
// Copy the sample ecore model for type completion
copyFileToTestProject(Activator.PLUGIN_ID, PATH, "test.ecore");
// Create VSM Project.
IProject viewpointSpecificationProject = ViewpointSpecificationProjectCreationTest.createViewpointSpecificationProject(bot, VSM_PROJECT_NAME, VSM);
// Wait the end of the current build and/or refresh.
viewpointSpecificationProject.refreshLocal(IProject.DEPTH_INFINITE, new NullProgressMonitor());
waitJobsBuildOrRefresh();
// Define the imports in the VSM and add Ecore dependency
String MANIFEST_MF = "MANIFEST.MF";
EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + MANIFEST_MF, VSM_PROJECT_NAME + "/META-INF/" + MANIFEST_MF);
EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + VSM, VSM_PROJECT_NAME + "/description/" + TESTED_ODESIGN_NAME);
waitJobsBuildOrRefresh();
// We open the new design used by the test. We avoid replacing the
// already existing one because sometime the refresh is not correctly
// done and tests can fail.
SWTBotView modelExplorerView = bot.viewById(ModelExplorerView.ID);
modelExplorerView.setFocus();
SWTBotTreeItem projectNode = modelExplorerView.bot().tree().expandNode("org.eclipse.sirius.test.design");
SWTBotTreeItem descriptionNode = projectNode.expandNode("description");
SWTBotTreeItem designNode = descriptionNode.getNode(TESTED_ODESIGN_NAME);
designNode.doubleClick();
waitJobsBuildOrRefresh();
// Copy the Java Service file
char pathSeparator = '/';
String package_name = VSM_PROJECT_NAME;
package_name = package_name.replace('.', pathSeparator);
String dest = VSM_PROJECT_NAME + "/src/" + package_name + pathSeparator;
EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + BASIC_SERVICE_JAVA, dest + BASIC_SERVICE_JAVA);
EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + BASIC_SERVICE_JAVA2, dest + BASIC_SERVICE_JAVA2);
waitJobsBuildOrRefresh();
// Launch a manual build and wait the end of the workspace build
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
waitJobsBuildOrRefresh();
bot.activeEditor().setFocus();
SWTBotTreeItem lastExpandNode = bot.activeEditor().bot().tree().expandNode("platform:/resource/" + VSM_PROJECT_NAME + "/description/" + TESTED_ODESIGN_NAME);
for (String node : nodes) {
lastExpandNode = lastExpandNode.expandNode(node);
}
diagramRepresentationDescription = lastExpandNode;
lastExpandNode.select();
if (selectPropertyField) {
propertiesBot = bot.viewByTitle("Properties");
propertiesBot.setFocus();
SWTBotSiriusHelper.selectPropertyTabItem("General");
}
}
/**
* There is problem on linux with this test so we are waiting build or
* refresh jobs by joining them.
*/
private void waitJobsBuildOrRefresh() throws InterruptedException, OperationCanceledException {
Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new NullProgressMonitor());
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, new NullProgressMonitor());
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, new NullProgressMonitor());
Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, new NullProgressMonitor());
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, new NullProgressMonitor());
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the service interpreter.</li>
* <li>The cursor is at the starting position</li>
* <li>The service called is present in two different classes</li>
* <li>The service from which the navigation is done is the first one in the
* wizard.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationWithSameServiceInDifferentClasses() throws Exception {
List<String> expectedItemLabels = new ArrayList<>();
expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
expectedItemLabels.add("BasicService2");
testNavigation("service:sampleService()", 2, expectedItemLabels, 0, 0);
}
/**
* Tests that double clicking a Java service declaration will open
* corresponding Java editor.
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationFromJavaExtensionDefinition() throws Exception {
initContext(Arrays.asList("test", "VP"), false);
SWTBotTreeItem javaExtensionItem = diagramRepresentationDescription.expandNode("org.eclipse.sirius.test.design.BasicService").select();
javaExtensionItem.doubleClick();
TestsUtil.waitUntil(new JavaEditorOpenedCondition(true));
}
/**
* Tests that double clicking a Java service declaration pointing at an
* unknown class opens a dialog with an error message.
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationFromJavaExtensionDefinitionError() throws Exception {
if (TestsUtil.shouldSkipUnreliableTests()) {
return;
}
initContext(Arrays.asList("test", "VP"), false);
SWTBotTreeItem javaExtensionItem = diagramRepresentationDescription.expandNode("org.eclipse.sirius.test.design.BasicService").select();
propertiesBot = bot.viewByTitle("Properties");
propertiesBot.setFocus();
SWTBotSiriusHelper.selectPropertyTabItem("General");
SWTBotText text = propertiesBot.bot().text(0);
text.setFocus();
text.setText("wrong service");
javaExtensionItem.doubleClick();
String message = bot.activeShell().getText();
assertEquals("An error dialog should have opened.", "Service class opening failure", message);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the service interpreter.</li>
* <li>The cursor is at the starting position</li>
* <li>The service called is present in two different classes</li>
* <li>The service from which the navigation is done is the second one in
* the wizard.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationWithSameServiceInDifferentClasses2() throws Exception {
List<String> expectedItemLabels = new ArrayList<>();
expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
expectedItemLabels.add("BasicService2");
testNavigation("service:sampleService()", 2, expectedItemLabels, 1, 0);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the service interpreter.</li>
* <li>The cursor is at the 12 index position</li>
* <li>The service called is present in one class</li>
* <li>The service is automatically opened in JAVA editor.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testSingleServiceNavigation() throws Exception {
testNavigation("service:sampleService(self)", 1, null, -1, 12);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the starting position</li>
* <li>No service should be detected at the cursor position. So nothing
* should be done.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationWithAqlInterpreterFirstPosition() throws Exception {
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 0);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the last position</li>
* <li>No service should be detected at the cursor position. So nothing
* should be done.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationWithAqlInterpreterLastPosition() throws Exception {
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 55);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the 27 index position</li>
* <li>No service should be detected at the cursor position. So nothing
* should be done.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testServiceNavigationWithAqlInterpreterMiddlePosition() throws Exception {
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 27);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the 13 index position</li>
* <li>The service call at cursor position is present in two different
* classes</li>
* <li>The service from which the navigation is done is the second one in
* the wizard.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testDualServiceNavigationWithAqlInterpreter() throws Exception {
List<String> expectedItemLabels = new ArrayList<>();
expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
expectedItemLabels.add("BasicService2");
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 13);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the 9 index position</li>
* <li>The service call at cursor position is present in two different
* classes</li>
* <li>The service from which the navigation is done is the second one in
* the wizard.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testDualServiceNavigationWithAqlInterpreter2() throws Exception {
List<String> expectedItemLabels = new ArrayList<>();
expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
expectedItemLabels.add("BasicService2");
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 9);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the 23 index position</li>
* <li>The service call at cursor position is present in two different
* classes</li>
* <li>The service from which the navigation is done is the second one in
* the wizard.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testDualServiceNavigationWithAqlInterpreter3() throws Exception {
List<String> expectedItemLabels = new ArrayList<>();
expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
expectedItemLabels.add("BasicService2");
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 23);
}
/**
* Check that Java service navigation from F3 key and a VSM expression works
* in the following context:
* <ul>
* <li>The expression calls the AQL interpreter.</li>
* <li>The cursor is at the 38 index position</li>
* <li>The service call at cursor position is present in one class</li>
* <li>The service is automatically opened in JAVA editor.</li>
* </ul>
*
* @exception Exception
* if a problem occurs.
*/
public void testSingleServiceNavigationWithAqlInterpreter() throws Exception {
testNavigation("aql:self.sampleService() and self.sampleService(self)->", 1, null, -1, 38);
}
/**
* Tests that Java service navigation from VSM expression is the expected
* one.
*
* @param vsmExpression
* the VSM expression used to test Java service navigation.
* @param matchingJavaServiceNumber
* the number of Java service that should be proposed for
* navigation.
* @param expectedItemLabels
* The Java service item's labels in their wizard's order.
* @param javaServiceIndex
* the index of the Java service item to open with Java editor
* when in Java service navigation wizard.
* @param cursorPosition
* the cursor position in the VSM expression before triggering
* navigation with F3 key.
*
* @throws InterruptedException
* if a problem occurs.
* @throws CoreException
* if a problem occurs.
* @throws CommandException
* if a problem occurs.
*/
protected void testNavigation(String vsmExpression, int matchingJavaServiceNumber, List<String> expectedItemLabels, int javaServiceIndex, int cursorPosition)
throws InterruptedException, CoreException, CommandException {
if (TestsUtil.shouldSkipUnreliableTests()) {
return;
}
initContext(Arrays.asList("test", "VP", "Diag"), true);
// Init the Precondition Expression
SWTBotText precondition = propertiesBot.bot().text(3);
precondition.setFocus();
precondition.setText(vsmExpression);
TestsUtil.waitUntil(new ICondition() {
@Override
public boolean test() throws Exception {
return vsmExpression.equals(precondition.getText());
}
@Override
public String getFailureMessage() {
return null;
}
});
Display.getDefault().asyncExec(() -> {
// bot.pressShortcut does not work
precondition.widget.setSelection(cursorPosition);
Event event = new Event();
event.keyCode = SWT.F3;
precondition.widget.notifyListeners(SWT.KeyDown, event);
});
if (matchingJavaServiceNumber > 0) {
if (matchingJavaServiceNumber > 1) {
TestsUtil.waitUntil(new ICondition() {
@Override
public boolean test() throws Exception {
SWTBotShell shell = null;
try {
shell = bot.shell("Service navigation");
} catch (Exception e) {
// do nothing
}
return shell != null;
}
@Override
public String getFailureMessage() {
return "Service navigation wizard did not open.";
}
}, 10000);
SWTBotShell shell = bot.shell("Service navigation");
SWTBot wizardBot = shell.bot();
SWTBotTable table = wizardBot.table(0);
TestsUtil.waitUntil(new ICondition() {
@Override
public boolean test() throws Exception {
return table.rowCount() > 0;
}
@Override
public String getFailureMessage() {
return "The type navigation wizard was not filled with target Java services.";
}
}, 15000);
assertEquals("Wrong number of matching Java service implementations.", matchingJavaServiceNumber, table.rowCount());
if (expectedItemLabels != null) {
for (int i = 0; i < expectedItemLabels.size(); i++) {
SWTBotTableItem tableItem = table.getTableItem(i);
assertEquals("Unknown service: " + tableItem.getText(), expectedItemLabels.get(i), tableItem.getText());
}
}
if (javaServiceIndex >= 0) {
table.select(javaServiceIndex);
wizardBot.button(TestsUtil.isPhotonPlatformOrLater() ? "Open" : "OK").click();
}
}
TestsUtil.waitUntil(new JavaEditorOpenedCondition(true));
}
if (matchingJavaServiceNumber == 0) {
TestsUtil.waitUntil(new JavaEditorOpenedCondition(false));
}
}
}