diff options
Diffstat (limited to 'org.eclipse.egit.ui.test')
3 files changed, 361 insertions, 60 deletions
diff --git a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF index ce28cd1ef0..2cb2ac23f9 100644 --- a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF +++ b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: org.apache.log4j;bundle-version="[1.0.0,2.0.0)", org.eclipse.ui;bundle-version="[3.4.0,4.0.0)", org.hamcrest;bundle-version="[1.1.0,2.0.0)", org.mockito;bundle-version="[1.8.0,1.9.0)", - org.objenesis;bundle-version="[1.0.0,2.0.0)" + org.objenesis;bundle-version="[1.0.0,2.0.0)", + org.eclipse.jdt.launching;bundle-version="[3.8.0,4.0.0)" Import-Package: org.eclipse.egit.core.test;version="[4.1.0,4.2.0)", org.eclipse.egit.gitflow;version="[4.1.0,4.2.0)", org.eclipse.egit.gitflow.op;version="[4.1.0,4.2.0)", diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java index dfe69aa962..dc7c247681 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java @@ -237,39 +237,12 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { protected File createProjectAndCommitToRepository(String repoName) throws Exception { - File gitDir = new File(new File(testDirectory, repoName), - Constants.DOT_GIT); - Repository myRepository = new RepositoryBuilder().setGitDir(gitDir) - .build(); - myRepository.create(); + Repository myRepository = createLocalTestRepository(repoName); + File gitDir = myRepository.getDirectory(); // we need to commit into master first - IProject firstProject = ResourcesPlugin.getWorkspace().getRoot() - .getProject(PROJ1); - - if (firstProject.exists()) { - firstProject.delete(true, null); - TestUtil.waitForJobs(100, 5000); - } - IProjectDescription desc = ResourcesPlugin.getWorkspace() - .newProjectDescription(PROJ1); - desc.setLocation(new Path(new File(myRepository.getWorkTree(), PROJ1) - .getPath())); - firstProject.create(desc, null); - firstProject.open(null); - TestUtil.waitForJobs(50, 5000); - - assertTrue("Project is not accessible: " + firstProject, - firstProject.isAccessible()); - - IFolder folder = firstProject.getFolder(FOLDER); - folder.create(false, true, null); - IFile textFile = folder.getFile(FILE1); - textFile.create(new ByteArrayInputStream("Hello, world" - .getBytes(firstProject.getDefaultCharset())), false, null); - IFile textFile2 = folder.getFile(FILE2); - textFile2.create(new ByteArrayInputStream("Some more content" - .getBytes(firstProject.getDefaultCharset())), false, null); + IProject firstProject = createStandardTestProjectInRepository( + myRepository, PROJ1); try { new ConnectProviderOperation(firstProject, gitDir).execute(null); @@ -278,34 +251,8 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { } assertConnected(firstProject); - IProject secondProject = ResourcesPlugin.getWorkspace().getRoot() - .getProject(PROJ2); - - if (secondProject.exists()) { - secondProject.delete(true, null); - TestUtil.waitForJobs(100, 5000); - } - - desc = ResourcesPlugin.getWorkspace().newProjectDescription(PROJ2); - desc.setLocation(new Path(new File(myRepository.getWorkTree(), PROJ2) - .getPath())); - secondProject.create(desc, null); - secondProject.open(null); - TestUtil.waitForJobs(50, 5000); - - assertTrue("Project is not accessible: " + secondProject, - secondProject.isAccessible()); - - IFolder secondfolder = secondProject.getFolder(FOLDER); - secondfolder.create(false, true, null); - IFile secondtextFile = secondfolder.getFile(FILE1); - secondtextFile.create(new ByteArrayInputStream("Hello, world" - .getBytes(firstProject.getDefaultCharset())), false, null); - IFile secondtextFile2 = secondfolder.getFile(FILE2); - secondtextFile2.create(new ByteArrayInputStream("Some more content" - .getBytes(firstProject.getDefaultCharset())), false, null); - - TestUtil.waitForJobs(50, 5000); + IProject secondProject = createStandardTestProjectInRepository( + myRepository, PROJ2); // TODO we should be able to hide the .project // IFile gitignore = secondPoject.getFile(".gitignore"); @@ -322,6 +269,12 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { IFile dotProject = firstProject.getFile(".project"); assertTrue(".project is not accessible: " + dotProject, dotProject.isAccessible()); + IFolder folder = firstProject.getFolder(FOLDER); + IFile textFile = folder.getFile(FILE1); + IFile textFile2 = folder.getFile(FILE2); + folder = secondProject.getFolder(FOLDER); + IFile secondtextFile = folder.getFile(FILE1); + IFile secondtextFile2 = folder.getFile(FILE2); IFile[] commitables = new IFile[] { dotProject, textFile, textFile2, secondtextFile, secondtextFile2 }; @@ -345,6 +298,50 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase { return gitDir; } + protected Repository createLocalTestRepository(String repoName) + throws IOException { + File gitDir = new File(new File(testDirectory, repoName), + Constants.DOT_GIT); + Repository myRepository = new RepositoryBuilder().setGitDir(gitDir) + .build(); + myRepository.create(); + return myRepository; + } + + protected IProject createStandardTestProjectInRepository( + Repository repository, String name) throws Exception { + IProject project = ResourcesPlugin.getWorkspace().getRoot() + .getProject(name); + + if (project.exists()) { + project.delete(true, null); + TestUtil.waitForJobs(100, 5000); + } + IProjectDescription desc = ResourcesPlugin.getWorkspace() + .newProjectDescription(name); + desc.setLocation( + new Path(new File(repository.getWorkTree(), name).getPath())); + project.create(desc, null); + project.open(null); + TestUtil.waitForJobs(50, 5000); + + assertTrue("Project is not accessible: " + project, + project.isAccessible()); + + IFolder folder = project.getFolder(FOLDER); + folder.create(false, true, null); + IFile textFile = folder.getFile(FILE1); + textFile.create( + new ByteArrayInputStream( + "Hello, world".getBytes(project.getDefaultCharset())), + false, null); + IFile textFile2 = folder.getFile(FILE2); + textFile2.create(new ByteArrayInputStream( + "Some more content".getBytes(project.getDefaultCharset())), + false, null); + return project; + } + protected RepositoryMapping assertConnected(IProject project) { RepositoryProvider provider = RepositoryProvider.getProvider(project, GitProvider.ID); diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/ShowBlameActionHandlerTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/ShowBlameActionHandlerTest.java new file mode 100644 index 0000000000..70dfdcd6cd --- /dev/null +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/ShowBlameActionHandlerTest.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (C) 2015, Thomas Wolf <thomas.wolf@paranor.ch> + * + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.test.team.actions; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceDescription; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.internal.indexdiff.IndexDiffCache; +import org.eclipse.egit.core.op.CommitOperation; +import org.eclipse.egit.core.op.ConnectProviderOperation; +import org.eclipse.egit.ui.common.LocalRepositoryTestCase; +import org.eclipse.egit.ui.internal.actions.ShowBlameActionHandler; +import org.eclipse.egit.ui.test.TestUtil; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.launching.JavaRuntime; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jgit.lib.Repository; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +/** + * JUnit plugin test (non-SWTBot) to verify that {@link ShowBlameActionHandler} + * is enabled not only for {@link IResource} but also for other things that + * might be visible in the package explorer and that adapt to {@link IResource}. + * We verify by setting up a Java project with a simple test class and then + * checking for {@link IFile}, {@link ICompilationUnit}, and {@link IType}. + * + * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=401156">Bug + * 401156</a> + */ +@RunWith(MockitoJUnitRunner.class) +public class ShowBlameActionHandlerTest extends LocalRepositoryTestCase { + + private static final String JAVA_PROJECT_NAME = "javatestProject"; + + private static final String SRC_FOLDER_NAME = "src"; + + private static final String BIN_FOLDER_NAME = "bin"; + + private static final String PACKAGE_NAME = "p"; + + private static final String JAVA_CLASS_NAME = "A"; + + private static final String JAVA_FILE_NAME = JAVA_CLASS_NAME + ".java"; + + private static final int MAX_DELETE_RETRY = 5; + + private static final int DELETE_RETRY_DELAY = 1000; // ms + + private static boolean initialAutobuild; + + private IJavaProject javaProject = null; + + @BeforeClass + public static void setupAutobuildOff() throws CoreException { + // Switch off autobuild -- we don't need it, and a build job might + // interfere with our removing the Java project at the end. + initialAutobuild = setAutobuild(false); + } + + @AfterClass + public static void teardownAutobuildReset() throws CoreException { + setAutobuild(initialAutobuild); + } + + @Before + public void setup() throws Exception { + javaProject = createJavaProjectAndCommitToRepository(); + } + + @After + public void teardown() throws CoreException { + removeJavaProject(); + } + + @Test + public void testShowAnnotationsFromProjectExplorer() throws Exception { + IProject project = javaProject.getProject(); + // Find the file + IFile file = project.getFolder(SRC_FOLDER_NAME).getFolder(PACKAGE_NAME) + .getFile(JAVA_FILE_NAME); + assertBlameEnabled(file, true); + // Now repeat the same with the ICompilationUnit. + IJavaElement element = JavaCore.create(file, javaProject); + assertTrue("Expected an ICompilationUnit", + element instanceof ICompilationUnit); + assertBlameEnabled(element, true); + // And with IType... + IType type = javaProject.findType(PACKAGE_NAME, JAVA_CLASS_NAME); + assertBlameEnabled(type, true); + // ... and finally with something that doesn't adapt to IResource: + assertBlameEnabled(this, false); + } + + @SuppressWarnings("boxing") + private void assertBlameEnabled(Object selected, boolean expected) { + assertNotNull("Nothing selected", selected); + IStructuredSelection selection = mock(IStructuredSelection.class); + when(selection.getFirstElement()).thenReturn(selected); + when(selection.size()).thenReturn(1); + ShowBlameActionHandler blame = new ShowBlameActionHandler(); + blame.setSelection(selection); + assertEquals("Unexpected enablement of blame action", expected, + blame.isEnabled()); + } + + // Java stuff below + + private static boolean setAutobuild(boolean value) throws CoreException { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IWorkspaceDescription desc = workspace.getDescription(); + boolean isAutoBuilding = desc.isAutoBuilding(); + if (isAutoBuilding != value) { + desc.setAutoBuilding(value); + workspace.setDescription(desc); + } + return isAutoBuilding; + } + + private IJavaProject createJavaProjectAndCommitToRepository() + throws Exception { + Repository myRepository = createLocalTestRepository(REPO1); + File gitDir = myRepository.getDirectory(); + IJavaProject jProject = createJavaProject(myRepository, + JAVA_PROJECT_NAME); + IProject project = jProject.getProject(); + try { + new ConnectProviderOperation(project, gitDir).execute(null); + } catch (Exception e) { + Activator.logError("Failed to connect project to repository", e); + } + assertConnected(project); + // Check in at least the java file + IFolder folder = project.getFolder(SRC_FOLDER_NAME) + .getFolder(PACKAGE_NAME); + IFile file = folder.getFile(JAVA_FILE_NAME); + + IFile[] commitables = new IFile[] { file }; + ArrayList<IFile> untracked = new ArrayList<IFile>(); + untracked.addAll(Arrays.asList(commitables)); + // commit to master + CommitOperation op = new CommitOperation(commitables, untracked, + TestUtil.TESTAUTHOR, TestUtil.TESTCOMMITTER, "Initial commit"); + op.execute(null); + + // Make sure cache entry is already listening for changes + IndexDiffCache cache = Activator.getDefault().getIndexDiffCache(); + cache.getIndexDiffCacheEntry(lookupRepository(gitDir)); + return jProject; + } + + private IJavaProject createJavaProject(final Repository repository, + final String projectName) throws Exception { + final IJavaProject[] jProjectHolder = new IJavaProject[] { null }; + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + @Override + public void run(IProgressMonitor monitor) throws CoreException { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject project = root.getProject(projectName); + if (project.exists()) { + project.delete(true, null); + TestUtil.waitForJobs(100, 5000); + } + IProjectDescription desc = ResourcesPlugin.getWorkspace() + .newProjectDescription(projectName); + desc.setLocation( + new Path(new File(repository.getWorkTree(), projectName) + .getPath())); + project.create(desc, null); + project.open(null); + TestUtil.waitForJobs(50, 5000); + // Create a "bin" folder + IFolder bin = project.getFolder(BIN_FOLDER_NAME); + if (!bin.exists()) { + bin.create(IResource.FORCE | IResource.DERIVED, true, null); + } + IPath outputLocation = bin.getFullPath(); + // Create a "src" folder + IFolder src = project.getFolder(SRC_FOLDER_NAME); + if (!src.exists()) { + src.create(IResource.FORCE, true, null); + } + addNatureToProject(project, JavaCore.NATURE_ID); + // Set up the IJavaProject + IJavaProject jProject = JavaCore.create(project); + IPackageFragmentRoot srcContainer = jProject + .getPackageFragmentRoot(src); + IClasspathEntry srcEntry = JavaCore + .newSourceEntry(srcContainer.getPath()); + // Create a JRE classpath entry using the default JRE + IClasspathEntry jreEntry = JavaRuntime + .getDefaultJREContainerEntry(); + jProject.setRawClasspath( + new IClasspathEntry[] { srcEntry, jreEntry }, + outputLocation, true, null); + // Create a package with a single test class + IPackageFragment javaPackage = srcContainer + .createPackageFragment(PACKAGE_NAME, true, null); + javaPackage + .createCompilationUnit(JAVA_FILE_NAME, + "package " + PACKAGE_NAME + ";\nclass " + + JAVA_CLASS_NAME + " {\n\n}", + true, null); + jProjectHolder[0] = jProject; + } + }; + ResourcesPlugin.getWorkspace().run(runnable, null); + return jProjectHolder[0]; + } + + private void addNatureToProject(IProject proj, String natureId) + throws CoreException { + IProjectDescription description = proj.getDescription(); + String[] prevNatures = description.getNatureIds(); + String[] newNatures = new String[prevNatures.length + 1]; + System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); + newNatures[prevNatures.length] = natureId; + description.setNatureIds(newNatures); + proj.setDescription(description, null); + } + + private void removeJavaProject() throws CoreException { + if (javaProject == null) { + return; + } + final IProject project = javaProject.getProject(); + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + @Override + public void run(IProgressMonitor monitor) throws CoreException { + // Following code inspired by {@link + // org.eclipse.jdt.testplugin.JavaProjectHelper#delete(IResource)}. + // I don't like all this sleeping at all, but apparently it's + // needed because the Java indexer might still run and hold on + // to some resources. + for (int i = 0; i < MAX_DELETE_RETRY; i++) { + try { + project.delete( + IResource.FORCE + | IResource.ALWAYS_DELETE_PROJECT_CONTENT, + null); + break; + } catch (CoreException e) { + if (i == MAX_DELETE_RETRY - 1) { + throw e; + } + try { + Activator.logInfo( + "Sleep before retrying to delete project " + + project.getLocationURI()); + // Give other threads the time to close and release + // the resource. + Thread.sleep(DELETE_RETRY_DELAY); + } catch (InterruptedException e1) { + // Ignore and retry to delete + } + } + } + + } + }; + ResourcesPlugin.getWorkspace().run(runnable, null); + } +} |