/*******************************************************************************
* Copyright (C) 2011, 2013 Tasktop Technologies Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Benjamin Muskalla (benjamin.muskalla@tasktop.com) - initial implementation
*******************************************************************************/
package org.eclipse.egit.ui.operations;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ModelProvider;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.JobFamilies;
import org.eclipse.egit.ui.common.LocalRepositoryTestCase;
import org.eclipse.egit.ui.internal.operations.GitScopeOperation;
import org.eclipse.egit.ui.internal.operations.GitScopeOperationFactory;
import org.eclipse.egit.ui.internal.operations.GitScopeUtil;
import org.eclipse.egit.ui.test.TestUtil;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.team.core.subscribers.SubscriberScopeManager;
import org.eclipse.ui.IWorkbenchPart;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
public class GitScopeUtilTest extends LocalRepositoryTestCase {
public static final String MODEL_FILE = "base.model";
public static final String MODEL_EXTENSIONS_FILE = "base.model.extension";
private IWorkbenchPart part;
private File repositoryFile;
@Before
public void setup() throws Exception {
SWTBotView view = TestUtil.showExplorerView();
part = view.getViewReference().getPart(false);
repositoryFile = createProjectAndCommitToRepository();
GitScopeOperationFactory.setFactory(new GitScopeOperationFactory() {
@Override
public GitScopeOperation createGitScopeOperation(
IWorkbenchPart workbenchPart, SubscriberScopeManager manager) {
return new GitScopeOperation(workbenchPart, manager) {
@Override
protected boolean promptForInputChange(
String requestPreviewMessage,
IProgressMonitor monitor) {
// we will avoid the confirmation prompt in the tests
return false;
}
};
}
});
}
@AfterClass
public static void afterClassBase() throws Exception {
GitScopeOperationFactory.setFactory(new GitScopeOperationFactory());
}
@Test
// model provider already available via fragment.xml
public void modelProviderWithExtensionFiles() throws Exception {
IFile modelFile = createModelFiles();
IResource[] selectedResources = new IResource[] { modelFile };
IResource[] relatedChanges = getRelatedChangesInUIThread(selectedResources);
assertEquals(2, relatedChanges.length);
assertContainsResourceByName(relatedChanges, MODEL_FILE);
assertContainsResourceByName(relatedChanges, MODEL_EXTENSIONS_FILE);
}
@Test
public void relatedChangesWithNullResources() throws Exception {
IResource[] resources = GitScopeUtil.getRelatedChanges(part, null);
assertNotNull(resources);
assertEquals(0, resources.length);
}
@Test
public void relatedChangesWithEmptyResources() throws Exception {
IResource[] res = new IResource[0];
IResource[] resources = getRelatedChangesInUIThread(res);
assertNotNull(resources);
assertEquals(0, resources.length);
}
@Test(expected = IllegalArgumentException.class)
public void relatedChangesWithInvalidParams() throws Exception {
IResource[] res = new IResource[0];
GitScopeUtil.getRelatedChanges(null, res);
}
@Test
public void relatedChangesWithPrompt() throws Exception {
GitScopeOperationFactory.setFactory(new GitScopeOperationFactory());
final IFile modelFile = createModelFiles();
Repository repository = lookupRepository(repositoryFile);
Activator.getDefault().getIndexDiffCache()
.getIndexDiffCacheEntry(repository);
TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE);
final IResource[] selectedResources = new IResource[] { modelFile };
UIThreadRunnable.asyncExec(new VoidResult() {
public void run() {
try {
GitScopeUtil.getRelatedChanges(part, selectedResources);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
// Prompt because the files are untracked
SWTBotShell dialog = bot.shell("Selection Adjustment Required");
dialog.bot().button(IDialogConstants.OK_LABEL).click();
IFile modelExtensionsFile = modelFile.getProject().getFile(
MODEL_EXTENSIONS_FILE);
addAndCommit(modelExtensionsFile, "add model extensions file");
addAndCommit(modelFile, "add model file");
TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE);
// Both files are committed, should no longer prompt now
IResource[] relatedChanges = getRelatedChangesInUIThread(selectedResources);
assertEquals(2, relatedChanges.length);
assertContainsResourceByName(relatedChanges, MODEL_FILE);
assertContainsResourceByName(relatedChanges, MODEL_EXTENSIONS_FILE);
}
private IResource[] getRelatedChangesInUIThread(
final IResource[] selectedResources) {
final IResource[][] relatedChanges = new IResource[1][];
UIThreadRunnable.syncExec(new VoidResult() {
public void run() {
try {
relatedChanges[0] = GitScopeUtil.getRelatedChanges(part,
selectedResources);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
});
return relatedChanges[0];
}
private IFile createModelFiles() throws CoreException,
UnsupportedEncodingException {
IProject project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(PROJ1);
IFile modelFile = project.getFile(MODEL_FILE);
modelFile.create(
new ByteArrayInputStream("This is the base model"
.getBytes(project.getDefaultCharset())), false,
null);
IFile modelExtensionFile = project.getFile(MODEL_EXTENSIONS_FILE);
modelExtensionFile.create(
new ByteArrayInputStream("Some more content"
.getBytes(project.getDefaultCharset())), false,
null);
return modelFile;
}
private void assertContainsResourceByName(IResource[] relatedChanges,
String fileName) {
for (IResource resource : relatedChanges)
if (resource.getName().equals(fileName))
return;
fail("Resource " + fileName + " not found.");
}
/**
* Model provider that requires for all given {@link IResource}s an
* additional {@link IResource}s with an appended extension ".extension"
*
*/
public static class MockModelProvider extends ModelProvider {
@Override
public ResourceMapping[] getMappings(IResource resource,
ResourceMappingContext context, IProgressMonitor monitor)
throws CoreException {
ResourceMapping[] mappings = new ResourceMapping[2];
mappings[0] = getMappingAdapter(resource);
IPath resourcePath = resource.getFullPath();
IPath extensionFilePath = resourcePath
.addFileExtension("extension");
IWorkspaceRoot workspace = resource.getWorkspace().getRoot();
IFile extensionFile = workspace.getFile(extensionFilePath);
mappings[1] = getMappingAdapter(extensionFile);
return mappings;
}
private ResourceMapping getMappingAdapter(IResource resource) {
return (ResourceMapping) resource.getAdapter(ResourceMapping.class);
}
}
}