From 1b8a986588a6566cd0c1c830a88d0baedfd15019 Mon Sep 17 00:00:00 2001 From: "Nadya.Zabrodina" Date: Thu, 28 Mar 2013 17:14:55 +0400 Subject: [PATCH] tests for HgMergeProvider merged *old tests for HgMergedProvider refactored and added to another test class (adapted for new test framework ) *new HgTestUtil created and merged with old one *2 repositories created in base test class together *checking if statusBar is null before update widget added (because status bar widget may be null for example in testMode, but project not disposed) --- .../hg4idea/status/ui/HgStatusWidget.java | 2 +- .../testSrc/hg4idea/test/HgPlatformTest.java | 27 ++- .../testSrc/hg4idea/test/HgTestUtil.java | 89 +++++++++ .../test/merge/HgMergeProviderTest.java | 126 ++++++++++++ .../hg4idea/test/HgMergeProviderTest.java | 185 ------------------ .../org/zmlx/hg4idea/test/HgTestUtil.java | 51 ----- 6 files changed, 238 insertions(+), 242 deletions(-) create mode 100644 plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java delete mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java delete mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java index 11a7a09f5d68..a5724010ba1e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java @@ -146,7 +146,7 @@ public class HgStatusWidget extends EditorBasedWidget implements StatusBarWidget int maxLength = MAX_STRING.length(); myText = StringUtil.shortenTextWithEllipsis(myText, maxLength, 5); - if (!isDisposed()) { + if (!isDisposed() && myStatusBar != null) { myStatusBar.updateWidget(ID()); } } diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java index 502e8fd7b6cc..e7bd4cdedac5 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java @@ -37,11 +37,11 @@ import static hg4idea.test.HgExecutor.hg; * The base class for tests of hg4idea plugin.
* Extend this test to write a test on Mercurial which has the following features/limitations: * * * @author Kirill Likhodedov @@ -51,11 +51,15 @@ public abstract class HgPlatformTest extends UsefulTestCase { protected Project myProject; protected VirtualFile myProjectRoot; protected VirtualFile myRepository; + protected VirtualFile myChildRepo; protected MergeProvider myMergeProvider; + protected static final String COMMIT_MESSAGE = "text"; + private IdeaProjectTestFixture myProjectFixture; protected static final String AFILE = "A.txt"; + protected static final String BFILE = "B.txt"; @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") protected HgPlatformTest() { @@ -82,6 +86,8 @@ public abstract class HgPlatformTest extends UsefulTestCase { assertNotNull(vcs); myMergeProvider = vcs.getMergeProvider(); assertNotNull(myMergeProvider); + + prepareSecondRepository(); } @Override @@ -117,4 +123,15 @@ public abstract class HgPlatformTest extends UsefulTestCase { hg("add file.txt"); hg("commit -m initial"); } + + private void prepareSecondRepository() throws IOException { + cd(myRepository); + hg("clone " + myRepository.getCanonicalPath() + " childRepo"); + myChildRepo = myRepository.findChild("childRepo"); + cd(myChildRepo); + hg("pull"); + hg("update"); + HgTestUtil.updateDirectoryMappings(myProject, myRepository); + HgTestUtil.updateDirectoryMappings(myProject, myChildRepo); + } } diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java new file mode 100644 index 000000000000..d3644d139b1c --- /dev/null +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java @@ -0,0 +1,89 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hg4idea.test; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsDirectoryMapping; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import org.zmlx.hg4idea.HgVcs; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Nadya Zabrodina + */ +public class HgTestUtil { + + public static void updateDirectoryMappings(Project project, VirtualFile mapRoot) { + if (project != null && (!project.isDefault()) && project.getBaseDir() != null && VfsUtil + .isAncestor(project.getBaseDir(), mapRoot, false)) { + mapRoot.refresh(false, false); + final String path = mapRoot.equals(project.getBaseDir()) ? "" : mapRoot.getPath(); + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); + final List vcsDirectoryMappings = new ArrayList(vcsManager.getDirectoryMappings()); + VcsDirectoryMapping mapping = new VcsDirectoryMapping(path, HgVcs.VCS_NAME); + for (int i = 0; i < vcsDirectoryMappings.size(); i++) { + final VcsDirectoryMapping m = vcsDirectoryMappings.get(i); + if (m.getDirectory().equals(path)) { + if (m.getVcs().length() == 0) { + vcsDirectoryMappings.set(i, mapping); + mapping = null; + break; + } + else if (m.getVcs().equals(mapping.getVcs())) { + mapping = null; + break; + } + } + } + if (mapping != null) { + vcsDirectoryMappings.add(mapping); + } + vcsManager.setDirectoryMappings(vcsDirectoryMappings); + vcsManager.updateActiveVcss(); + } + } + + private HgTestUtil() { + } + + /** + * Writes the given content to the file. + * + * @param file file which content will be substituted by the given one. + * @param content new file content + */ + public static void printToFile(VirtualFile file, String content) throws FileNotFoundException { + PrintStream centralPrinter = null; + try { + centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath()))); + centralPrinter.print(content); + centralPrinter.close(); + } + finally { + if (centralPrinter != null) { + centralPrinter.close(); + } + } + } +} diff --git a/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java index 74197b4a919d..c084259bac2c 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java @@ -15,12 +15,16 @@ */ package hg4idea.test.merge; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.merge.MergeData; import com.intellij.openapi.vfs.VirtualFile; import hg4idea.test.HgPlatformTest; +import hg4idea.test.HgTestUtil; import org.testng.Assert; +import java.io.IOException; + import static com.intellij.dvcs.test.Executor.*; import static hg4idea.test.HgExecutor.hg; @@ -66,6 +70,128 @@ public class HgMergeProviderTest extends HgPlatformTest { verifyMergeData(myRepository.findChild(FILENAME), "base", "base modify with b", "base modify with a"); } + /** + * Start with a file in both repositories. + * 1. Edit the file in parent repository, commit the change. + * 2. Edit the file in child repository, commit the change. + * 3. Update. + * 4. Test the MergeData from the MergeProvider to have correct data. + */ + public void testMergeWithCommittedLocalChange() throws Exception { + final Pair files = prepareFileInBothRepositories(); + final VirtualFile parentFile = files.first; + final VirtualFile childFile = files.second; + cd(myRepository); + HgTestUtil.printToFile(parentFile, "server"); + hg("commit -m " + COMMIT_MESSAGE); + // committing conflicting change + cd(myChildRepo); + HgTestUtil.printToFile(childFile, "local"); + hg("commit -m " + COMMIT_MESSAGE); + hg("pull"); + hg("update"); + hg("merge"); + verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server"); + } + + /** + * Start with a file in both repositories. + * 1. Edit the file in parent repository, commit the change. + * 2. Edit the file in child repository, don't commit the change. + * 3. Update. + * 4. Test the MergeData from the MergeProvider to have correct data. + */ + public void testMergeWithUncommittedLocalChange() throws Exception { + final Pair files = prepareFileInBothRepositories(); + final VirtualFile parentFile = files.first; + final VirtualFile childFile = files.second; + cd(myRepository); + HgTestUtil.printToFile(parentFile, "server"); + hg("commit -m " + COMMIT_MESSAGE); + + // uncommitted conflicting change + cd(myChildRepo); + HgTestUtil.printToFile(childFile, "local"); + hg("pull"); + hg("update"); + hg("merge"); + + verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server"); + } + + /** + * Start with a non fresh repository. + * 1. Add a file in parent repository, commit. + * 2. Add a file with the same name, but different content in child repository, commit. + * 3. Update. + * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty). + */ + public void testFileAddedAndCommitted() throws Exception { + // this is needed to have the same root changeset - otherwise conflicting root changeset will cause + // an error during 'hg pull': "abort: repository is unrelated" + prepareFileInBothRepositories(); + cd(myRepository); + touch(BFILE, "server"); + hg("add " + BFILE); + hg("commit -m " + COMMIT_MESSAGE); + + cd(myChildRepo); + touch(BFILE, "local"); + hg("add " + BFILE); + hg("commit -m " + COMMIT_MESSAGE); + + hg("pull"); + hg("update"); + hg("merge"); + + verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server"); + } + + /** + * Start with a non fresh repository. + * 1. Add a file in parent repository, commit. + * 2. Add a file with the same name, but different content in child repository, don't commit. + * 3. Update. + * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty). + */ + public void testFileAddedNotCommited() throws Exception { + // this is needed to have the same root changeset - otherwise conflicting root changeset will cause + // an error during 'hg pull': "abort: repository is unrelated" + prepareFileInBothRepositories(); + cd(myRepository); + touch(BFILE, "server"); + hg("add " + BFILE); + hg("commit -m " + COMMIT_MESSAGE); + + cd(myChildRepo); + touch(BFILE, "local"); + hg("add " + BFILE); + + hg("pull"); + hg("update"); + hg("merge"); + + verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server"); + } + + + /** + * Creates a file with initial content in the parent repository, pulls & updates it to the child repository. + * + * @return References to the files in parent and child repositories respectively. + */ + private Pair prepareFileInBothRepositories() throws IOException { + cd(myRepository); + touch(AFILE, "basic"); + hg("add " + AFILE); + hg("commit -m 'create file' "); + cd(myChildRepo); + hg("pull"); + hg("update"); + final VirtualFile childFile = myChildRepo.findChild(AFILE); + return Pair.create(myRepository.findChild(AFILE), childFile); + } + private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer) throws VcsException { final MergeData mergeData = myMergeProvider.loadRevisions(file); diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java deleted file mode 100644 index ca486678b082..000000000000 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.zmlx.hg4idea.test; - -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.merge.MergeData; -import com.intellij.openapi.vcs.merge.MergeProvider; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ui.UIUtil; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import org.zmlx.hg4idea.HgVcs; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.concurrent.atomic.AtomicReference; - -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; - -/** - * Tests HgMergeProvider for different merge situations. - * All Mercurial operations are performed natively to test only HgMergeProvider functionality. - * @author Kirill Likhodedov - */ -public class HgMergeProviderTest extends HgCollaborativeTest { - - private MergeProvider myMergeProvider; - - @BeforeMethod - @Override - protected void setUp(Method testMethod) throws Exception { - super.setUp(testMethod); - myMergeProvider = HgVcs.getInstance(myProject).getMergeProvider(); - assertNotNull(myMergeProvider); - } - - /** - * Start with a file in both repositories. - * 1. Edit the file in parent repository, commit the change. - * 2. Edit the file in child repository, commit the change. - * 3. Update. - * 4. Test the MergeData from the MergeProvider to have correct data. - */ - @Test - public void mergeWithCommittedLocalChange() throws Exception { - final Pair files = prepareFileInBothRepositories(); - final VirtualFile parentFile = files.first; - final VirtualFile childFile = files.second; - - HgTestUtil.printToFile(parentFile, "server"); - myParentRepo.commit(); - // committing conflicting change - HgTestUtil.printToFile(childFile, "local"); - myRepo.commit(); - - myRepo.pullUpdateMerge(); - - verifyMergeData(childFile, "basic", "local", "server"); - } - - /** - * Start with a file in both repositories. - * 1. Edit the file in parent repository, commit the change. - * 2. Edit the file in child repository, don't commit the change. - * 3. Update. - * 4. Test the MergeData from the MergeProvider to have correct data. - */ - @Test - public void mergeWithUncommittedLocalChange() throws Exception { - final Pair files = prepareFileInBothRepositories(); - final VirtualFile parentFile = files.first; - final VirtualFile childFile = files.second; - - HgTestUtil.printToFile(parentFile, "server"); - myParentRepo.commit(); - - // uncommitted conflicting change - HgTestUtil.printToFile(childFile, "local"); - - myRepo.pullUpdateMerge(); - - verifyMergeData(childFile, "basic", "local", "server"); - } - - /** - * Start with a non fresh repository. - * 1. Add a file in parent repository, commit. - * 2. Add a file with the same name, but different content in child repository, commit. - * 3. Update. - * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty). - */ - @Test - public void fileAddedAndCommitted() throws Exception { - // this is needed to have the same root changeset - otherwise conflicting root changeset will cause - // an error during 'hg pull': "abort: repository is unrelated" - prepareFileInBothRepositories(); - - myParentRepo.createFile("b.txt", "server"); - myParentRepo.addCommit(); - - final VirtualFile childFile = myRepo.createFile("b.txt", "local"); - myRepo.addCommit(); - - myRepo.pullUpdateMerge(); - - verifyMergeData(childFile, "", "local", "server"); - } - - /** - * Start with a non fresh repository. - * 1. Add a file in parent repository, commit. - * 2. Add a file with the same name, but different content in child repository, don't commit. - * 3. Update. - * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty). - */ - @Test - public void fileAddedNotCommited() throws Exception { - // this is needed to have the same root changeset - otherwise conflicting root changeset will cause - // an error during 'hg pull': "abort: repository is unrelated" - prepareFileInBothRepositories(); - - myParentRepo.createFile("b.txt", "server"); - myParentRepo.addCommit(); - - final VirtualFile childFile = myRepo.createFile("b.txt", "local"); - myRepo.add(); - - myRepo.pullUpdateMerge(); - - verifyMergeData(childFile, "", "local", "server"); - } - - private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer) throws Exception { - final AtomicReference mergeData = new AtomicReference(); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - @Override - public void run() { - try { - mergeData.set(myMergeProvider.loadRevisions(file)); - } catch (VcsException e) { - fail("Failed to load revisions", e); - } - } - }); - - assertEquals(mergeData.get().ORIGINAL, expectedBase); - assertEquals(mergeData.get().CURRENT, expectedLocal); - assertEquals(mergeData.get().LAST, expectedServer); - } - - private static void assertEquals(byte[] bytes, String s) { - Assert.assertEquals(new String(bytes), s); - } - - /** - * Creates a file with initial content in the parent repository, pulls & updates it to the child repository. - * @return References to the files in parent and child repositories respectively. - */ - private Pair prepareFileInBothRepositories() throws IOException { - final VirtualFile parentFile = myParentRepo.createFile("a.txt", "basic"); - myParentRepo.add(); - myParentRepo.commit(); - myRepo.pull(); - myRepo.update(); - final VirtualFile childFile = myRepo.getDir().findChild("a.txt"); - return Pair.create(parentFile, childFile); - } - -} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java deleted file mode 100644 index 875ddfa0081d..000000000000 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.zmlx.hg4idea.test; - -import com.intellij.openapi.vfs.VirtualFile; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; - -/** - * HgTestUtil is a collection of static utility methods for Mercurial tests. - * @author Kirill Likhodedov - */ -public class HgTestUtil { - - private HgTestUtil() {} - - /** - * Writes the given content to the file. - * @param file file which content will be substituted by the given one. - * @param content new file content - */ - public static void printToFile(VirtualFile file, String content) throws FileNotFoundException { - PrintStream centralPrinter = null; - try { - centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath()))); - centralPrinter.print(content); - centralPrinter.close(); - } finally { - if (centralPrinter != null) { - centralPrinter.close(); - } - } - } - -}