Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langer2014-10-13 17:26:24 +0000
committerPhilip Langer2014-10-27 07:10:59 +0000
commitd8a83af8b15c8d0fb4a13dbcbb06d29240d35bf9 (patch)
tree10ef1248784fd2e048ebbc686a53368507784950 /plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict
parentf016bf99d10c350a0dc20df81e06d732c108d90e (diff)
downloadorg.eclipse.emf.compare-d8a83af8b15c8d0fb4a13dbcbb06d29240d35bf9.tar.gz
org.eclipse.emf.compare-d8a83af8b15c8d0fb4a13dbcbb06d29240d35bf9.tar.xz
org.eclipse.emf.compare-d8a83af8b15c8d0fb4a13dbcbb06d29240d35bf9.zip
[446947] Adds support for three-way merging multi-line String attributes
Changes applied to String attributes, which might for instance contain multiple lines of code in a model (e.g., OpaqueBehaviors in UML), will now be checked whether concurrent changes in the context of a three-way diff are mergeable using a three-way line-based merge algorithm. If yes, no conflict will be raised and they will be merged line by line. Therefore, this commit introduces a copy of the diff_match_patch class R106 and a ThreeWayTextDiff utility, which extends the capabilities of diff_match_patch to support three-way diffing and merging of text (as opposed to two-way diffing only). Bug: 446947 CQ: 8824 Change-Id: Ifc7a3144461f7d47750b90a8098d565279ee826d Signed-off-by: Philip Langer <planger@eclipsesource.com>
Diffstat (limited to 'plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict')
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/MultiLineAttributeConflictDetectionTest.java288
1 files changed, 288 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/MultiLineAttributeConflictDetectionTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/MultiLineAttributeConflictDetectionTest.java
new file mode 100644
index 000000000..2a9b2babb
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/MultiLineAttributeConflictDetectionTest.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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.tests.conflict;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Conflict;
+import org.eclipse.emf.compare.EMFCompare;
+import org.eclipse.emf.compare.scope.DefaultComparisonScope;
+import org.eclipse.emf.compare.scope.IComparisonScope;
+import org.eclipse.emf.compare.tests.merge.ThreeWayAttributeMergeScenario;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Test;
+
+/**
+ * Tests the conflict detection of concurrent changes of multi-line string attributes.
+ * <p>
+ * This test covers also the basic cases of single-line attributes to avoid regression.
+ * </p>
+ *
+ * @author Philip Langer <planger@eclipsesource.com>
+ */
+@SuppressWarnings("nls")
+public class MultiLineAttributeConflictDetectionTest {
+
+ private static final String NL = "\n";
+
+ @Test
+ public void multiLineAttributeChangeOnOneSide() throws IOException {
+ final String origin = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?";
+
+ final String left = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What _do_ they call it?" + NL // changed
+ + "They call it a Royale with Cheese." + NL //
+ + "" // removed
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac."; // added
+
+ final String right = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?";
+
+ compareAndAssertNoConflictInBothDirections(origin, left, right);
+ }
+
+ @Test
+ public void conflictingMultiLineAttributeChange_InsertInsertConflict() throws IOException {
+ final String origin = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String left = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What _do_ they call it?" + NL // changed
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String right = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it??" + NL // changed
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ compareAndAssertConflictInBothDirections(origin, left, right);
+ }
+
+ @Test
+ public void conflictingMultiLineAttributeChange_MultipleLinesInsertInsert() throws IOException {
+ final String origin = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String left = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a \"Royale with Cheese\"." + NL // changed
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String right = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "" // deleted
+ + "" // deleted
+ + "" // deleted
+ + "" // deleted
+ + "What _do_ they call a Big Mac?" + NL // changed
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ compareAndAssertConflictInBothDirections(origin, left, right);
+ }
+
+ @Test
+ public void conflictingMultiLineAttributeChange_DeleteInsertConflict() throws IOException {
+ final String origin = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String left = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What _do_ they call it?" + NL // changed
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String right = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "" // removed
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ compareAndAssertConflictInBothDirections(origin, left, right);
+ }
+
+ @Test
+ public void mergableMultiLineAttributeChangeOnBothSides() throws IOException {
+ final String origin = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String left = "" // removed
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What _do_ they call it?" + NL // changed
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "That's right." + NL //
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Mac.";
+
+ final String right = "They don't call it a Quarter Pounder with Cheese?" + NL //
+ + "Nah, they got the metric system, they wouldn't know what a Quarter Pounder is." + NL //
+ + "What do they call it?" + NL //
+ + "They call it a Royale with Cheese." + NL //
+ + "Royale with Cheese." + NL //
+ + "" // removed
+ + "What do they call a Big Mac?" + NL //
+ + "A Big Mac's a Big Mac, but they call it Le Big Maec."; // changed
+
+ compareAndAssertNoConflictInBothDirections(origin, left, right);
+ }
+
+ @Test
+ public void conflictingSingleLineAttributeChange() throws IOException {
+ final Comparison comparison = compare("A", "B", "C");
+ assertOneConflict(comparison);
+ }
+
+ @Test
+ public void conflictingSingleLineAttributeChangeAndDelete() throws IOException {
+ final Comparison comparison = compare("A", "", "C");
+ assertOneConflict(comparison);
+ }
+
+ @Test
+ public void singleLineAttributeChangeRightSide() throws IOException {
+ final Comparison comparison = compare("A", "A", "C");
+ assertNoConflict(comparison);
+ }
+
+ @Test
+ public void singleLineAttributeChangeLeftSide() throws IOException {
+ final Comparison comparison = compare("A", "B", "A");
+ assertNoConflict(comparison);
+ }
+
+ @Test
+ public void singleLineAttributeSet() throws IOException {
+ final Comparison comparison = compare(null, "B", null);
+ assertNoConflict(comparison);
+ }
+
+ @Test
+ public void singleLineAttributeUnset() throws IOException {
+ final Comparison comparison = compare("A", "A", null);
+ assertNoConflict(comparison);
+ }
+
+ @Test
+ public void singleLineAttributeRemove() throws IOException {
+ final Comparison comparison = compare("A", "A", "");
+ assertNoConflict(comparison);
+ }
+
+ private void compareAndAssertNoConflictInBothDirections(String origin, String left, String right)
+ throws IOException {
+ final Comparison comparisonLeftRight = compare(origin, left, right);
+ assertNoConflict(comparisonLeftRight);
+
+ final Comparison comparisonRightLeft = compare(origin, right, left);
+ assertNoConflict(comparisonRightLeft);
+ }
+
+ private void compareAndAssertConflictInBothDirections(final String origin, final String left,
+ final String right) throws IOException {
+ final Comparison comparisonLeftRight = compare(origin, left, right);
+ assertOneConflict(comparisonLeftRight);
+
+ final Comparison comparisonRightLeft = compare(origin, right, left);
+ assertOneConflict(comparisonRightLeft);
+ }
+
+ private Comparison compare(String origin, String left, String right) throws IOException {
+ final ThreeWayAttributeMergeScenario scenario = createMergeScenario(origin, left, right);
+ final Comparison comparison = compare(scenario);
+ return comparison;
+ }
+
+ private ThreeWayAttributeMergeScenario createMergeScenario(String origin, String left, String right)
+ throws IOException {
+ return new ThreeWayAttributeMergeScenario(origin, left, right);
+ }
+
+ private Comparison compare(final ThreeWayAttributeMergeScenario scenario) {
+ final Resource origin = scenario.getOriginResource();
+ final Resource left = scenario.getLeftResource();
+ final Resource right = scenario.getRightResource();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ final Comparison comparison = EMFCompare.builder().build().compare(scope);
+ return comparison;
+ }
+
+ private void assertOneConflict(final Comparison comparison) {
+ final List<Conflict> conflicts = comparison.getConflicts();
+ assertEquals(1, conflicts.size());
+ }
+
+ private void assertNoConflict(final Comparison comparison) {
+ final List<Conflict> conflicts = comparison.getConflicts();
+ assertEquals(0, conflicts.size());
+ }
+}

Back to the top