| /******************************************************************************* |
| * Copyright (c) 2014, 2015 Obeo. |
| * 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: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.emf.compare.git.pgm.internal.app; |
| |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.CURRENT; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.EOL; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.PARENT; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.SEP; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.google.common.collect.Sets; |
| |
| import java.nio.file.Path; |
| import java.util.Iterator; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.emf.compare.git.pgm.Returns; |
| import org.eclipse.emf.compare.git.pgm.internal.app.data.ContextSetup; |
| import org.eclipse.equinox.app.IApplication; |
| import org.eclipse.jgit.revwalk.RevCommit; |
| import org.junit.Test; |
| |
| /** |
| * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a> |
| */ |
| @SuppressWarnings("nls") |
| public class MergeApplicationTest extends AbstractApplicationTest { |
| |
| private ContextSetup contextSetup; |
| |
| /** |
| * <h3>Use case MER001</h3> |
| * <p> |
| * This use case is used to achieve a conflicting merge |
| * </p> |
| * |
| * @see ContextSetup#setupMER001() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER001() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER001(); |
| |
| runMerge(Returns.ABORTED, getShortId("branch_c")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Auto-merging failed in ").append("MER001/model.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER001/model.uml").append(EOL); |
| expectedOut.append("Automatic merge failed; fix conflicts and then commit the result.").append(EOL) |
| .append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| assertNoConflitMarker(contextSetup.getProjectPath().resolve("model.uml"), contextSetup |
| .getProjectPath().resolve("model.notation")); |
| |
| Set<String> expectedConflictingFilePath = Sets |
| .newHashSet("MER001/model.uml", "MER001/model.notation"); |
| assertEquals(expectedConflictingFilePath, getGit().status().call().getConflicting()); |
| } |
| |
| /** |
| * <h3>Test use case MER002</h3> |
| * <p> |
| * This aims to test a merge between two branches with more than commit between them (see history) |
| * </p> |
| * |
| * @see ContextSetup#setupMER002() |
| */ |
| @Test |
| public void testMER002() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER002(); |
| |
| runMerge(Returns.ABORTED, getShortId("branch_d")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Auto-merging failed in ").append("MER002/model.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER002/model.uml").append(EOL); |
| expectedOut.append("Automatic merge failed; fix conflicts and then commit the result.").append(EOL) |
| .append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| assertNoConflitMarker(contextSetup.getProjectPath().resolve("model.uml"), contextSetup |
| .getProjectPath().resolve("model.notation")); |
| |
| Set<String> expectedConflictingFilePath = Sets |
| .newHashSet("MER002/model.uml", "MER002/model.notation"); |
| assertEquals(expectedConflictingFilePath, getGit().status().call().getConflicting()); |
| |
| } |
| |
| /** |
| * <h3>Test the logical merge application on the current branch</h3> |
| * <p> |
| * This use case aims to produce a "Already up to date message". |
| * </p> |
| * <h3>History:</h3> |
| * |
| * <pre> |
| * Initial commit (PapyrusProject3) [Master] |
| * </pre> |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_alreadyUpToDate0() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_alreadyUpToDate0(); |
| |
| runMerge(Returns.COMPLETE, getShortId("master")); |
| |
| assertTrue(getGit().status().call().isClean()); |
| assertEquals(getGit().getRepository().resolve("HEAD").getName(), getLongId("master")); |
| assertOutputMessageEnd("Already up to date." + EOL + EOL); |
| } |
| |
| /** |
| * <h3>Test the logical application on previous commit of the current branch</h3> <h3>History:</h3> |
| * |
| * <pre> |
| * * Adds Class 1 [branch_b] |
| * | |
| * | |
| * Initial commit (PapyrusProject3) [branch_a] |
| * |
| * </pre> |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_alreadyUpToDate1() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_alreadyUpToDate1(); |
| |
| runMerge(Returns.COMPLETE, getShortId("branch_a")); |
| |
| assertOutputMessageEnd("Already up to date." + EOL + EOL); |
| |
| assertTrue(getGit().status().call().isClean()); |
| assertEquals(getGit().getRepository().resolve("HEAD").getName(), getLongId("branch_b")); |
| } |
| |
| /** |
| * <h3>Test with a setup file that references incorrect projects.</h3> |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_IncorrectProjectToImport_NotExistingProject() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_IncorrectProjectToImport_NotExistingProject(); |
| |
| // Sets args |
| getContext().addArg(getRepositoryPath().resolve(".git").toString(), |
| contextSetup.getUserSetupFile().getAbsolutePath(), getShortId("branch_a")); |
| |
| runCommand(Returns.COMPLETE); |
| |
| assertOutputMessageEnd("Already up to date." + EOL + EOL); |
| |
| assertTrue(getGit().status().call().isClean()); |
| assertEquals(getGit().getRepository().resolve("HEAD").getName(), getLongId("branch_a")); |
| } |
| |
| /** |
| * Test importing a project with a real complex path. |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_ProjectToImport_complexPath() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_ProjectToImport_complexPath(); |
| |
| runMerge(Returns.COMPLETE, getShortId("branch_a")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Already up to date.").append(EOL).append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| } |
| |
| /** |
| * Test using a setup file using a complex path |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_SetupFile_complexPath() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_SetupFile_complexPath(); |
| |
| runMerge(Returns.COMPLETE, getShortId("branch_a")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Already up to date.").append(EOL).append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| } |
| |
| /** |
| * Test using a setup file using a complex path |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003_RelativePaths() throws Exception { |
| // Mocks that the commands is launched from the git repository folder. |
| setCmdLocation(getRepositoryPath().toString()); |
| |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003_RelativePaths(); |
| |
| // Args : relative paths |
| String repoPathLastSegment = getRepositoryPath().toString().substring( |
| getRepositoryPath().toString().lastIndexOf(SEP) + 1); |
| String gitRelativePath = PARENT + SEP + repoPathLastSegment + SEP + ".git"; |
| String setupRelativePath = CURRENT + SEP + "a" + SEP + "b" + SEP + "c" + SEP + "setup.setup"; |
| |
| // Sets args |
| getContext().addArg(gitRelativePath, setupRelativePath, getShortId("branch_a")); |
| |
| runCommand(Returns.COMPLETE); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Already up to date.").append(EOL).append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| } |
| |
| /** |
| * <h3>Test the use case MER003</h3> |
| * <p> |
| * This use case aims to test a logical merge on a model with no conflict (Auto merging should succeed). |
| * </p> |
| * |
| * @see ContextSetup#setupMER003() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER003() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER003(); |
| |
| runMerge(Returns.COMPLETE, getShortId("branch_c"), "My message"); |
| |
| assertOutputMessageEnd("Merge made by 'recursive' strategy." + EOL + EOL); |
| |
| final String class1URIFragment = "_bB2fYC3HEeSN_5D5iyrZGQ"; |
| final String class2URIFragment = "_hfIr4C3HEeSN_5D5iyrZGQ"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model.uml"), class1URIFragment, |
| class2URIFragment); |
| |
| final String class2ShapeURIFragment = "_hfJS8C3HEeSN_5D5iyrZGQ"; |
| final String class1ShapeURIFragment = "_bB3tgC3HEeSN_5D5iyrZGQ"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model.notation"), |
| class1ShapeURIFragment, class2ShapeURIFragment); |
| |
| Iterator<RevCommit> it = getGit().log().call().iterator(); |
| RevCommit newHead = it.next(); |
| assertEquals("My message", newHead.getFullMessage()); |
| |
| } |
| |
| /** |
| * @see ContextSetup#setupMER004() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER004() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupCHE004(); |
| |
| runMerge(Returns.COMPLETE, getShortId("branch_c")); |
| |
| assertOutputMessageEnd("Merge made by 'recursive' strategy." + EOL + EOL); |
| |
| final String class1URIFragment = "_adib0C9QEeShUolneTgohg"; |
| final String class3URIFragment = "_lztC0C9QEeShUolneTgohg"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model.uml"), class1URIFragment, |
| class3URIFragment); |
| |
| final String class2URIFragment = "_a7N2UC9QEeShUolneTgohg"; |
| final String class4URIFragment = "_m3mv0C9QEeShUolneTgohg"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model2.uml"), class2URIFragment, |
| class4URIFragment); |
| |
| final String class1ShapeURIFragment = "_adjp8C9QEeShUolneTgohg"; |
| final String class3ShapeURIFragment = "_lzuQ8C9QEeShUolneTgohg"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model.notation"), |
| class1ShapeURIFragment, class3ShapeURIFragment); |
| |
| final String class2ShapeURIFragment = "_a7PEcC9QEeShUolneTgohg"; |
| final String class4ShapeURIFragment = "_m3nW4C9QEeShUolneTgohg"; |
| assertExistInResource(contextSetup.getProjectPath().resolve("model2.notation"), |
| class2ShapeURIFragment, class4ShapeURIFragment); |
| |
| } |
| |
| /** |
| * @see ContextSetup#setupMER005() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER005() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupMER005(); |
| |
| runMerge(Returns.ABORTED, getShortId("branch_c")); |
| |
| assertNoConflitMarker(contextSetup.getProjectPath().resolve("model.uml"),// |
| contextSetup.getProjectPath().resolve("model.notation"),// |
| contextSetup.getProjectPath().resolve("model2.uml"), // |
| contextSetup.getProjectPath().resolve("model2.notation")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Auto-merging failed in ").append("MER005/model.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER005/model.uml").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER005/model2.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER005/model2.uml").append(EOL); |
| expectedOut.append("Automatic merge failed; fix conflicts and then commit the result.").append(EOL) |
| .append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| Set<String> expectedConflictingFilePath = Sets.newHashSet("MER005/model.uml", |
| "MER005/model.notation", "MER005/model2.uml", "MER005/model2.notation"); |
| assertEquals(expectedConflictingFilePath, getGit().status().call().getConflicting()); |
| |
| } |
| |
| /** |
| * <h3>Test MER006</h3> |
| * <p> |
| * Successive conflicts on multiple models in multiple files (one file per model) |
| * </p> |
| * |
| * @see ContextSetup#setupMER006() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER006() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupCHE006(); |
| |
| runMerge(Returns.ABORTED, getShortId("branch_d")); |
| |
| assertNoConflitMarker(contextSetup.getProjectPath().resolve("model.uml"), // |
| contextSetup.getProjectPath().resolve("model.notation"), // |
| contextSetup.getProjectPath().resolve("model2.uml"), // |
| contextSetup.getProjectPath().resolve("model2.notation")); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Auto-merging failed in ").append("MER006/model.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER006/model.uml").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER006/model2.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("MER006/model2.uml").append(EOL); |
| expectedOut.append("Automatic merge failed; fix conflicts and then commit the result.").append(EOL) |
| .append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| Set<String> expectedConflictingFilePath = Sets.newHashSet("MER006/model.uml", |
| "MER006/model.notation", "MER006/model2.uml", "MER006/model2.notation"); |
| assertEquals(expectedConflictingFilePath, getGit().status().call().getConflicting()); |
| } |
| |
| /** |
| * <h3>Use case MER008</h3> |
| * <p> |
| * Single conflict on a fragmented model in multiple files (two files per model) |
| * </p> |
| * |
| * @see ContextSetup#setupMER008() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER008() throws Exception { |
| // implement this test once https://bugs.eclipse.org/bugs/show_bug.cgi?id=453709 resolved |
| } |
| |
| /** |
| * <h3>Use case MER009</h3> |
| * <p> |
| * Single conflict on a fragmented model in multiple files (two files per model) |
| * </p> |
| * |
| * @see ContextSetup#setupMER009() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER009() throws Exception { |
| // implement this test once https://bugs.eclipse.org/bugs/show_bug.cgi?id=453709 resolved |
| } |
| |
| /** |
| * Model conflict but no textual conflict. |
| * |
| * @see ContextSetup#setupREB011() |
| * @throws Exception |
| */ |
| @Test |
| public void testMER011() throws Exception { |
| contextSetup = new ContextSetup(getGit(), getTestTmpFolder()); |
| contextSetup.setupREB011(); |
| |
| runMerge(Returns.ABORTED, "branch_b"); |
| |
| StringBuilder expectedOut = new StringBuilder(); |
| expectedOut.append("Auto-merging failed in ").append("REB011/model.notation").append(EOL); |
| expectedOut.append("Auto-merging failed in ").append("REB011/model.uml").append(EOL); |
| expectedOut.append("Automatic merge failed; fix conflicts and then commit the result.").append(EOL) |
| .append(EOL); |
| assertOutputMessageEnd(expectedOut.toString()); |
| |
| // Checks that the expected file are marked as conflicting |
| assertEquals(Sets.newHashSet("REB011/model.notation", "REB011/model.uml"), getGit().status().call() |
| .getConflicting()); |
| // Checks that the model files were not corrupted by <<< and >>> markers. |
| Path projectPath = contextSetup.getProjectPath(); |
| assertNoConflitMarker(projectPath.resolve("model.uml"), // |
| projectPath.resolve("model.notation"),// |
| projectPath.resolve("model.di")); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.compare.git.pgm.internal.app.AbstractApplicationTest#buildApp() |
| */ |
| @Override |
| protected IApplication buildApp() { |
| return new MergeApplication(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.compare.git.pgm.internal.app.AbstractApplicationTest#getApp() |
| */ |
| @Override |
| protected MergeApplication getApp() { |
| return (MergeApplication)super.getApp(); |
| } |
| |
| private void runCommand(Returns expectedReturnCode) throws Exception { |
| resetApp(); |
| // Runs command |
| Object result = getApp().start(getContext()); |
| |
| printOut(); |
| printErr(); |
| |
| assertEquals(expectedReturnCode.code(), result); |
| IProject[] projectInWorkspace = ResourcesPlugin.getWorkspace().getRoot().getProjects(); |
| assertEquals(1, projectInWorkspace.length); |
| } |
| |
| private void runMerge(Returns expectedReturnCode, String commit) throws Exception { |
| runMerge(expectedReturnCode, commit, null); |
| } |
| |
| private void runMerge(Returns expectedReturnCode, String commit, String message) throws Exception { |
| resetContext(); |
| |
| getContext().addArg(getGit().getRepository().getDirectory().getAbsolutePath(), |
| contextSetup.getUserSetupFile().getAbsolutePath(), "--show-stack-trace", commit); |
| if (message != null) { |
| getContext().addArg("-m", message); |
| } |
| |
| runCommand(expectedReturnCode); |
| } |
| } |