Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAxel Richard2014-05-21 09:26:26 +0000
committerAxel Richard2014-05-23 09:52:22 +0000
commit01962bfa99975d1ea70c2e08d629a63caca7da50 (patch)
treef0d439edc6a69e9e3186566c655f7c8fc97cc3cc
parent919590ee3a62b7f8e07efc5609c70ca505ea6846 (diff)
downloadorg.eclipse.emf.compare-01962bfa99975d1ea70c2e08d629a63caca7da50.tar.gz
org.eclipse.emf.compare-01962bfa99975d1ea70c2e08d629a63caca7da50.tar.xz
org.eclipse.emf.compare-01962bfa99975d1ea70c2e08d629a63caca7da50.zip
[435053] Add Pseudo conflicts tests.
In case of a pseudo conflict, no merge action is performed, even in ACCEPT/REJECT mode. Add tests for pseudo conflicts. Bug: 435053 Change-Id: I450c6676633502bb001829c889336023ee0d1cc1
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/PseudoConflictsMergeActionTest.java547
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java19
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/PseudoConflictMergeTest.java557
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/IndividualDiffInputData.java48
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/ancestor.nodes7
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/left.nodes11
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/right.nodes11
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/ancestor.nodes18
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/left.nodes18
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/right.nodes18
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/ancestor.nodes11
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/left.nodes7
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/right.nodes7
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/ancestor.nodes21
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/left.nodes21
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/right.nodes21
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java3
17 files changed, 1343 insertions, 2 deletions
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/PseudoConflictsMergeActionTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/PseudoConflictsMergeActionTest.java
new file mode 100644
index 000000000..109cba86f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/PseudoConflictsMergeActionTest.java
@@ -0,0 +1,547 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.collect.Iterables.filter;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.EMFCompare;
+import org.eclipse.emf.compare.domain.ICompareEditingDomain;
+import org.eclipse.emf.compare.domain.impl.EMFCompareEditingDomain;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
+import org.eclipse.emf.compare.internal.merge.MergeOperation;
+import org.eclipse.emf.compare.merge.IMerger;
+import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.DefaultGroupProvider;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.provider.TreeNodeItemProviderSpec;
+import org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.groups.provider.AbstractTestTreeNodeItemProviderAdapter;
+import org.eclipse.emf.compare.scope.DefaultComparisonScope;
+import org.eclipse.emf.compare.scope.IComparisonScope;
+import org.eclipse.emf.compare.tests.merge.data.IndividualDiffInputData;
+import org.eclipse.emf.edit.tree.TreeFactory;
+import org.eclipse.emf.edit.tree.TreeNode;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a>
+ */
+@SuppressWarnings({"restriction" })
+public class PseudoConflictsMergeActionTest extends AbstractTestTreeNodeItemProviderAdapter {
+
+ private static TreeNodeItemProviderSpec itemProvider;
+
+ private IMerger.Registry mergerRegistry;
+
+ private ICompareEditingDomain editingDomain;
+
+ private TreeNode leftAdd;
+
+ private TreeNode rightAdd;
+
+ private TreeNode leftDelete;
+
+ private TreeNode rightDelete;
+
+ private TreeNode leftChange;
+
+ private TreeNode rightChange;
+
+ @Override
+ @Before
+ public void before() throws IOException {
+ super.before();
+ itemProvider = (TreeNodeItemProviderSpec)treeItemProviderAdapterFactory.createTreeNodeAdapter();
+ mergerRegistry = EMFCompareRCPPlugin.getDefault().getMergerRegistry();
+
+ IndividualDiffInputData scopeProvider = new IndividualDiffInputData();
+ final IComparisonScope scope = new DefaultComparisonScope(scopeProvider
+ .getLeftPseudoConflictFullScope(), scopeProvider.getRightPseudoConflictFullScope(),
+ scopeProvider.getOriginPseudoConflictFullScope());
+ final Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ editingDomain = EMFCompareEditingDomain.create(scopeProvider.getLeftPseudoConflictFullScope(),
+ scopeProvider.getRightPseudoConflictFullScope(), scopeProvider
+ .getOriginPseudoConflictFullScope());
+
+ TreeNode nodeRootMatch = getNodeRootMatch(comparison);
+ TreeNode nodeD = nodeRootMatch.getChildren().get(0).getChildren().get(0);
+ EList<Diff> differences = comparison.getDifferences();
+
+ // Get left add difference
+ Diff leftAddDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD)));
+ leftAdd = getTreeNode(nodeRootMatch, leftAddDiff);
+
+ // Get right add difference
+ Diff rightAddDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.ADD)));
+ rightAdd = getTreeNode(nodeRootMatch, rightAddDiff);
+
+ // Get left delete difference
+ Diff leftDeleteDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE)));
+ leftDelete = getTreeNode(nodeRootMatch, leftDeleteDiff);
+
+ // Get right delete difference
+ Diff rightDeleteDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.DELETE)));
+ rightDelete = getTreeNode(nodeRootMatch, rightDeleteDiff);
+
+ // Get left change difference
+ Diff leftChangeDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.CHANGE)));
+ leftChange = getTreeNode(nodeD, leftChangeDiff);
+
+ // Get right change difference
+ Diff rightChangeDiff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.CHANGE)));
+ rightChange = getTreeNode(nodeD, rightChangeDiff);
+ }
+
+ @Test
+ public void testAcceptLocalLeftEditable() throws Exception {
+
+ final MergeMode accept = MergeMode.ACCEPT;
+ final boolean leftEditable = true;
+ final boolean rightEditable = false;
+
+ final TreeNode localAdd = leftAdd;
+ final TreeNode remoteAdd = rightAdd;
+ final TreeNode localDelete = leftDelete;
+ final TreeNode remoteDelete = rightDelete;
+ final TreeNode localChange = leftChange;
+ final TreeNode remoteChange = rightChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, accept, leftEditable,
+ rightEditable, null);
+
+ // ACCEPT Local Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertTrue(accept.isLeftToRight(localAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localAddDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // ACCEPT Local Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertTrue(accept.isLeftToRight(localDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // ACCEPT Local Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertTrue(accept.isLeftToRight(localChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testRejectLocalLeftEditable() throws Exception {
+
+ final MergeMode reject = MergeMode.REJECT;
+ final boolean leftEditable = true;
+ final boolean rightEditable = false;
+
+ final TreeNode localAdd = leftAdd;
+ final TreeNode remoteAdd = rightAdd;
+ final TreeNode localDelete = leftDelete;
+ final TreeNode remoteDelete = rightDelete;
+ final TreeNode localChange = leftChange;
+ final TreeNode remoteChange = rightChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, reject, leftEditable,
+ rightEditable, null);
+
+ // REJECT Local Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertFalse(reject.isLeftToRight(localAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject.getMergeAction(localAddDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // REJECT Local Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertFalse(reject.isLeftToRight(localDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject
+ .getMergeAction(localDeleteDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // REJECT Local Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertFalse(reject.isLeftToRight(localChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject
+ .getMergeAction(localChangeDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testAcceptRemoteLeftEditable() throws Exception {
+
+ final MergeMode accept = MergeMode.ACCEPT;
+ final boolean leftEditable = true;
+ final boolean rightEditable = false;
+
+ final TreeNode localAdd = leftAdd;
+ final TreeNode remoteAdd = rightAdd;
+ final TreeNode localDelete = leftDelete;
+ final TreeNode remoteDelete = rightDelete;
+ final TreeNode localChange = leftChange;
+ final TreeNode remoteChange = rightChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, accept, leftEditable,
+ rightEditable, null);
+
+ // ACCEPT Remote Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertFalse(accept.isLeftToRight(remoteAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteAddDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(remoteAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // ACCEPT Remote Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertFalse(accept.isLeftToRight(remoteDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // ACCEPT Remote Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertFalse(accept.isLeftToRight(remoteChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testRejectRemoteLeftEditable() throws Exception {
+
+ final MergeMode reject = MergeMode.REJECT;
+ final boolean leftEditable = true;
+ final boolean rightEditable = false;
+
+ final TreeNode localAdd = leftAdd;
+ final TreeNode remoteAdd = rightAdd;
+ final TreeNode localDelete = leftDelete;
+ final TreeNode remoteDelete = rightDelete;
+ final TreeNode localChange = leftChange;
+ final TreeNode remoteChange = rightChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, reject, leftEditable,
+ rightEditable, null);
+
+ // REJECT Remote Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertTrue(reject.isLeftToRight(remoteAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteAddDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // REJECT Remote Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertTrue(reject.isLeftToRight(remoteDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // REJECT Remote Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertTrue(reject.isLeftToRight(remoteChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testAcceptLocalRightEditable() throws Exception {
+
+ final MergeMode accept = MergeMode.ACCEPT;
+ final boolean leftEditable = false;
+ final boolean rightEditable = true;
+
+ final TreeNode localAdd = rightAdd;
+ final TreeNode remoteAdd = leftAdd;
+ final TreeNode localDelete = rightDelete;
+ final TreeNode remoteDelete = leftDelete;
+ final TreeNode localChange = rightChange;
+ final TreeNode remoteChange = leftChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, accept, leftEditable,
+ rightEditable, null);
+
+ // ACCEPT Local Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertFalse(accept.isLeftToRight(localAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localAddDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // ACCEPT Local Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertFalse(accept.isLeftToRight(localDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // ACCEPT Local Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertFalse(accept.isLeftToRight(localChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, accept.getMergeAction(localChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(localChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testRejectLocalRightEditable() throws Exception {
+
+ final MergeMode reject = MergeMode.REJECT;
+ final boolean leftEditable = false;
+ final boolean rightEditable = true;
+
+ final TreeNode localAdd = rightAdd;
+ final TreeNode remoteAdd = leftAdd;
+ final TreeNode localDelete = rightDelete;
+ final TreeNode remoteDelete = leftDelete;
+ final TreeNode localChange = rightChange;
+ final TreeNode remoteChange = leftChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, reject, leftEditable,
+ rightEditable, null);
+
+ // REJECT Local Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertTrue(reject.isLeftToRight(localAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject.getMergeAction(localAddDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // REJECT Local Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertTrue(reject.isLeftToRight(localDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject
+ .getMergeAction(localDeleteDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // REJECT Local Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertTrue(reject.isLeftToRight(localChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, reject
+ .getMergeAction(localChangeDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(localChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testAcceptRemoteRightEditable() throws Exception {
+
+ final MergeMode accept = MergeMode.ACCEPT;
+ final boolean leftEditable = false;
+ final boolean rightEditable = true;
+
+ final TreeNode localAdd = rightAdd;
+ final TreeNode remoteAdd = leftAdd;
+ final TreeNode localDelete = rightDelete;
+ final TreeNode remoteDelete = leftDelete;
+ final TreeNode localChange = rightChange;
+ final TreeNode remoteChange = leftChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, accept, leftEditable,
+ rightEditable, null);
+
+ // ACCEPT Remote Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertTrue(accept.isLeftToRight(remoteAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteAddDiff, leftEditable, rightEditable));
+ action.updateSelection(new StructuredSelection(remoteAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // ACCEPT Remote Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertTrue(accept.isLeftToRight(remoteDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // ACCEPT Remote Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertTrue(accept.isLeftToRight(remoteChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MERGE, accept.getMergeAction(remoteChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ @Test
+ public void testRejectRemoteRightEditable() throws Exception {
+
+ final MergeMode reject = MergeMode.REJECT;
+ final boolean leftEditable = false;
+ final boolean rightEditable = true;
+
+ final TreeNode localAdd = rightAdd;
+ final TreeNode remoteAdd = leftAdd;
+ final TreeNode localDelete = rightDelete;
+ final TreeNode remoteDelete = leftDelete;
+ final TreeNode localChange = rightChange;
+ final TreeNode remoteChange = leftChange;
+
+ MockMergeAction action = new MockMergeAction(editingDomain, mergerRegistry, reject, leftEditable,
+ rightEditable, null);
+
+ // REJECT Remote Add difference
+ Diff localAddDiff = (Diff)localAdd.getData();
+ Diff remoteAddDiff = (Diff)remoteAdd.getData();
+ assertFalse(reject.isLeftToRight(remoteAddDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteAddDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteAdd));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localAddDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteAddDiff.getState());
+
+ // REJECT Remote Delete difference
+ Diff localDeleteDiff = (Diff)localDelete.getData();
+ Diff remoteDeleteDiff = (Diff)remoteDelete.getData();
+ assertFalse(reject.isLeftToRight(remoteDeleteDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteDeleteDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteDelete));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localDeleteDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteDeleteDiff.getState());
+
+ // REJECT Remote Change difference
+ Diff localChangeDiff = (Diff)localChange.getData();
+ Diff remoteChangeDiff = (Diff)remoteChange.getData();
+ assertFalse(reject.isLeftToRight(remoteChangeDiff, leftEditable, rightEditable));
+ assertEquals(MergeOperation.MARK_AS_MERGE, reject.getMergeAction(remoteChangeDiff, leftEditable,
+ rightEditable));
+ action.updateSelection(new StructuredSelection(remoteChange));
+ action.run();
+ assertEquals(DifferenceState.MERGED, localChangeDiff.getState());
+ assertEquals(DifferenceState.MERGED, remoteChangeDiff.getState());
+
+ }
+
+ private static TreeNode getNodeRootMatch(Comparison comparison) throws IOException {
+ TreeNode treeNode = TreeFactory.eINSTANCE.createTreeNode();
+ treeNode.setData(comparison);
+ treeNode.eAdapters().add(new DefaultGroupProvider());
+
+ Collection<?> children = itemProvider.getChildren(treeNode);
+
+ Iterable<?> matches = filter(children, matchTreeNode);
+ return (TreeNode)matches.iterator().next();
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java
index 18b284dbe..340c0bd8b 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java
@@ -14,14 +14,22 @@ import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.textui.TestRunner;
+import org.eclipse.emf.compare.ComparePackage;
import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeActionTest;
+import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.PseudoConflictsMergeActionTest;
import org.eclipse.emf.compare.ide.ui.tests.unit.DependenciesTest;
+import org.eclipse.emf.compare.tests.nodes.NodesPackage;
+import org.eclipse.emf.compare.tests.nodes.util.NodesResourceFactoryImpl;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-@SuiteClasses({DependenciesTest.class, MergeActionTest.class, BugsTestSuite.class })
+@SuiteClasses({DependenciesTest.class, MergeActionTest.class, PseudoConflictsMergeActionTest.class,
+ BugsTestSuite.class })
public class AllTests {
/**
* Launches the test with the given arguments.
@@ -41,4 +49,13 @@ public class AllTests {
public static Test suite() {
return new JUnit4TestAdapter(AllTests.class);
}
+
+ @BeforeClass
+ public static void fillEMFRegistries() {
+ EPackage.Registry.INSTANCE.put(ComparePackage.eNS_URI, ComparePackage.eINSTANCE);
+ EPackage.Registry.INSTANCE.put(NodesPackage.eNS_URI, NodesPackage.eINSTANCE);
+
+ Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("nodes", //$NON-NLS-1$
+ new NodesResourceFactoryImpl());
+ }
}
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/PseudoConflictMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/PseudoConflictMergeTest.java
new file mode 100644
index 000000000..10109fc66
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/PseudoConflictMergeTest.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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.tests.merge;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.not;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.ConflictKind;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.EMFCompare;
+import org.eclipse.emf.compare.merge.IMerger;
+import org.eclipse.emf.compare.scope.DefaultComparisonScope;
+import org.eclipse.emf.compare.scope.IComparisonScope;
+import org.eclipse.emf.compare.tests.merge.data.IndividualDiffInputData;
+import org.eclipse.emf.compare.tests.nodes.Node;
+import org.eclipse.emf.compare.tests.nodes.NodeSingleValueAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.junit.Test;
+
+@SuppressWarnings("nls")
+public class PseudoConflictMergeTest {
+
+ private IndividualDiffInputData input = new IndividualDiffInputData();
+
+ private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+
+ @Test
+ public void testPseudoAdd_LtR_1() throws IOException {
+ // Pseudo Conflict between Node A[containmentRef1 add] from left side and Node A[containmentRef1 add]
+ // from right side
+
+ final Resource left = input.getLeftPseudoConflictAddScope();
+ final Resource right = input.getRightPseudoConflictAddScope();
+ final Resource origin = input.getOriginPseudoConflictAddScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD)));
+
+ // Merge -> Node A[containmentRef1 add] from left to right : <- Node A[containmentRef1 add] will be
+ // merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeA = getNodeNamed(left, "A");
+ assertNotNull(leftNodeA);
+ final EObject rightNodeA = getNodeNamed(right, "A");
+ assertNotNull(rightNodeA);
+ final EStructuralFeature feature = rightNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)rightNodeRoot).getContainmentRef1();
+ assertFalse(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoAdd_LtR_2() throws IOException {
+ // Pseudo Conflict between Node A[containmentRef1 add] from left side and Node A[containmentRef1 add]
+ // from right side
+
+ final Resource left = input.getLeftPseudoConflictAddScope();
+ final Resource right = input.getRightPseudoConflictAddScope();
+ final Resource origin = input.getOriginPseudoConflictAddScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.ADD)));
+
+ // Merge <- Node A[containmentRef1 add] from left to right : -> Node A[containmentRef1 add] will be
+ // merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeA = getNodeNamed(left, "A");
+ assertNotNull(leftNodeA);
+ final EObject rightNodeA = getNodeNamed(right, "A");
+ assertNotNull(rightNodeA);
+ final EStructuralFeature feature = rightNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)rightNodeRoot).getContainmentRef1();
+ assertFalse(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoAdd_RtL_1() throws IOException {
+ // Pseudo Conflict between Node A[containmentRef1 add] from left side and Node A[containmentRef1 add]
+ // from right side
+
+ final Resource left = input.getLeftPseudoConflictAddScope();
+ final Resource right = input.getRightPseudoConflictAddScope();
+ final Resource origin = input.getOriginPseudoConflictAddScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD)));
+
+ // Merge -> Node A[containmentRef1 add] from right to left : <- Node A[containmentRef1 add] will be
+ // merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeA = getNodeNamed(left, "A");
+ assertNotNull(leftNodeA);
+ final EObject rightNodeA = getNodeNamed(right, "A");
+ assertNotNull(rightNodeA);
+ final EStructuralFeature feature = leftNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)leftNodeRoot).getContainmentRef1();
+ assertFalse(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoAdd_RtL_2() throws IOException {
+ // Pseudo Conflict between Node A[containmentRef1 add] from left side and Node A[containmentRef1 add]
+ // from right side
+
+ final Resource left = input.getLeftPseudoConflictAddScope();
+ final Resource right = input.getRightPseudoConflictAddScope();
+ final Resource origin = input.getOriginPseudoConflictAddScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.ADD)));
+
+ // Merge <- Node A[containmentRef1 add] from right to left : -> Node A[containmentRef1 add] will be
+ // merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeA = getNodeNamed(left, "A");
+ assertNotNull(leftNodeA);
+ final EObject rightNodeA = getNodeNamed(right, "A");
+ assertNotNull(rightNodeA);
+ final EStructuralFeature feature = leftNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)leftNodeRoot).getContainmentRef1();
+ assertFalse(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoDelete_LtR_1() throws IOException {
+ // Pseudo Conflict between Node B[containmentRef1 delete] from left side and Node B[containmentRef1
+ // delete] from right side
+
+ final Resource left = input.getLeftPseudoConflictDeleteScope();
+ final Resource right = input.getRightPseudoConflictDeleteScope();
+ final Resource origin = input.getOriginPseudoConflictDeleteScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE)));
+
+ // Merge -> Node B[containmentRef1 delete] from left to right : <- Node B[containmentRef1 delete] will
+ // be merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeB = getNodeNamed(left, "B");
+ assertNull(leftNodeB);
+ final EObject rightNodeB = getNodeNamed(right, "B");
+ assertNull(rightNodeB);
+ final EStructuralFeature feature = rightNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)rightNodeRoot).getContainmentRef1();
+ assertTrue(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoDelete_LtR_2() throws IOException {
+ // Pseudo Conflict between Node B[containmentRef1 delete] from left side and Node B[containmentRef1
+ // delete] from right side
+
+ final Resource left = input.getLeftPseudoConflictDeleteScope();
+ final Resource right = input.getRightPseudoConflictDeleteScope();
+ final Resource origin = input.getOriginPseudoConflictDeleteScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.DELETE)));
+
+ // Merge <- Node B[containmentRef1 delete] from left to right : -> Node B[containmentRef1 delete] will
+ // be merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeB = getNodeNamed(left, "B");
+ assertNull(leftNodeB);
+ final EObject rightNodeB = getNodeNamed(right, "B");
+ assertNull(rightNodeB);
+ final EStructuralFeature feature = rightNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)rightNodeRoot).getContainmentRef1();
+ assertTrue(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoDelete_RtL_1() throws IOException {
+ // Pseudo Conflict between Node B[containmentRef1 delete] from left side and Node B[containmentRef1
+ // delete] from right side
+
+ final Resource left = input.getLeftPseudoConflictDeleteScope();
+ final Resource right = input.getRightPseudoConflictDeleteScope();
+ final Resource origin = input.getOriginPseudoConflictDeleteScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE)));
+
+ // Merge -> Node B[containmentRef1 delete] from right to left : <- Node B[containmentRef1 delete] will
+ // be merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeB = getNodeNamed(left, "B");
+ assertNull(leftNodeB);
+ final EObject rightNodeB = getNodeNamed(right, "B");
+ assertNull(rightNodeB);
+ final EStructuralFeature feature = leftNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)leftNodeRoot).getContainmentRef1();
+ assertTrue(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoDelete_RtL_2() throws IOException {
+ // Pseudo Conflict between Node B[containmentRef1 delete] from left side and Node B[containmentRef1
+ // delete] from right side
+
+ final Resource left = input.getLeftPseudoConflictDeleteScope();
+ final Resource right = input.getRightPseudoConflictDeleteScope();
+ final Resource origin = input.getOriginPseudoConflictDeleteScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.DELETE)));
+
+ // Merge <- Node B[containmentRef1 delete] from right to left : -> Node B[containmentRef1 delete] will
+ // be merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "containmentRef1";
+ final EObject leftNodeRoot = getNodeNamed(left, "root");
+ assertNotNull(leftNodeRoot);
+ final EObject rightNodeRoot = getNodeNamed(right, "root");
+ assertNotNull(rightNodeRoot);
+ final EObject leftNodeB = getNodeNamed(left, "B");
+ assertNull(leftNodeB);
+ final EObject rightNodeB = getNodeNamed(right, "B");
+ assertNull(rightNodeB);
+ final EStructuralFeature feature = leftNodeRoot.eClass().getEStructuralFeature(featureName);
+ assertNotNull(feature);
+ final EList<Node> containmentRef1 = ((Node)leftNodeRoot).getContainmentRef1();
+ assertTrue(containmentRef1.isEmpty());
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoChange_LtR_1() throws IOException {
+ // Pseudo Conflict between Hello[singleValuedAttribute changed] from left side and
+ // Hello[singleValuedAttribute changed] from right side
+
+ final Resource left = input.getLeftPseudoConflictChangeScope();
+ final Resource right = input.getRightPseudoConflictChangeScope();
+ final Resource origin = input.getOriginPseudoConflictChangeScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.CHANGE)));
+
+ // Merge -> Hello[singleValuedAttribute changed] from left to right : <- Hello[singleValuedAttribute
+ // changed] will be merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "singleValuedAttribute";
+ final EObject leftNodeD = getNodeNamed(left, "D");
+ assertNotNull(leftNodeD);
+ final EObject rightNodeD = getNodeNamed(right, "D");
+ assertNotNull(rightNodeD);
+ final EStructuralFeature featureRight = rightNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureRight);
+ final EStructuralFeature featureLeft = leftNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureLeft);
+ final String singleValuedAttributeRight = ((NodeSingleValueAttribute)rightNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeRight);
+ final String singleValuedAttributeLeft = ((NodeSingleValueAttribute)leftNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeLeft);
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoChange_LtR_2() throws IOException {
+ // Pseudo Conflict between Hello[singleValuedAttribute changed] from left side and
+ // Hello[singleValuedAttribute changed] from right side
+
+ final Resource left = input.getLeftPseudoConflictChangeScope();
+ final Resource right = input.getRightPseudoConflictChangeScope();
+ final Resource origin = input.getOriginPseudoConflictChangeScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.CHANGE)));
+
+ // Merge <- Hello[singleValuedAttribute changed] from left to right : -> Hello[singleValuedAttribute
+ // changed] will be merge from left to right too.
+ mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor());
+
+ final String featureName = "singleValuedAttribute";
+ final EObject leftNodeD = getNodeNamed(left, "D");
+ assertNotNull(leftNodeD);
+ final EObject rightNodeD = getNodeNamed(right, "D");
+ assertNotNull(rightNodeD);
+ final EStructuralFeature featureRight = rightNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureRight);
+ final EStructuralFeature featureLeft = leftNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureLeft);
+ final String singleValuedAttributeRight = ((NodeSingleValueAttribute)rightNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeRight);
+ final String singleValuedAttributeLeft = ((NodeSingleValueAttribute)leftNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeLeft);
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoChange_RtL_1() throws IOException {
+ // Pseudo Conflict between Hello[singleValuedAttribute changed] from left side and
+ // Hello[singleValuedAttribute changed] from right side
+
+ final Resource left = input.getLeftPseudoConflictChangeScope();
+ final Resource right = input.getRightPseudoConflictChangeScope();
+ final Resource origin = input.getOriginPseudoConflictChangeScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.CHANGE)));
+
+ // Merge -> Hello[singleValuedAttribute changed] from right to left : <- Hello[singleValuedAttribute
+ // changed] will be merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "singleValuedAttribute";
+ final EObject leftNodeD = getNodeNamed(left, "D");
+ assertNotNull(leftNodeD);
+ final EObject rightNodeD = getNodeNamed(right, "D");
+ assertNotNull(rightNodeD);
+ final EStructuralFeature featureRight = rightNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureRight);
+ final EStructuralFeature featureLeft = leftNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureLeft);
+ final String singleValuedAttributeRight = ((NodeSingleValueAttribute)rightNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeRight);
+ final String singleValuedAttributeLeft = ((NodeSingleValueAttribute)leftNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeLeft);
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ @Test
+ public void testPseudoChange_RtL_2() throws IOException {
+ // Pseudo Conflict between Hello[singleValuedAttribute changed] from left side and
+ // Hello[singleValuedAttribute changed] from right side
+
+ final Resource left = input.getLeftPseudoConflictChangeScope();
+ final Resource right = input.getRightPseudoConflictChangeScope();
+ final Resource origin = input.getOriginPseudoConflictChangeScope();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ List<Diff> differences = comparison.getDifferences();
+ assertSame(Integer.valueOf(2), Integer.valueOf(differences.size()));
+
+ final Diff diff = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT),
+ ofKind(DifferenceKind.CHANGE)));
+
+ // Merge -> Hello[singleValuedAttribute changed] from right to left : <- Hello[singleValuedAttribute
+ // changed] will be merge from right to left too.
+ mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
+
+ final String featureName = "singleValuedAttribute";
+ final EObject leftNodeD = getNodeNamed(left, "D");
+ assertNotNull(leftNodeD);
+ final EObject rightNodeD = getNodeNamed(right, "D");
+ assertNotNull(rightNodeD);
+ final EStructuralFeature featureRight = rightNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureRight);
+ final EStructuralFeature featureLeft = leftNodeD.eClass().getEStructuralFeature(featureName);
+ assertNotNull(featureLeft);
+ final String singleValuedAttributeRight = ((NodeSingleValueAttribute)rightNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeRight);
+ final String singleValuedAttributeLeft = ((NodeSingleValueAttribute)leftNodeD)
+ .getSingleValuedAttribute();
+ assertEquals("GoodBye", singleValuedAttributeLeft);
+
+ Iterators.any(differences.iterator(), not(hasConflict(ConflictKind.PSEUDO)));
+
+ }
+
+ private EObject getNodeNamed(Resource res, String name) {
+ final Iterator<EObject> iterator = EcoreUtil.getAllProperContents(res, false);
+ while (iterator.hasNext()) {
+ final EObject next = iterator.next();
+ final EStructuralFeature nameFeature = next.eClass().getEStructuralFeature("name");
+ if (nameFeature != null && name.equals(next.eGet(nameFeature))) {
+ return next;
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/IndividualDiffInputData.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/IndividualDiffInputData.java
index 01b9697d8..61d01ed32 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/IndividualDiffInputData.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/IndividualDiffInputData.java
@@ -341,4 +341,52 @@ public class IndividualDiffInputData extends AbstractInputData {
public Resource getLeftMoveRightDeleteRightConflictScope() throws IOException {
return loadFromClassLoader("conflictscope/leftmove_rightdelete/right.ecore");
}
+
+ public Resource getLeftPseudoConflictAddScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/add/left.nodes");
+ }
+
+ public Resource getOriginPseudoConflictAddScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/add/ancestor.nodes");
+ }
+
+ public Resource getRightPseudoConflictAddScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/add/right.nodes");
+ }
+
+ public Resource getLeftPseudoConflictChangeScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/change/left.nodes");
+ }
+
+ public Resource getOriginPseudoConflictChangeScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/change/ancestor.nodes");
+ }
+
+ public Resource getRightPseudoConflictChangeScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/change/right.nodes");
+ }
+
+ public Resource getLeftPseudoConflictDeleteScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/delete/left.nodes");
+ }
+
+ public Resource getOriginPseudoConflictDeleteScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/delete/ancestor.nodes");
+ }
+
+ public Resource getRightPseudoConflictDeleteScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/delete/right.nodes");
+ }
+
+ public Resource getLeftPseudoConflictFullScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/fullscope/left.nodes");
+ }
+
+ public Resource getOriginPseudoConflictFullScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/fullscope/ancestor.nodes");
+ }
+
+ public Resource getRightPseudoConflictFullScope() throws IOException {
+ return loadFromClassLoader("pseudoconflictscope/fullscope/right.nodes");
+ }
}
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/ancestor.nodes
new file mode 100644
index 000000000..71e1fb2a0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/ancestor.nodes
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root"/>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/left.nodes
new file mode 100644
index 000000000..f5666f5b3
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/left.nodes
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_AT1TgNqXEeOXstPlKfVTPg"
+ name="A"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/right.nodes
new file mode 100644
index 000000000..f5666f5b3
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/add/right.nodes
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_AT1TgNqXEeOXstPlKfVTPg"
+ name="A"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/ancestor.nodes
new file mode 100644
index 000000000..b4fdaf9a1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/ancestor.nodes
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="Hello"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/left.nodes
new file mode 100644
index 000000000..89fe3ef0b
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/left.nodes
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="GoodBye"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/right.nodes
new file mode 100644
index 000000000..89fe3ef0b
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/change/right.nodes
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="GoodBye"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/ancestor.nodes
new file mode 100644
index 000000000..fed946d3f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/ancestor.nodes
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_D29cANqXEeOXstPlKfVTPg"
+ name="B"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/left.nodes
new file mode 100644
index 000000000..71e1fb2a0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/left.nodes
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root"/>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/right.nodes
new file mode 100644
index 000000000..71e1fb2a0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/delete/right.nodes
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root"/>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/ancestor.nodes
new file mode 100644
index 000000000..5065e5b04
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/ancestor.nodes
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_D29cANqXEeOXstPlKfVTPg"
+ name="B"/>
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="Hello"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/left.nodes
new file mode 100644
index 000000000..28224cdcc
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/left.nodes
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_AT1TgNqXEeOXstPlKfVTPg"
+ name="A"/>
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="GoodBye"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/right.nodes
new file mode 100644
index 000000000..28224cdcc
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/data/pseudoconflictscope/fullscope/right.nodes
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_CEv4EM7REeOlS6AUBGqBsw"
+ name="root">
+ <containmentRef1
+ xmi:id="_AT1TgNqXEeOXstPlKfVTPg"
+ name="A"/>
+ <containmentRef1
+ xmi:id="_E30dAMqXEeOXstPlKfVTPg"
+ name="C">
+ <containmentRef1
+ xsi:type="nodes:NodeSingleValueAttribute"
+ xmi:id="_2N8O0OC7EeOz6tW2ExS0YQ"
+ name="D"
+ singleValuedAttribute="GoodBye"/>
+ </containmentRef1>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
index 292f599f4..6f7953bae 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
@@ -35,6 +35,7 @@ import org.eclipse.emf.compare.tests.merge.ExtensionMergeTest;
import org.eclipse.emf.compare.tests.merge.IndividualMergeOutOfScopeValuesTest;
import org.eclipse.emf.compare.tests.merge.IndividualMergeTest;
import org.eclipse.emf.compare.tests.merge.MultipleMergeTest;
+import org.eclipse.emf.compare.tests.merge.PseudoConflictMergeTest;
import org.eclipse.emf.compare.tests.nodes.NodesPackage;
import org.eclipse.emf.compare.tests.nodes.util.NodesResourceFactoryImpl;
import org.eclipse.emf.compare.tests.postprocess.PostProcessorTest;
@@ -61,7 +62,7 @@ import org.junit.runners.Suite.SuiteClasses;
IndividualMergeOutOfScopeValuesTest.class, ProximityComparisonTest.class,
DynamicInstanceComparisonTest.class, URIDistanceTest.class, FragmentationTest.class,
AllEditTests.class, CommandStackTestSuite.class, MatchEngineFactoryRegistryTest.class,
- ConflictMergeTest.class, ProximityIndexTest.class, AllRCPTests.class })
+ ConflictMergeTest.class, PseudoConflictMergeTest.class, ProximityIndexTest.class, AllRCPTests.class })
public class AllTests {
/**
* Standalone launcher for all of compare's tests.

Back to the top