Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.egit.ui.test')
-rw-r--r--org.eclipse.egit.ui.test/META-INF/MANIFEST.MF7
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java45
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/gitflow/AbstractGitflowHandlerTest.java6
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/submodules/SubmoduleFolderTest.java46
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewRepoDeletionTest.java143
5 files changed, 232 insertions, 15 deletions
diff --git a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
index c2eed536e3..88c0eac8ad 100644
--- a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
@@ -48,9 +48,10 @@ Import-Package: org.eclipse.egit.core.test;version="[4.3.0,4.4.0)",
org.eclipse.swtbot.swt.finder.utils,
org.eclipse.swtbot.swt.finder.waits,
org.eclipse.swtbot.swt.finder.widgets,
- org.junit;version="[4.3.1,5.0.0)",
- org.junit.runner;version="[4.3.1,5.0.0)",
- org.junit.runners;version="[4.3.1,5.0.0)",
+ org.junit;version="[4.7.0,5.0.0)",
+ org.junit.rules;version="[4.7.0,5.0.0)",
+ org.junit.runner;version="[4.7.0,5.0.0)",
+ org.junit.runners;version="[4.7.0,5.0.0)",
org.mockito;version="[1.8.0,1.9.0)",
org.mockito.stubbing;version="[1.8.0,1.9.0)",
org.osgi.framework;version="[1.4.0,2.0.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 22c2784ef4..ad75191040 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
@@ -36,6 +36,7 @@ import org.eclipse.egit.core.GitCorePreferences;
import org.eclipse.egit.core.GitProvider;
import org.eclipse.egit.core.JobFamilies;
import org.eclipse.egit.core.RepositoryCache;
+import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCache;
import org.eclipse.egit.core.internal.util.ResourceUtil;
import org.eclipse.egit.core.op.AddToIndexOperation;
@@ -47,7 +48,12 @@ import org.eclipse.egit.core.project.GitProjectData;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.core.test.TestUtils;
import org.eclipse.egit.ui.UIPreferences;
+import org.eclipse.egit.ui.internal.dialogs.CompareTreeView;
import org.eclipse.egit.ui.internal.push.PushOperationUI;
+import org.eclipse.egit.ui.internal.rebase.RebaseInteractiveView;
+import org.eclipse.egit.ui.internal.reflog.ReflogView;
+import org.eclipse.egit.ui.internal.repository.RepositoriesView;
+import org.eclipse.egit.ui.internal.staging.StagingView;
import org.eclipse.egit.ui.test.ContextMenuHelper;
import org.eclipse.egit.ui.test.Eclipse;
import org.eclipse.egit.ui.test.TestUtil;
@@ -69,10 +75,14 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.ui.history.IHistoryView;
+import org.eclipse.team.ui.synchronize.ISynchronizeView;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestName;
/**
* Base class for testing with local (file-system based) repositories
@@ -140,20 +150,39 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
protected static final String FILE2 = "test2.txt";
-
-
protected final static TestUtils testUtils = new TestUtils();
+ private static final String[] VIEWS_TO_CLOSE = { //
+ RebaseInteractiveView.VIEW_ID, //
+ ISynchronizeView.VIEW_ID, //
+ IHistoryView.VIEW_ID, //
+ CompareTreeView.ID, //
+ ReflogView.VIEW_ID, //
+ StagingView.VIEW_ID, //
+ RepositoriesView.VIEW_ID, //
+ "org.eclipse.search.ui.views.SearchView", //
+ "org.eclipse.ui.views.PropertySheet"
+ };
+
+ @Rule
+ public TestName testName = new TestName();
+
public File getTestDirectory() {
return testDirectory;
}
+ protected static void closeGitViews() {
+ for (String viewId : VIEWS_TO_CLOSE) {
+ TestUtil.hideView(viewId);
+ }
+ }
+
@Before
public void initNewTestDirectory() throws Exception {
testMethodNumber++;
// create standalone temporary directory
testDirectory = testUtils.createTempDir("LocalRepositoriesTests"
- + testMethodNumber);
+ + testMethodNumber + '_' + testName.getMethodName());
if (testDirectory.exists())
FileUtils.delete(testDirectory, FileUtils.RECURSIVE
| FileUtils.RETRY);
@@ -174,6 +203,7 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
TestUtil.processUIEvents();
// close all editors/dialogs
new Eclipse().reset();
+ closeGitViews();
TestUtil.processUIEvents();
// cleanup
for (IProject project : ResourcesPlugin.getWorkspace().getRoot()
@@ -201,6 +231,7 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
.getPreferenceStore()
.setValue(UIPreferences.SHOW_DETACHED_HEAD_WARNING,
false);
+ closeGitViews();
}
@AfterClass
@@ -208,11 +239,17 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
testUtils.deleteTempDirs();
}
- protected static void shutDownRepositories() {
+ protected static void shutDownRepositories() throws Exception {
RepositoryCache cache = Activator.getDefault().getRepositoryCache();
for(Repository repository:cache.getAllRepositories())
repository.close();
cache.clear();
+ IEclipsePreferences prefs = Activator.getDefault().getRepositoryUtil()
+ .getPreferences();
+ synchronized (prefs) {
+ prefs.put(RepositoryUtil.PREFS_DIRECTORIES, "");
+ prefs.flush();
+ }
}
protected static void deleteAllProjects() throws Exception {
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/gitflow/AbstractGitflowHandlerTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/gitflow/AbstractGitflowHandlerTest.java
index 03b5ee58e2..e048977827 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/gitflow/AbstractGitflowHandlerTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/gitflow/AbstractGitflowHandlerTest.java
@@ -37,6 +37,7 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
+import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
@@ -59,6 +60,11 @@ public abstract class AbstractGitflowHandlerTest extends LocalRepositoryTestCase
resetPreferences();
}
+ @After
+ public void teardown() {
+ repository = null;
+ }
+
private void resetPreferences() {
IPreferenceStore prefStore = Activator.getDefault()
.getPreferenceStore();
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/submodules/SubmoduleFolderTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/submodules/SubmoduleFolderTest.java
index 320344a6f9..7b77a7fa40 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/submodules/SubmoduleFolderTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/submodules/SubmoduleFolderTest.java
@@ -50,6 +50,7 @@ import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IViewPart;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -86,6 +87,8 @@ public class SubmoduleFolderTest extends LocalRepositoryTestCase {
parentRepositoryGitDir = createProjectAndCommitToRepository();
childRepositoryGitDir = createProjectAndCommitToRepository(CHILDREPO,
CHILDPROJECT);
+ Activator.getDefault().getRepositoryUtil()
+ .addConfiguredRepository(parentRepositoryGitDir);
parentRepository = lookupRepository(parentRepositoryGitDir);
childRepository = lookupRepository(childRepositoryGitDir);
parentProject = ResourcesPlugin.getWorkspace().getRoot()
@@ -137,6 +140,21 @@ public class SubmoduleFolderTest extends LocalRepositoryTestCase {
assertNotNull(subRepository);
}
+ @After
+ public void removeConfiguredRepositories() {
+ if (parentRepositoryGitDir != null) {
+ Activator.getDefault().getRepositoryUtil()
+ .removeDir(parentRepositoryGitDir);
+ }
+ if (childRepositoryGitDir != null) {
+ Activator.getDefault().getRepositoryUtil()
+ .removeDir(childRepositoryGitDir);
+ }
+ childRepository = null;
+ parentRepository = null;
+ subRepository = null;
+ }
+
@Test
public void testChildProjectMapsToSubRepo() {
RepositoryMapping mapping = RepositoryMapping.getMapping(childProject);
@@ -185,6 +203,7 @@ public class SubmoduleFolderTest extends LocalRepositoryTestCase {
TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE);
IndexDiffCacheEntry cache = Activator.getDefault().getIndexDiffCache()
.getIndexDiffCacheEntry(subRepository);
+ TestUtil.joinJobs(JobFamilies.INDEX_DIFF_CACHE_UPDATE);
IResourceState state = ResourceStateFactory.getInstance()
.get(cache.getIndexDiff(), file);
assertTrue("File should be staged", state.isStaged());
@@ -261,6 +280,24 @@ public class SubmoduleFolderTest extends LocalRepositoryTestCase {
node.getText().contains("[child"));
}
+ /**
+ * Tests that unrelated changes to the configured repositories do not
+ * prematurely remove submodules from the cache.
+ */
+ @Test
+ public void testRepoRemoval() {
+ Activator.getDefault().getRepositoryUtil()
+ .addConfiguredRepository(childRepositoryGitDir);
+ assertTrue("Should still have the subrepo in the cache",
+ containsRepo(Activator.getDefault().getRepositoryCache()
+ .getAllRepositories(), subRepository));
+ assertTrue("Should have changed the preference", Activator.getDefault()
+ .getRepositoryUtil().removeDir(childRepositoryGitDir));
+ assertTrue("Should still have the subrepo in the cache",
+ containsRepo(Activator.getDefault().getRepositoryCache()
+ .getAllRepositories(), subRepository));
+ }
+
@SuppressWarnings("restriction")
@Test
public void testHistoryFromProjectExplorerIsFromSubRepository()
@@ -283,6 +320,15 @@ public class SubmoduleFolderTest extends LocalRepositoryTestCase {
2);
}
+ private boolean containsRepo(Repository[] repositories, Repository needle) {
+ for (Repository repo : repositories) {
+ if (needle.equals(repo)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void assertRowCountInHistory(String msg, int expected)
throws Exception {
SWTBotView historyBot = TestUtil.showHistoryView();
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewRepoDeletionTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewRepoDeletionTest.java
index 730b0739dc..0399bed316 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewRepoDeletionTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewRepoDeletionTest.java
@@ -17,11 +17,22 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.util.Arrays;
import java.util.List;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCache;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.JobFamilies;
+import org.eclipse.egit.ui.internal.RepositoryCacheRule;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.test.ContextMenuHelper;
import org.eclipse.egit.ui.test.TestUtil;
@@ -32,6 +43,7 @@ import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -149,21 +161,109 @@ public class GitRepositoriesViewRepoDeletionTest extends
TestUtil.joinJobs(JobFamilies.REPOSITORY_DELETE);
refreshAndWait();
assertEmpty();
+
assertTrue(repositoryFile.exists());
assertTrue(
new File(repositoryFile.getParentFile(), PROJ1).isDirectory());
+ waitForDecorations();
+ closeGitViews();
+ TestUtil.waitForJobs(500, 5000);
+ // Session properties are stored in the Eclipse resource tree as part of
+ // the resource info. org.eclipse.core.internal.dtree.DataTreeLookup has
+ // a static LRU cache of lookup instances to avoid excessive strain on
+ // the garbage collector due to constantly allocating and then
+ // forgetting instances. These lookup objects may contain things
+ // recently queried or modified in the resource tree, such as session
+ // properties. As a result, the session properties of a deleted resource
+ // remain around a little longer than expected: to be precise, exactly
+ // 100 more queries on the Eclipse resource tree until the entry
+ // containing the session property is recycled. We use session
+ // properties to store the RepositoryMappings, which reference the
+ // repository.
+ //
+ // Make sure we clear that cache:
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IProject project = root.getProject(PROJ1);
+ for (int i = 0; i < 101; i++) {
+ // Number of iterations at least DataTreeLookup.POOL_SIZE!
+ // Use up one DataTreeLookup instance:
+ project.create(null);
+ if (i == 0) {
+ // Furthermore, the WorkbenchSourceProvider has still a
+ // reference to the last selection, which is our now long
+ // removed repository node! Arguably that's a strange thing, but
+ // strictly speaking, since there is no guarantee _when_ a
+ // weakly referenced object is removed, not even making
+ // WorkbenchSourceProvider.lastShowInSelection a WeakReference
+ // might help. Therefore, let's make sure that the last "show
+ // in" selection is no longer the RepositoryNode, which also
+ // still has a reference to the repository. That last "show in"
+ // selection is set when the "Shown in..." context menu is
+ // filled, which happens when the project explorer's context
+ // menu is activated. So we have to open that menu at least once
+ // with a different selection.
+ SWTBotTree explorerTree = TestUtil.getExplorerTree();
+ SWTBotTreeItem projectNode = TestUtil.navigateTo(explorerTree,
+ PROJ1);
+ projectNode.select();
+ ContextMenuHelper.isContextMenuItemEnabled(explorerTree, "New");
+ }
+ project.delete(true, true, null);
+ }
+ TestUtil.waitForJobs(500, 5000);
+ // And we may have the RepositoryChangeScanner running: use a job
+ // with a scheduling rule that ensures we have exclusive access.
+ final String[] results = { null, null };
+ Job verifier = new Job(testName.getMethodName()) {
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ // Wait for things to definitely quieten down. Note that
+ // waitForJobs only waits for running and waiting jobs, there
+ // may still be scheduled jobs that might wake up and run after
+ // that. TestUtil.joinJobs does really join, which also waits
+ // for scheduled jobs.
+ try {
+ TestUtil.joinJobs(
+ org.eclipse.egit.core.JobFamilies.INDEX_DIFF_CACHE_UPDATE);
+ // Is this job doing something when the view is hidden?
+ TestUtil.joinJobs(JobFamilies.REPO_VIEW_REFRESH);
+ waitForDecorations();
+ } catch (InterruptedException e) {
+ results[0] = "Interrupted";
+ Thread.currentThread().interrupt();
+ return Status.CANCEL_STATUS;
+ }
+ // Finally... Java does not give any guarantees about when
+ // exactly an only weakly reachable object is finalized and
+ // garbage collected.
+ waitForFinalization(5000);
+ // Experience shows that an explicit garbage collection run very
+ // often does reclaim only weakly reachable objects and set the
+ // weak references' referents to null, but not even that can be
+ // guaranteed! Whether or not it does may also depend on the
+ // configuration of the JVM (such as through command-line
+ // arguments).
+ Repository[] repositories = org.eclipse.egit.core.Activator
+ .getDefault().getRepositoryCache().getAllRepositories();
+ results[0] = Arrays.asList(repositories).toString();
+ IndexDiffCache indexDiffCache = org.eclipse.egit.core.Activator
+ .getDefault().getIndexDiffCache();
+ results[1] = indexDiffCache.currentCacheEntries().toString();
+ return Status.OK_STATUS;
+ }
+
+ };
+ verifier.setRule(new RepositoryCacheRule());
+ verifier.setSystem(true);
+ verifier.schedule();
+ verifier.join();
List<String> configuredRepos = org.eclipse.egit.core.Activator
.getDefault().getRepositoryUtil().getConfiguredRepositories();
assertTrue("Expected no configured repositories",
configuredRepos.isEmpty());
- Repository[] repositories = org.eclipse.egit.core.Activator.getDefault()
- .getRepositoryCache().getAllRepositories();
- assertEquals("Expected no cached repositories", 0, repositories.length);
- // A pity we can't mock the cache.
- IndexDiffCache indexDiffCache = org.eclipse.egit.core.Activator
- .getDefault().getIndexDiffCache();
- assertTrue("Expected no IndexDiffCache entries",
- indexDiffCache.currentCacheEntries().isEmpty());
+ assertEquals("Expected no cached repositories", "[]", results[0]);
+ assertEquals("Expected no IndexDiffCache entries", "[]", results[1]);
}
@Test
@@ -217,4 +317,31 @@ public class GitRepositoriesViewRepoDeletionTest extends
assertFalse(subRepo.getWorkTree().exists());
}
+ @SuppressWarnings("restriction")
+ private void waitForDecorations() throws InterruptedException {
+ TestUtil.joinJobs(
+ org.eclipse.ui.internal.decorators.DecoratorManager.FAMILY_DECORATE);
+ }
+
+ /**
+ * Best-effort attempt to get finalization to occur.
+ *
+ * @param maxMillis
+ * maximum amount of time in milliseconds to try getting the
+ * garbage collector to finalize objects
+ */
+ private void waitForFinalization(int maxMillis) {
+ long stop = System.currentTimeMillis() + maxMillis;
+ MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
+ do {
+ System.gc();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ } while (System.currentTimeMillis() < stop
+ && memoryBean.getObjectPendingFinalizationCount() > 0);
+ }
}

Back to the top