[462884] Allows merging specific diffs in MergeAllNonConflictingRunnable
Renames MergeAllNonConflictingRunnable to MergeNonConflictingRunnable,
as it now allows to also merge a specific set of differences with the
same strategy as for all non-conflicting differences. Therefore, this
runnable now also implements IMergeRunnable.
Accordingly, also the test class for MergeNonConflictingRunnable have
been extended concerning the use cases for merging a given list of
differences only.
Also we introduce additional two-way tests in MergeAllCommandTests.
Bug: 462884
Change-Id: I80518d479db18c19bd51ebdabe5789ca58850672
Signed-off-by: Philip Langer <planger@eclipsesource.com>
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
index 21a169c..57aea71 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Philip Langer -
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.tests.command;
@@ -33,7 +34,7 @@
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.command.impl.MergeAllNonConflictingCommand;
import org.eclipse.emf.compare.domain.impl.EMFCompareEditingDomain;
-import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAllNonConflictingRunnable;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable;
import org.eclipse.emf.compare.ide.ui.tests.command.data.MergeAllCommandInputData;
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.merge.IMerger;
@@ -41,38 +42,48 @@
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.emf.ecore.change.util.ChangeRecorder;
import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Before;
import org.junit.Test;
@SuppressWarnings({"restriction", "unchecked" })
public class MergeAllCommandTests {
- private MergeAllCommandInputData input = new MergeAllCommandInputData();
+ private Resource leftResource;
- private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+ private Resource rightResource;
+
+ private Resource originResource;
+
+ private IMerger.Registry mergerRegistry;
+
+ @Before
+ public void getInputData() throws IOException {
+ final MergeAllCommandInputData input = new MergeAllCommandInputData();
+ leftResource = input.getLeftScope();
+ rightResource = input.getRightScope();
+ originResource = input.getOriginScope();
+ mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+ }
@Test
- public void testMergeAllNonConflictingFromLeftToRight() throws IOException {
+ public void testMergeAllNonConflictingFromLeftToRightThreeWayWithoutConflicts() throws IOException {
MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
boolean leftToRight = true;
boolean isLeftEditable = true;
boolean isRightEditable = true;
- Resource left = input.getLeftScope();
- Resource right = input.getRightScope();
- Resource origin = input.getOriginScope();
-
- IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
Comparison comparison = EMFCompare.builder().build().compare(scope);
- EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
- right, origin);
+ EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+ leftResource, rightResource, originResource);
ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
- ImmutableList.of(left, right, origin)).build();
+ ImmutableList.of(leftResource, rightResource, originResource)).build();
- MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+ MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
isRightEditable, mergeMode);
MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -124,28 +135,24 @@
}
@Test
- public void testMergeAllNonConflictingFromRightToLeft() throws IOException {
+ public void testMergeAllNonConflictingFromRightToLeftThreeWayWithoutConflicts() throws IOException {
MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
boolean leftToRight = false;
boolean isLeftEditable = true;
boolean isRightEditable = true;
- Resource left = input.getLeftScope();
- Resource right = input.getRightScope();
- Resource origin = input.getOriginScope();
-
- IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
Comparison comparison = EMFCompare.builder().build().compare(scope);
- EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
- right, origin);
+ EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+ leftResource, rightResource, originResource);
ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
- ImmutableList.of(left, right, origin)).build();
+ ImmutableList.of(leftResource, rightResource, originResource)).build();
- MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+ MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
isRightEditable, mergeMode);
MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -174,7 +181,7 @@
command.execute();
EList<Diff> differencesAfter = comparison.getDifferences();
- // Test state of differences before command
+ // Test state of differences after command
// 0 Left Delete differences merged
leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -197,28 +204,24 @@
}
@Test
- public void testAcceptAllNonConflictingChanges() throws IOException {
+ public void testAcceptAllNonConflictingChangesThreeWayWithoutConflicts() throws IOException {
MergeMode mergeMode = MergeMode.ACCEPT;
boolean leftToRight = false;
boolean isLeftEditable = true;
boolean isRightEditable = false;
- Resource left = input.getLeftScope();
- Resource right = input.getRightScope();
- Resource origin = input.getOriginScope();
-
- IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
Comparison comparison = EMFCompare.builder().build().compare(scope);
- EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
- right, origin);
+ EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+ leftResource, rightResource, originResource);
ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
- ImmutableList.of(left, right, origin)).build();
+ ImmutableList.of(leftResource, rightResource, originResource)).build();
- MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+ MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
isRightEditable, mergeMode);
MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -247,7 +250,7 @@
command.execute();
EList<Diff> differencesAfter = comparison.getDifferences();
- // Test state of differences before command
+ // Test state of differences after command
// 3 Left Delete differences merged
leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -270,28 +273,24 @@
}
@Test
- public void testRejectAllNonConflictingChanges() throws IOException {
+ public void testRejectAllNonConflictingChangesThreeWayWithoutConflicts() throws IOException {
MergeMode mergeMode = MergeMode.REJECT;
boolean leftToRight = false;
boolean isLeftEditable = true;
boolean isRightEditable = false;
- Resource left = input.getLeftScope();
- Resource right = input.getRightScope();
- Resource origin = input.getOriginScope();
-
- IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
Comparison comparison = EMFCompare.builder().build().compare(scope);
- EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
- right, origin);
+ EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+ leftResource, rightResource, originResource);
ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
- ImmutableList.of(left, right, origin)).build();
+ ImmutableList.of(leftResource, rightResource, originResource)).build();
- MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+ MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
isRightEditable, mergeMode);
MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -320,7 +319,7 @@
command.execute();
EList<Diff> differencesAfter = comparison.getDifferences();
- // Test state of differences before command
+ // Test state of differences after command
// 3 Left Delete differences merged
leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -341,4 +340,65 @@
command.dispose();
editingDomain.dispose();
}
+
+ @Test
+ public void testMergeAllNonConflictingChangesFromLeftToRightTwoWay() throws IOException {
+ testMergeAllNonConflictingTwoWay(MergeMode.LEFT_TO_RIGHT);
+ }
+
+ @Test
+ public void testMergeAllNonConflictingChangesFromRightToLeftTwoWay() throws IOException {
+ testMergeAllNonConflictingTwoWay(MergeMode.RIGHT_TO_LEFT);
+ }
+
+ private void testMergeAllNonConflictingTwoWay(MergeMode mergeMode) {
+ boolean isLeftEditable = true;
+ boolean isRightEditable = true;
+
+ IComparisonScope scope = new DefaultComparisonScope(leftResource, originResource, null);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+ leftResource, originResource, null);
+ ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
+
+ ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
+ ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
+ ImmutableList.of(leftResource, originResource)).build();
+
+ MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
+ isRightEditable, mergeMode);
+
+ MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
+ comparison, mergeMode.isLeftToRight(isLeftEditable, isRightEditable), mergerRegistry,
+ runnable);
+
+ EList<Diff> differencesBefore = comparison.getDifferences();
+ // Test state of differences before command
+ // 3 Left Delete differences
+ Iterable<Diff> leftDelete = filter(differencesBefore, and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE), hasState(DifferenceState.UNRESOLVED)));
+ assertEquals(3, size(leftDelete));
+ // 3 Left Add differences
+ Iterable<Diff> leftAdd = filter(differencesBefore, and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD), hasState(DifferenceState.UNRESOLVED)));
+ assertEquals(3, size(leftAdd));
+
+ // Execute command
+ command.execute();
+
+ EList<Diff> differencesAfter = comparison.getDifferences();
+ // Test state of differences after command
+ // 3 Left Delete differences merged
+ leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
+ assertEquals(3, size(leftDelete));
+ // 3 Left Add differences merged
+ leftAdd = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT), ofKind(DifferenceKind.ADD),
+ hasState(DifferenceState.MERGED)));
+ assertEquals(3, size(leftAdd));
+
+ command.dispose();
+ editingDomain.dispose();
+ }
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java
deleted file mode 100644
index 4531852..0000000
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 EclipseSource Muenchen GmbH and others.
- * 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:
- * Philip Langer - initial API and implementation
- *******************************************************************************/
-package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions;
-
-import static org.eclipse.emf.compare.DifferenceKind.ADD;
-import static org.eclipse.emf.compare.DifferenceKind.DELETE;
-import static org.eclipse.emf.compare.DifferenceSource.LEFT;
-import static org.eclipse.emf.compare.DifferenceSource.RIGHT;
-import static org.eclipse.emf.compare.DifferenceState.MERGED;
-import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-
-import org.eclipse.emf.common.util.BasicEList;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.Monitor;
-import org.eclipse.emf.compare.Comparison;
-import org.eclipse.emf.compare.Conflict;
-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.DifferenceState;
-import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAllNonConflictingRunnable;
-import org.eclipse.emf.compare.internal.merge.MergeMode;
-import org.eclipse.emf.compare.merge.IMerger;
-import org.eclipse.emf.compare.merge.IMerger.Registry;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests the {@link MergeAllNonConflictingRunnable} according to the specification given in <a
- * href="https://wiki.eclipse.org/EMF_Compare/Specifications/AllNonConflictingActions">the wiki</a>.
- * <p>
- * The goal of this test is to have a more unit-level test of the {@link MergeAllNonConflictingRunnable} (as
- * opposed to o.e.e.compare.ide.ui.tests.command.MergeAllCommandTests, which is more an integration test), as
- * well as to have a test in preparation of the refactorings panned for fixing bug 462884.
- * </p>
- *
- * @author Philip Langer <planger@eclipsesource.com>
- */
-@SuppressWarnings("restriction")
-public class MergeAllNonConflictingRunnableTest {
-
- private Comparison comparison;
-
- private Registry mergerRegistry;
-
- private IMerger merger;
-
- private Diff leftDelete;
-
- private Diff leftAdd;
-
- private Diff rightDelete;
-
- private Diff rightAdd;
-
- @Before
- public void setupMocks() {
- comparison = mock(Comparison.class);
- mergerRegistry = mock(Registry.class);
- merger = mock(IMerger.class);
- when(mergerRegistry.getHighestRankingMerger(any(Diff.class))).thenReturn(merger);
- }
-
- @Test
- public void testMergeAllLeftToRightWithConflicts() {
- final boolean isLeftToRight = true;
- final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedLeftToRightOnly(leftAdd);
- verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
- verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
- }
-
- @Test
- public void testMergeAllLeftToRightWithoutConflicts() {
- final boolean isLeftToRight = true;
- final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- setNoConflictsInMockComparison();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
- verifyHasNotBeenMerged(rightDelete, rightAdd);
- verifyStateIsUnchanged(rightDelete, rightAdd);
- }
-
- @Test
- public void testMergeAllRightToLeftWithConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(rightAdd);
- verifyHasNotBeenMerged(rightDelete, leftDelete, leftAdd);
- verifyStateIsUnchanged(rightDelete, leftDelete, leftAdd);
- }
-
- @Test
- public void testMergeAllRightToLeftWithoutConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- setNoConflictsInMockComparison();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
- verifyHasNotBeenMerged(leftDelete, leftAdd);
- verifyStateIsUnchanged(leftDelete, leftAdd);
- }
-
- @Test
- public void testAcceptAllWithoutConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.ACCEPT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- setNoConflictsInMockComparison();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
- verifyHasNotBeenMerged(leftDelete, leftAdd);
- verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
- }
-
- @Test
- public void testRejectAllWithoutConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.REJECT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- setNoConflictsInMockComparison();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
- verifyHasNotBeenMerged(rightDelete, rightAdd);
- verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
- }
-
- @Test
- public void testAcceptAllWithConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.ACCEPT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(rightAdd);
- verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
- verifyHasBeenMarkedAsMerged(leftAdd);
- verifyStateIsUnchanged(leftDelete, rightDelete);
- }
-
- @Test
- public void testRejectAllWithConflicts() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.REJECT;
-
- setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
- addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(leftAdd);
- verifyHasNotBeenMerged(rightDelete, leftDelete, rightAdd);
- verifyHasBeenMarkedAsMerged(rightAdd);
- verifyStateIsUnchanged(leftDelete, rightDelete);
- }
-
- @Test
- public void testTwoWayMergeAllLeftToRight() {
- final boolean isLeftToRight = true;
- final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
- setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
- }
-
- @Test
- public void testTwoWayMergeAllRightToLeft() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
- setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
- }
-
- @Test
- public void testTwoWayAcceptAll() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.ACCEPT;
-
- setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasNotBeenMerged(leftDelete, leftAdd);
- verifyHasBeenMarkedAsMerged(leftDelete, leftAdd);
- }
-
- @Test
- public void testTwoWayRejectAll() {
- final boolean isLeftToRight = false;
- final MergeMode mergeMode = MergeMode.REJECT;
-
- setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
- final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
- sut.merge(comparison, isLeftToRight, mergerRegistry);
-
- verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
- }
-
- private void addConflictsToMockComparison(Conflict... conflicts) {
- when(comparison.getConflicts()).thenReturn(newEList(conflicts));
- }
-
- private void addDifferencesToMockComparison(Diff... diffs) {
- when(comparison.getDifferences()).thenReturn(newEList(diffs));
- }
-
- private ReferenceChange mockReferenceChange(DifferenceSource side, DifferenceKind kind) {
- final ReferenceChange diff = mock(ReferenceChange.class);
- when(diff.getSource()).thenReturn(side);
- when(diff.getKind()).thenReturn(kind);
- when(diff.getState()).thenReturn(UNRESOLVED);
- return diff;
- }
-
- private Conflict newConflict(Diff... diffs) {
- Conflict conflict = mock(Conflict.class);
- when(conflict.getKind()).thenReturn(ConflictKind.REAL);
- when(conflict.getDifferences()).thenReturn(newEList(diffs));
- for (Diff diff : diffs) {
- when(diff.getConflict()).thenReturn(conflict);
- }
- return conflict;
- }
-
- private EList<Conflict> newEList(Conflict... diffs) {
- final EList<Conflict> list = new BasicEList<Conflict>();
- for (Conflict diff : diffs) {
- list.add(diff);
- }
- return list;
- }
-
- private EList<Diff> newEList(Diff... diffs) {
- final EList<Diff> list = new BasicEList<Diff>();
- for (Diff diff : diffs) {
- list.add(diff);
- }
- return list;
- }
-
- private void setNoConflictsInMockComparison() {
- addConflictsToMockComparison(new Conflict[0]);
- }
-
- private void setThreeWayComparison() {
- when(comparison.isThreeWay()).thenReturn(true);
- }
-
- private void setTwoWayComparison() {
- when(comparison.isThreeWay()).thenReturn(false);
- }
-
- private void setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide() {
- leftDelete = mockReferenceChange(LEFT, DELETE);
- leftAdd = mockReferenceChange(LEFT, ADD);
- rightDelete = mockReferenceChange(RIGHT, DELETE);
- rightAdd = mockReferenceChange(RIGHT, ADD);
-
- addDifferencesToMockComparison(leftDelete, leftAdd, rightDelete, rightAdd);
- setThreeWayComparison();
- }
-
- private void setUpTwoWayComparisonWithOneAdditionAndOneDeletion() {
- leftDelete = mockReferenceChange(LEFT, DELETE);
- leftAdd = mockReferenceChange(LEFT, ADD);
-
- addDifferencesToMockComparison(leftDelete, leftAdd);
- setNoConflictsInMockComparison();
- setTwoWayComparison();
- }
-
- private void verifyHasBeenMarkedAsMerged(Diff... diffs) {
- for (Diff diff : diffs) {
- verifyHasBeenMarkedAsMerged(diff);
- }
- }
-
- private void verifyHasBeenMarkedAsMerged(Diff diff) {
- verify(diff).setState(eq(MERGED));
- }
-
- private void verifyHasBeenMergedLeftToRightOnly(Diff diff) {
- verify(merger, atLeastOnce()).copyLeftToRight(same(diff), any(Monitor.class));
- verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
- }
-
- private void verifyHasBeenMergedLeftToRightOnly(Diff... diffs) {
- for (Diff diff : diffs) {
- verifyHasBeenMergedLeftToRightOnly(diff);
- }
- }
-
- private void verifyHasBeenMergedRightToLeftOnly(Diff... diffs) {
- for (Diff diff : diffs) {
- verifyHasBeenMergedRightToLeftOnly(diff);
- }
- }
-
- private void verifyHasBeenMergedRightToLeftOnly(Diff diff) {
- verify(merger, atLeastOnce()).copyRightToLeft(same(diff), any(Monitor.class));
- verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
- }
-
- private void verifyHasNotBeenMerged(Diff diff) {
- verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
- verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
- }
-
- private void verifyHasNotBeenMerged(Diff... diffs) {
- for (Diff diff : diffs) {
- verifyHasNotBeenMerged(diff);
- }
- }
-
- private void verifyStateIsUnchanged(Diff diff) {
- verify(diff, never()).setState(any(DifferenceState.class));
- }
-
- private void verifyStateIsUnchanged(Diff... diffs) {
- for (Diff diff : diffs) {
- verifyStateIsUnchanged(diff);
- }
- }
-
- private MergeAllNonConflictingRunnable newMergeAllNonConflictingRunnable(MergeMode mergeMode) {
- final boolean isLeftEditable;
- final boolean isRightEditable;
- switch (mergeMode) {
- case LEFT_TO_RIGHT:
- // fall through
- case RIGHT_TO_LEFT:
- isLeftEditable = true;
- isRightEditable = true;
- break;
- case ACCEPT:
- // fall through
- case REJECT:
- isLeftEditable = true;
- isRightEditable = false;
- break;
- default:
- throw new IllegalArgumentException();
- }
- return new MergeAllNonConflictingRunnable(isLeftEditable, isRightEditable, mergeMode) {
- @Override
- protected void addOrUpdateMergeData(Collection<Diff> differences, MergeMode mode) {
- // do nothing to prevent call of EcoreUtil.getAdapter()
- }
-
- @Override
- protected void markAsMerged(Diff diff, MergeMode mode, boolean mergeRightToLeft, Registry registry) {
- // overwritten to prevent call of EcoreUtil.getAdapter()
- // note that we rely on setting diff state to merged in verifyHasBeenMarkedAsMerged(Diff)
- diff.setState(MERGED);
- }
- };
- }
-
-}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java
new file mode 100644
index 0000000..d0ad712
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java
@@ -0,0 +1,637 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EclipseSource Muenchen GmbH and others.
+ * 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:
+ * Philip Langer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions;
+
+import static java.util.Arrays.asList;
+import static org.eclipse.emf.compare.DifferenceKind.ADD;
+import static org.eclipse.emf.compare.DifferenceKind.DELETE;
+import static org.eclipse.emf.compare.DifferenceSource.LEFT;
+import static org.eclipse.emf.compare.DifferenceSource.RIGHT;
+import static org.eclipse.emf.compare.DifferenceState.MERGED;
+import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.Monitor;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Conflict;
+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.DifferenceState;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ReferenceChange;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
+import org.eclipse.emf.compare.merge.IMerger;
+import org.eclipse.emf.compare.merge.IMerger.Registry;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests the {@link MergeNonConflictingRunnable} according to the specification given in <a
+ * href="https://wiki.eclipse.org/EMF_Compare/Specifications/AllNonConflictingActions">the wiki</a> and
+ * according to its capabilities to only merge a given collection of differences.
+ * <p>
+ * The goal of this test is to have a more unit-level test of the {@link MergeNonConflictingRunnable} (as
+ * opposed to o.e.e.compare.ide.ui.tests.command.MergeAllCommandTests, which is more an integration test).
+ * </p>
+ *
+ * @author Philip Langer <planger@eclipsesource.com>
+ */
+@SuppressWarnings({"restriction", "nls" })
+public class MergeNonConflictingRunnableTest {
+
+ private Comparison comparison;
+
+ private Registry mergerRegistry;
+
+ private IMerger merger;
+
+ private Diff leftDelete;
+
+ private Diff leftAdd;
+
+ private Diff rightDelete;
+
+ private Diff rightAdd;
+
+ @Before
+ public void setupMocks() {
+ comparison = mock(Comparison.class);
+ mergerRegistry = mock(Registry.class);
+ merger = mock(IMerger.class);
+ when(mergerRegistry.getHighestRankingMerger(any(Diff.class))).thenReturn(merger);
+ }
+
+ @Test
+ public void testMergeAllLeftToRightWithConflicts() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedLeftToRightOnly(leftAdd);
+ verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
+ verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeLeftToRightWithConflicts() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // leftAdd is in the list and the only non-conflicting
+ sut.merge(asList(leftDelete, rightDelete, leftAdd), isLeftToRight, mergerRegistry);
+
+ // so it should be the only diff that has been merged
+ verifyHasBeenMergedLeftToRightOnly(leftAdd);
+ verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
+ verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeLeftToRightWithConflictsAndLimitedSetOfDifferences() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // leftAdd is not in the list, but the only non-conflicting on the left
+ sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+ // so no merge should be performed
+ verifyHasNotBeenMerged(leftAdd, leftDelete, rightDelete, rightAdd);
+ verifyStateIsUnchanged(leftAdd, leftDelete, rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeAllLeftToRightWithoutConflicts() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
+ verifyHasNotBeenMerged(rightDelete, rightAdd);
+ verifyStateIsUnchanged(rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeLeftToRightWithoutConflicts() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // leftDelete is in the list, but we do not include leftAdd
+ sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+ // so only leftDelete should be merged
+ verifyHasBeenMergedLeftToRightOnly(leftDelete);
+ verifyHasNotBeenMerged(leftAdd, rightDelete, rightAdd);
+ verifyStateIsUnchanged(leftAdd, rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeAllRightToLeftWithConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(rightAdd);
+ verifyHasNotBeenMerged(rightDelete, leftDelete, leftAdd);
+ verifyStateIsUnchanged(rightDelete, leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testMergeRightToLeftWithConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // rightAdd is in the list and the only non-conflicting on the right
+ sut.merge(asList(leftDelete, rightDelete, rightAdd), isLeftToRight, mergerRegistry);
+
+ // so it should be the only diff that has been merged
+ verifyHasBeenMergedRightToLeftOnly(rightAdd);
+ verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
+ verifyStateIsUnchanged(leftDelete, rightDelete, leftAdd);
+ }
+
+ @Test
+ public void testMergeRightToLeftWithConflictsAndLimitedSetOfDifferences() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // rightAdd is not in the list, but the only non-conflicting
+ sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+ // so no merge should be performed
+ verifyHasNotBeenMerged(leftAdd, leftDelete, rightDelete, rightAdd);
+ verifyStateIsUnchanged(leftAdd, leftDelete, rightDelete, rightAdd);
+ }
+
+ @Test
+ public void testMergeAllRightToLeftWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
+ verifyHasNotBeenMerged(leftDelete, leftAdd);
+ verifyStateIsUnchanged(leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testMergeRightToLeftWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // we do not include rightAdd, so it should not be merged
+ // and leftDelete should not be merged, because we merge left to right
+ sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(rightDelete);
+ verifyHasNotBeenMerged(leftAdd, leftDelete, rightAdd);
+ verifyStateIsUnchanged(leftAdd, leftDelete, rightAdd);
+ }
+
+ @Test
+ public void testAcceptAllWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.ACCEPT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
+ verifyHasNotBeenMerged(leftDelete, leftAdd);
+ verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
+ }
+
+ @Test
+ public void testAcceptWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.ACCEPT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // rightDelete is in the list, but we do not include rightAdd
+ sut.merge(asList(leftAdd, leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+ // so only rightDelete should be merged
+ verifyHasBeenMergedRightToLeftOnly(rightDelete);
+ verifyHasNotBeenMerged(leftDelete, leftAdd);
+ verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
+ verifyStateIsUnchanged(rightAdd);
+ }
+
+ @Test
+ public void testRejectAllWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.REJECT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+ verifyHasNotBeenMerged(rightDelete, rightAdd);
+ verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
+ }
+
+ @Test
+ public void testRejectWithoutConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.REJECT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ setNoConflictsInMockComparison();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ // leftDelete is in the list, but we do not include leftAdd
+ sut.merge(asList(leftDelete, rightDelete, rightAdd), isLeftToRight, mergerRegistry);
+
+ // so only leftDelete should be merged
+ verifyHasBeenMergedRightToLeftOnly(leftDelete);
+ verifyHasNotBeenMerged(rightDelete, rightAdd);
+ verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
+ verifyStateIsUnchanged(leftAdd);
+ }
+
+ @Test
+ public void testAcceptAllWithConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.ACCEPT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(rightAdd);
+ verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
+ verifyHasBeenMarkedAsMerged(leftAdd);
+ verifyStateIsUnchanged(leftDelete, rightDelete);
+ }
+
+ @Test
+ public void testRejectAllWithConflicts() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.REJECT;
+
+ setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+ addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftAdd);
+ verifyHasNotBeenMerged(rightDelete, leftDelete, rightAdd);
+ verifyHasBeenMarkedAsMerged(rightAdd);
+ verifyStateIsUnchanged(leftDelete, rightDelete);
+ }
+
+ @Test
+ public void testTwoWayMergeAllLeftToRight() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testTwoWayMergeLeftToRight() {
+ final boolean isLeftToRight = true;
+ final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedLeftToRightOnly(leftDelete);
+ verifyHasNotBeenMerged(leftAdd);
+ verifyStateIsUnchanged(leftAdd);
+ }
+
+ @Test
+ public void testTwoWayMergeAllRightToLeft() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testTwoWayMergeRightToLeft() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftDelete);
+ verifyHasNotBeenMerged(leftAdd);
+ verifyStateIsUnchanged(leftAdd);
+ }
+
+ @Test
+ public void testTwoWayAcceptAll() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.ACCEPT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasNotBeenMerged(leftDelete, leftAdd);
+ verifyHasBeenMarkedAsMerged(leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testTwoWayAccept() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.ACCEPT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+ verifyHasNotBeenMerged(leftDelete);
+ verifyHasBeenMarkedAsMerged(leftDelete);
+ verifyStateIsUnchanged(leftAdd);
+ }
+
+ @Test
+ public void testTwoWayRejectAll() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.REJECT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+ }
+
+ @Test
+ public void testTwoWayReject() {
+ final boolean isLeftToRight = false;
+ final MergeMode mergeMode = MergeMode.REJECT;
+
+ setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+ final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+ sut.merge(asList(leftAdd), isLeftToRight, mergerRegistry);
+
+ verifyHasBeenMergedRightToLeftOnly(leftAdd);
+ verifyHasNotBeenMerged(leftDelete);
+ }
+
+ private void addConflictsToMockComparison(Conflict... conflicts) {
+ when(comparison.getConflicts()).thenReturn(newEList(conflicts));
+ }
+
+ private void addDifferencesToMockComparison(Diff... diffs) {
+ when(comparison.getDifferences()).thenReturn(newEList(diffs));
+ for (Diff diff : diffs) {
+ final Match match = mock(Match.class);
+ when(match.getComparison()).thenReturn(comparison);
+ when(diff.getMatch()).thenReturn(match);
+ }
+ }
+
+ private ReferenceChange mockReferenceChange(DifferenceSource side, DifferenceKind kind, String name) {
+ final ReferenceChange diff = mock(ReferenceChange.class, name);
+ when(diff.getSource()).thenReturn(side);
+ when(diff.getKind()).thenReturn(kind);
+ when(diff.getState()).thenReturn(UNRESOLVED);
+ return diff;
+ }
+
+ private Conflict newConflict(Diff... diffs) {
+ Conflict conflict = mock(Conflict.class);
+ when(conflict.getKind()).thenReturn(ConflictKind.REAL);
+ when(conflict.getDifferences()).thenReturn(newEList(diffs));
+ for (Diff diff : diffs) {
+ when(diff.getConflict()).thenReturn(conflict);
+ }
+ return conflict;
+ }
+
+ private EList<Conflict> newEList(Conflict... diffs) {
+ final EList<Conflict> list = new BasicEList<Conflict>();
+ for (Conflict diff : diffs) {
+ list.add(diff);
+ }
+ return list;
+ }
+
+ private EList<Diff> newEList(Diff... diffs) {
+ final EList<Diff> list = new BasicEList<Diff>();
+ for (Diff diff : diffs) {
+ list.add(diff);
+ }
+ return list;
+ }
+
+ private void setNoConflictsInMockComparison() {
+ addConflictsToMockComparison(new Conflict[0]);
+ }
+
+ private void setThreeWayComparison() {
+ when(Boolean.valueOf(comparison.isThreeWay())).thenReturn(Boolean.TRUE);
+ }
+
+ private void setTwoWayComparison() {
+ when(Boolean.valueOf(comparison.isThreeWay())).thenReturn(Boolean.FALSE);
+ }
+
+ private void setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide() {
+ leftDelete = mockReferenceChange(LEFT, DELETE, "leftDelete");
+ leftAdd = mockReferenceChange(LEFT, ADD, "leftAdd");
+ rightDelete = mockReferenceChange(RIGHT, DELETE, "rightDelete");
+ rightAdd = mockReferenceChange(RIGHT, ADD, "rightAdd");
+
+ addDifferencesToMockComparison(leftDelete, leftAdd, rightDelete, rightAdd);
+ setThreeWayComparison();
+ }
+
+ private void setUpTwoWayComparisonWithOneAdditionAndOneDeletion() {
+ leftDelete = mockReferenceChange(LEFT, DELETE, "leftDelete");
+ leftAdd = mockReferenceChange(LEFT, ADD, "leftAdd");
+
+ addDifferencesToMockComparison(leftDelete, leftAdd);
+ setNoConflictsInMockComparison();
+ setTwoWayComparison();
+ }
+
+ private void verifyHasBeenMarkedAsMerged(Diff... diffs) {
+ for (Diff diff : diffs) {
+ verifyHasBeenMarkedAsMerged(diff);
+ }
+ }
+
+ private void verifyHasBeenMarkedAsMerged(Diff diff) {
+ verify(diff).setState(eq(MERGED));
+ }
+
+ private void verifyHasBeenMergedLeftToRightOnly(Diff diff) {
+ verify(merger, atLeastOnce()).copyLeftToRight(same(diff), any(Monitor.class));
+ verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
+ }
+
+ private void verifyHasBeenMergedLeftToRightOnly(Diff... diffs) {
+ for (Diff diff : diffs) {
+ verifyHasBeenMergedLeftToRightOnly(diff);
+ }
+ }
+
+ private void verifyHasBeenMergedRightToLeftOnly(Diff... diffs) {
+ for (Diff diff : diffs) {
+ verifyHasBeenMergedRightToLeftOnly(diff);
+ }
+ }
+
+ private void verifyHasBeenMergedRightToLeftOnly(Diff diff) {
+ verify(merger, atLeastOnce()).copyRightToLeft(same(diff), any(Monitor.class));
+ verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
+ }
+
+ private void verifyHasNotBeenMerged(Diff diff) {
+ verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
+ verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
+ }
+
+ private void verifyHasNotBeenMerged(Diff... diffs) {
+ for (Diff diff : diffs) {
+ verifyHasNotBeenMerged(diff);
+ }
+ }
+
+ private void verifyStateIsUnchanged(Diff diff) {
+ verify(diff, never()).setState(any(DifferenceState.class));
+ }
+
+ private void verifyStateIsUnchanged(Diff... diffs) {
+ for (Diff diff : diffs) {
+ verifyStateIsUnchanged(diff);
+ }
+ }
+
+ private MergeNonConflictingRunnable newMergeAllNonConflictingRunnable(MergeMode mergeMode) {
+ final boolean isLeftEditable;
+ final boolean isRightEditable;
+ switch (mergeMode) {
+ case LEFT_TO_RIGHT:
+ // fall through
+ case RIGHT_TO_LEFT:
+ isLeftEditable = true;
+ isRightEditable = true;
+ break;
+ case ACCEPT:
+ // fall through
+ case REJECT:
+ isLeftEditable = true;
+ isRightEditable = false;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ return new MergeNonConflictingRunnable(isLeftEditable, isRightEditable, mergeMode) {
+ @Override
+ protected void addOrUpdateMergeData(Collection<Diff> differences, MergeMode mode) {
+ // do nothing to prevent call of EcoreUtil.getAdapter()
+ }
+
+ @Override
+ protected void markAsMerged(Diff diff, MergeMode mode, boolean mergeRightToLeft, Registry registry) {
+ // overwritten to prevent call of EcoreUtil.getAdapter()
+ // note that we rely on setting diff state to merged in verifyHasBeenMarkedAsMerged(Diff)
+ diff.setState(MERGED);
+ }
+ };
+ }
+
+}
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 8552852..1944cb3 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
@@ -31,7 +31,7 @@
import org.eclipse.emf.compare.ide.ui.tests.logical.resolver.ThreadedModelResolverWithCustomDependencyProviderTest;
import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.NavigatableTest;
import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeActionTest;
-import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeAllNonConflictingRunnableTest;
+import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeNonConflictingRunnableTest;
import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.PseudoConflictsMergeActionTest;
import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.notloadedfragment.NotLoadedFragmentNodeTest;
import org.eclipse.emf.compare.ide.ui.tests.unit.DependenciesTest;
@@ -52,7 +52,7 @@
ThreadedModelResolverWithCustomDependencyProviderTest.class, DependencyGraphUpdaterTest.class,
GraphResolutionTest.class, EMFModelProviderTest.class, MergeAllCommandTests.class,
LocalMonitoredProxyCreationListenerTest.class, RemoteMonitoredProxyCreationListenerTest.class,
- MergeAllNonConflictingRunnableTest.class })
+ MergeNonConflictingRunnableTest.class })
public class AllTests {
/**
* Launches the test with the given arguments.
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
index 8f4e6bf..46c0f85 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 Obeo.
+ * Copyright (c) 2013, 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
@@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
-import com.google.common.base.Preconditions;
-
import java.util.Collections;
import java.util.List;
@@ -52,21 +50,8 @@
public MergeAllNonConflictingAction(ICompareEditingDomain editingDomain, Comparison comparison,
IMerger.Registry mergerRegistry, MergeMode mode, boolean isLeftEditable, boolean isRightEditable) {
super(editingDomain, mergerRegistry, mode, isLeftEditable, isRightEditable, null);
-
- Preconditions.checkNotNull(mode);
- Preconditions.checkState(isLeftEditable || isRightEditable);
- // if left and right editable, the only accepted mode are LtR or RtL
- if (isLeftEditable && isRightEditable) {
- Preconditions.checkState(mode == MergeMode.LEFT_TO_RIGHT || mode == MergeMode.RIGHT_TO_LEFT);
- }
- // if mode is accept or reject, left and right can't be both read only (no action should be created in
- // this case) and can't be both editable.
- if (isLeftEditable != isRightEditable) {
- Preconditions.checkState(mode == MergeMode.ACCEPT || mode == MergeMode.REJECT);
- }
-
this.comparison = comparison;
- this.runnable = new MergeAllNonConflictingRunnable(isLeftEditable, isRightEditable, mode);
+ this.runnable = new MergeNonConflictingRunnable(isLeftEditable, isRightEditable, mode);
}
@Override
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
similarity index 83%
rename from plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java
rename to plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
index 123793b..bd55894 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
@@ -7,7 +7,7 @@
*
* Contributors:
* Obeo - initial API and implementation
- * Philip Langer - bug 469355
+ * Philip Langer - bug 469355, bug 462884, refactorings
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
@@ -34,10 +34,12 @@
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.domain.IMergeRunnable;
import org.eclipse.emf.compare.internal.domain.IMergeAllNonConflictingRunnable;
import org.eclipse.emf.compare.internal.merge.MergeDependenciesUtil;
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.internal.merge.MergeOperation;
+import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
import org.eclipse.emf.compare.internal.utils.Graph;
import org.eclipse.emf.compare.internal.utils.PruningIterator;
import org.eclipse.emf.compare.merge.BatchMerger;
@@ -47,11 +49,11 @@
import org.eclipse.emf.compare.merge.IMerger2;
/**
- * Implements the "merge all non-conflicting" action.
+ * Implements the "merge non-conflicting" and "merge all non-conflicting" action.
*
* @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
*/
-public class MergeAllNonConflictingRunnable extends AbstractMergeRunnable implements IMergeAllNonConflictingRunnable {
+public class MergeNonConflictingRunnable extends AbstractMergeRunnable implements IMergeAllNonConflictingRunnable, IMergeRunnable {
/**
* Default constructor.
*
@@ -62,7 +64,7 @@
* @param mergeMode
* Merge mode for this operation.
*/
- public MergeAllNonConflictingRunnable(boolean isLeftEditable, boolean isRightEditable, MergeMode mergeMode) {
+ public MergeNonConflictingRunnable(boolean isLeftEditable, boolean isRightEditable, MergeMode mergeMode) {
super(isLeftEditable, isRightEditable, mergeMode);
}
@@ -71,20 +73,52 @@
*/
public Iterable<Diff> merge(Comparison comparison, boolean leftToRight, Registry mergerRegistry) {
checkState(getMergeMode().isLeftToRight(isLeftEditable(), isRightEditable()) == leftToRight);
+ return doMergeNonConflicting(comparison.getDifferences(), comparison, leftToRight, mergerRegistry);
+ }
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Differences that are conflicting or that depend on conflicting differences will be left out.
+ * Non-conflicting differences that are implied or required by the given differences will be merged, also
+ * if they are not explicitly included in the given list of {@code differences}.
+ * </p>
+ */
+ @SuppressWarnings("unchecked")
+ public void merge(List<? extends Diff> differences, boolean leftToRight, Registry mergerRegistry) {
+ checkState(getMergeMode().isLeftToRight(isLeftEditable(), isRightEditable()) == leftToRight);
+ checkState(!differences.isEmpty() && ComparisonUtil.getComparison(differences.get(0)) != null);
+ final Comparison comparison = ComparisonUtil.getComparison(differences.get(0));
+ doMergeNonConflicting((Collection<Diff>)differences, comparison, leftToRight, mergerRegistry);
+ }
+
+ /**
+ * Performs the merge of the non-conflicting differences in the given {@code differences}.
+ *
+ * @param differences
+ * The differences to be merged.
+ * @param comparison
+ * The comparison containing the differences to decide on whether conflicts are in play or not
+ * and to determine whether this is a three- or two-way comparison.
+ * @param leftToRight
+ * The direction in which {@code differences} should be merged.
+ * @param mergerRegistry
+ * The registry of mergers.
+ * @return an iterable over the differences that have actually been merged by this operation.
+ */
+ private Iterable<Diff> doMergeNonConflicting(Collection<Diff> differences, Comparison comparison,
+ boolean leftToRight, Registry mergerRegistry) {
final Iterable<Diff> affectedChanges;
if (hasRealConflict(comparison)) {
// This is a 3-way comparison, pre-merge what can be.
- affectedChanges = mergeWithConflicts(comparison.getDifferences(), leftToRight, mergerRegistry);
+ affectedChanges = mergeWithConflicts(differences, leftToRight, mergerRegistry);
} else if (comparison.isThreeWay()) {
// This is a 3-way comparison without conflicts
- affectedChanges = mergeThreeWayWithoutConflicts(comparison.getDifferences(), leftToRight,
- mergerRegistry);
+ affectedChanges = mergeThreeWayWithoutConflicts(differences, leftToRight, mergerRegistry);
} else {
// This is a 2-way comparison
- affectedChanges = mergeTwoWay(comparison.getDifferences(), leftToRight, mergerRegistry);
+ affectedChanges = mergeTwoWay(differences, leftToRight, mergerRegistry);
}
-
return affectedChanges;
}