blob: 10b81bab41cc503c451a5614c31cea668e1b3f57 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2019 Red Hat Inc. and others
*
* 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:
* - Mickael Istria (Red Hat Inc.)
* - Lucas Bullen (Red Hat Inc.)
*******************************************************************************/
package org.eclipse.ui.tests.datatransfer;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.wizards.datatransfer.SmartImportRootWizardPage;
import org.eclipse.ui.internal.wizards.datatransfer.SmartImportWizard;
import org.eclipse.ui.tests.datatransfer.contributions.ImportMeProjectConfigurator;
import org.eclipse.ui.tests.harness.util.UITestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
/**
* @since 3.12
*
*/
@RunWith(BlockJUnit4ClassRunner.class)
public class SmartImportTests extends UITestCase {
private WizardDialog dialog;
public SmartImportTests() {
super(SmartImportTests.class.getName());
}
@Override
public void doSetUp() throws Exception {
super.doSetUp();
ImportMeProjectConfigurator.configuredProjects.clear();
clearAll();
}
@Override
public void doTearDown() throws Exception {
ImportMeProjectConfigurator.configuredProjects.clear();
try {
clearAll();
} finally {
super.doTearDown();
}
}
private void clearAll() throws CoreException, IOException {
processEvents();
boolean closed = true;
if (dialog != null && !dialog.getShell().isDisposed()) {
closed = dialog.close();
}
for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
IFile projectDescription = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
IPath projectDescriptionLocation = projectDescription != null ? projectDescription.getRawLocation() : null;
project.delete(false, false, new NullProgressMonitor());
// Bug 535940: The project description which may be created from the test run
// must be removed or further test runs may fail.
if (projectDescriptionLocation != null) {
Path projectDescriptionFile = projectDescriptionLocation.toFile().toPath();
if (Files.exists(projectDescriptionFile)) {
Files.delete(projectDescriptionFile);
}
}
}
waitForJobs(100, 300);
if (!closed) {
assertTrue("Wizard dialog was not properly closed!", closed);
}
}
public void runSmartImport(File source) throws OperationCanceledException, InterruptedException {
SmartImportWizard wizard = new SmartImportWizard();
wizard.setInitialImportSource(source);
proceedSmartImportWizard(wizard);
}
private void proceedSmartImportWizard(SmartImportWizard wizard) throws InterruptedException {
WizardDialog dialog = new WizardDialog(getWorkbench().getActiveWorkbenchWindow().getShell(), wizard);
try {
dialog.setBlockOnOpen(false);
dialog.open();
processEvents();
final Button okButton = getFinishButton(dialog.buttonBar);
assertNotNull(okButton);
processEventsUntil(() -> okButton.isEnabled(), -1);
wizard.performFinish();
waitForJobs(100, 1000); // give the job framework time to schedule the job
wizard.getImportJob().join();
waitForJobs(100, 5000); // give some time for asynchronous workspace jobs to complete
} finally {
if (!dialog.getShell().isDisposed()) {
dialog.close();
}
}
}
/**
* @param dialog
*/
private Button getFinishButton(Control control) {
if (control instanceof Button && ((Button) control).getText().equals(IDialogConstants.FINISH_LABEL)) {
return (Button)control;
} else if (control instanceof Composite) {
Button res = null;
for (Control child : ((Composite)control).getChildren()) {
res = getFinishButton(child);
if (res != null) {
return res;
}
}
}
return null;
}
@Test
public void testImport6Projects() throws IOException, OperationCanceledException, InterruptedException {
URL url = FileLocator
.toFileURL(getClass().getResource("/data/org.eclipse.datatransferArchives/ProjectsArchive.zip"));
File file = new File(url.getFile());
runSmartImport(file);
assertEquals(6, ResourcesPlugin.getWorkspace().getRoot().getProjects().length);
}
@Test
public void testImportModularProjectsWithSameName()
throws IOException, OperationCanceledException, InterruptedException {
URL url = FileLocator
.toFileURL(getClass().getResource("/data/org.eclipse.datatransferArchives/project"));
File file = new File(url.getFile());
runSmartImport(file);
// Check expected projects are there
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
assertEquals(10, projects.length);
Set<String> implProjectNames = new HashSet<>();
for (IProject project : projects) {
if (project.getLocation().lastSegment().equals("impl")) {
implProjectNames.add(project.getName());
}
}
assertEquals(3, implProjectNames.size());
assertTrue(implProjectNames.contains("impl"));
assertTrue(implProjectNames.contains("module2_impl"));
assertTrue(implProjectNames.contains("module3_impl"));
}
@Test
public void testImportProjectWithExistingName()
throws IOException, OperationCanceledException, InterruptedException {
URL url = FileLocator
.toFileURL(getClass()
.getResource("/data/org.eclipse.datatransferArchives/sameNameProject1/sameNameProject"));
File file = new File(url.getFile());
runSmartImport(file);
// Check expected project is there
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
assertEquals(1, projects.length);
url = FileLocator
.toFileURL(getClass()
.getResource("/data/org.eclipse.datatransferArchives/sameNameProject2/sameNameProject"));
file = new File(url.getFile());
SmartImportWizard wizard = new SmartImportWizard();
wizard.setInitialImportSource(file);
this.dialog = new WizardDialog(getWorkbench().getActiveWorkbenchWindow().getShell(), wizard);
dialog.setBlockOnOpen(false);
dialog.open();
processEvents();
processEventsUntil(() -> !dialog.getErrorMessage().isEmpty(), -1);
SmartImportRootWizardPage page = (SmartImportRootWizardPage) dialog.getCurrentPage();
CheckboxTreeViewer treeViewer = getTreeViewer((Composite) page.getControl());
assertNotNull(treeViewer);
assertEquals(1, treeViewer.getTree().getItemCount());
assertEquals(0, treeViewer.getCheckedElements().length);
assertEquals("Project with same name already imported", treeViewer.getTree().getItems()[0].getText(1));
}
private CheckboxTreeViewer getTreeViewer(Composite parent) {
for (Control control : parent.getChildren()) {
if (control instanceof FilteredTree) {
return (CheckboxTreeViewer) ((FilteredTree) control).getViewer();
} else if (control instanceof Composite) {
CheckboxTreeViewer res = getTreeViewer((Composite) control);
if (res != null) {
return res;
}
}
}
return null;
}
@Test
public void testConfigurationIgnoreNestedProjects()
throws IOException, OperationCanceledException, InterruptedException {
URL url = FileLocator
.toFileURL(getClass().getResource("/data/org.eclipse.datatransferArchives/projectSingleModule"));
File file = new File(url.getFile());
runSmartImport(file);
// Check expected projects are there
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
assertEquals(2, projects.length);
IProject rootProject = ResourcesPlugin.getWorkspace().getRoot().getProject("projectSingleModule");
assertTrue("Missing root project", rootProject.exists());
assertFalse("Root project shouldn't have been configured",
ImportMeProjectConfigurator.configuredProjects.contains(rootProject));
assertEquals("Should have one project configured", 1, ImportMeProjectConfigurator.configuredProjects.size());
Set<IProject> modules = new HashSet<>(Arrays.asList(projects));
modules.remove(rootProject);
assertEquals(modules.size(), ImportMeProjectConfigurator.configuredProjects.size());
assertTrue("All modules should be configured",
ImportMeProjectConfigurator.configuredProjects.containsAll(modules));
}
@Test
public void testCancelWizardCancelsJob() {
SmartImportWizard wizard = new SmartImportWizard();
wizard.setInitialImportSource(File.listRoots()[0]);
this.dialog = new WizardDialog(getWorkbench().getActiveWorkbenchWindow().getShell(), wizard);
dialog.setBlockOnOpen(false);
dialog.open();
SmartImportRootWizardPage page = (SmartImportRootWizardPage) dialog.getCurrentPage();
ProgressMonitorPart wizardProgressMonitor = page.getWizardProgressMonitor();
assertNotNull("Wizard should have a progress monitor", wizardProgressMonitor);
ToolItem stopButton = getStopButton(wizardProgressMonitor);
processEventsUntil(() -> stopButton.isEnabled(), 10000);
assertTrue("Wizard should show progress monitor", wizardProgressMonitor.isVisible());
assertTrue("Stop button should be enabled", stopButton.isEnabled());
Event clickButtonEvent = new Event();
clickButtonEvent.widget = stopButton;
clickButtonEvent.item = stopButton;
clickButtonEvent.type = SWT.Selection;
clickButtonEvent.doit = true;
clickButtonEvent.stateMask = SWT.BUTTON1;
stopButton.notifyListeners(SWT.Selection, clickButtonEvent);
processEventsUntil(() -> !wizardProgressMonitor.isVisible(), 10000);
assertFalse("Progress monitor should be hidden within 10 seconds", wizardProgressMonitor.isVisible());
}
private static ToolItem getStopButton(ProgressMonitorPart part) {
for (Control control : part.getChildren()) {
if (control instanceof ToolBar) {
for (ToolItem item : ((ToolBar) control).getItems()) {
if (item.getToolTipText().equals(JFaceResources.getString("ProgressMonitorPart.cancelToolTip"))) { //$NON-NLS-1$ ))
return item;
}
}
}
}
return null;
}
@Test
public void testInitialWorkingSets() throws Exception {
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
IWorkingSet workingSet = workingSetManager.createWorkingSet("testWorkingSet", new IAdaptable[0]);
workingSet.setId("org.eclipse.ui.resourceWorkingSetPage");
workingSetManager.addWorkingSet(workingSet);
File directoryToImport = Files
.createTempDirectory(getClass().getSimpleName() + "_" + System.currentTimeMillis()).toFile();
try {
SmartImportWizard wizard = new SmartImportWizard();
wizard.setInitialImportSource(directoryToImport);
wizard.setInitialWorkingSets(Collections.singleton(workingSet));
proceedSmartImportWizard(wizard);
assertEquals("Projects were not added to working set", 1, workingSet.getElements().length);
} finally {
for (File child : directoryToImport.listFiles()) {
child.delete();
}
directoryToImport.delete();
workingSetManager.removeWorkingSet(workingSet);
}
}
@Test
public void testChangedWorkingSets() throws Exception {
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
IWorkingSet workingSet = workingSetManager.createWorkingSet("testWorkingSet", new IAdaptable[0]);
workingSet.setId("org.eclipse.ui.resourceWorkingSetPage");
workingSetManager.addWorkingSet(workingSet);
IWorkingSet workingSet2 = workingSetManager.createWorkingSet("testWorkingSet2", new IAdaptable[0]);
workingSet2.setId("org.eclipse.ui.resourceWorkingSetPage");
workingSetManager.addWorkingSet(workingSet2);
WorkbenchPlugin.getDefault().getDialogSettings().put("workingset_selection_history",
new String[] { workingSet.getName(), workingSet2.getName() });
File directoryToImport = Files
.createTempDirectory(getClass().getSimpleName() + "_" + System.currentTimeMillis()).toFile();
try {
SmartImportWizard wizard = new SmartImportWizard();
wizard.setInitialImportSource(directoryToImport);
wizard.setInitialWorkingSets(Collections.singleton(workingSet));
this.dialog = new WizardDialog(getWorkbench().getActiveWorkbenchWindow().getShell(), wizard);
dialog.setBlockOnOpen(false);
dialog.open();
processEvents();
final Button okButton = getFinishButton(dialog.buttonBar);
assertNotNull(okButton);
processEventsUntil(() -> okButton.isEnabled(), -1);
SmartImportRootWizardPage page = (SmartImportRootWizardPage) dialog.getCurrentPage();
Combo combo = getComboWithSelection(workingSet.getName(), (Composite) page.getControl());
combo.select(1);
Event e = new Event();
e.widget = combo;
e.display = combo.getDisplay();
e.type = SWT.Selection;
e.text = workingSet2.getName();
e.index = 1;
combo.notifyListeners(SWT.Selection, e);
processEvents();
processEventsUntil(() -> okButton.isEnabled(), -1);
wizard.performFinish();
waitForJobs(100, 1000); // give the job framework time to schedule the job
wizard.getImportJob().join();
waitForJobs(100, 5000); // give some time for asynchronous workspace jobs to complete
assertEquals("WorkingSet2 should be selected", Collections.singleton(workingSet2),
page.getSelectedWorkingSets());
assertEquals("Projects were not added to working set", 1, workingSet2.getElements().length);
} finally {
for (File child : directoryToImport.listFiles()) {
child.delete();
}
directoryToImport.delete();
workingSetManager.removeWorkingSet(workingSet);
workingSetManager.removeWorkingSet(workingSet2);
}
}
private static Combo getComboWithSelection(String selection, Composite parent) {
for (Control control : parent.getChildren()) {
if (control instanceof Combo && ((Combo) control).getText().equals(selection)) {
return (Combo) control;
} else if (control instanceof Composite) {
Combo res = getComboWithSelection(selection, (Composite) control);
if (res != null) {
return res;
}
}
}
return null;
}
}