blob: 1dff47f2d377d297f529091e6daf1cff17da4d25 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2017 Obeo 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:
* Obeo - initial API and implementation
* Christian W. Damus - bug 522064
*******************************************************************************/
package org.eclipse.emf.compare.uml2.tests.profiles;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.eclipse.emf.compare.ConflictKind.PSEUDO;
import static org.eclipse.emf.compare.DifferenceSource.LEFT;
import static org.eclipse.emf.compare.DifferenceSource.RIGHT;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.Diagnostic;
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.ReferenceChange;
import org.eclipse.emf.compare.uml2.internal.ProfileApplicationChange;
import org.eclipse.emf.compare.uml2.internal.StereotypeApplicationChange;
import org.eclipse.emf.compare.uml2.tests.AbstractDynamicProfileTest;
import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData;
import org.eclipse.emf.compare.uml2.tests.profiles.data.dynamic.DynamicProfileInputData;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.uml2.uml.UMLPackage;
import org.hamcrest.CustomTypeSafeMatcher;
import org.hamcrest.Matcher;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@SuppressWarnings("nls")
public class DynamicProfileTest extends AbstractDynamicProfileTest {
private DynamicProfileInputData input = new DynamicProfileInputData();
@BeforeClass
public static void setupClass() {
initEPackageNsURIToProfileLocationMap();
}
@AfterClass
public static void teardownClass() {
resetEPackageNsURIToProfileLocationMap();
}
@Test
public void testDynamicA10UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
final Comparison comparison = compare(left, right);
testAB1(TestKind.ADD, comparison);
}
@Test
public void testMergeRtLDynamicA10UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeRightToLeft(left, right, null);
}
@Test
public void testMergeLtRDynamicA10UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeLeftToRight(left, right, null);
}
@Test
public void testDynamicA11UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
final Comparison comparison = compare(right, left);
testAB1(TestKind.DELETE, comparison);
}
@Test
public void testMergeRtLDynamicA11UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeRightToLeft(right, left, null);
}
@Test
public void testMergeLtRDynamicA11UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeLeftToRight(right, left, null);
}
@Test
public void testDynamicA10UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
final Comparison comparison = compare(left, right, right);
testAB1(TestKind.ADD, comparison);
}
@Test
public void testMergeRtLDynamicA10UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeRightToLeft(left, right, right);
}
@Test
public void testMergeLtRDynamicA10UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeLeftToRight(left, right, right);
}
@Test
public void testDynamicA11UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
final Comparison comparison = compare(left, right, left);
testAB1(TestKind.DELETE, comparison);
}
@Test
public void testMergeRtLDynamicA11UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeRightToLeft(left, right, left);
}
@Test
public void testMergeLtRDynamicA11UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Left();
testMergeLeftToRight(left, right, left);
}
@Test
public void testA2UseCase() throws IOException {
final Resource left = input.getA2Left();
final Resource right = input.getA2Right();
final Comparison comparison = compare(left, right);
assertTrue(comparison.getDifferences().isEmpty());
}
/**
* Verify that a fatal error is reported when, in a three-way comparison, the origin has a different
* version of a profile applied than either other side.
*/
@SuppressWarnings("boxing")
@Test
public void testA3UseCase() throws IOException {
final Resource left = input.getA3Left();
final Resource right = input.getA3Right();
final Resource origin = input.getA3Origin();
final Comparison comparison = compare(left, right, origin);
assertThat("Comparison not cancelled", comparison.getDifferences(), empty());
assertThat(comparison.getDiagnostic().getSeverity(), greaterThanOrEqualTo(Diagnostic.ERROR));
}
/**
* Verify that a sensible comparison is computed, in a three-way comparison, when the origin does not have
* the profile applied that the other two sides have applied at the same version.
*/
@Test
public void testA4UseCase() throws IOException {
final Resource left = input.getA4Left();
final Resource right = input.getA4Right();
final Resource origin = input.getA4Origin();
final Comparison comparison = compare(left, right, origin);
assertThat("Comparison cancelled", comparison.getDifferences(), not(empty()));
Iterable<Diff> leftDiffs = filter(comparison.getDifferences(), fromSide(LEFT));
Iterable<Diff> rightDiffs = filter(comparison.getDifferences(), fromSide(RIGHT));
Diff leftPA = getOnlyElement(filter(leftDiffs, instanceOf(ProfileApplicationChange.class)));
assertThat(leftPA.getKind(), is(DifferenceKind.ADD));
Diff rightPA = getOnlyElement(filter(rightDiffs, instanceOf(ProfileApplicationChange.class)));
assertThat(rightPA.getKind(), is(DifferenceKind.ADD));
Set<Conflict> conflicts = getConflicts(leftPA);
assertThat("Left profile application not conflicting", conflicts, not(empty()));
assertThat("Left and right profile applications not conflicting exactly", getConflicts(rightPA),
is(conflicts));
assertThat("Some profile application conflicts is real", conflicts, everyItem(conflictIs(PSEUDO)));
Diff leftSA = getOnlyElement(filter(leftDiffs, instanceOf(StereotypeApplicationChange.class)));
assertThat(leftSA.getKind(), is(DifferenceKind.ADD));
Diff rightSA = getOnlyElement(filter(rightDiffs, instanceOf(StereotypeApplicationChange.class)));
assertThat(rightSA.getKind(), is(DifferenceKind.ADD));
}
/**
* Verify that a fatal error is reported when, in a three-way comparison, the origin has no profile
* definition annotation, indicating a static profile definition (simulated for this test).
*/
@SuppressWarnings("boxing")
@Test
public void testA5UseCase() throws IOException {
final Resource left = input.getA5Left();
final Resource right = input.getA5Right();
final Resource origin = input.getA5Origin();
final Comparison comparison = compare(left, right, origin);
assertThat("Comparison not cancelled", comparison.getDifferences(), empty());
assertThat(comparison.getDiagnostic().getSeverity(), greaterThanOrEqualTo(Diagnostic.ERROR));
}
/**
* Gets all of the conflicts of a {@code diff} and its refinements.
*
* @param diff
* a diff
* @return all of its conflicts
*/
private Set<Conflict> getConflicts(Diff diff) {
ImmutableSet.Builder<Conflict> result = ImmutableSet.builder();
result.addAll(Optional.fromNullable(diff.getConflict()).asSet());
for (Diff refining : diff.getRefinedBy()) {
result.addAll(getConflicts(refining));
}
return result.build();
}
/**
* Hamcrest matcher for conflicts of some {@code kind}.
*
* @param kind
* the kind of conflict to match
* @return the conflict-kind matcher
*/
private Matcher<Conflict> conflictIs(final ConflictKind kind) {
return new CustomTypeSafeMatcher<Conflict>(String.format("%s conflict", kind)) {
@Override
protected boolean matchesSafely(Conflict item) {
return item.getKind() == kind;
}
};
}
private void testAB1(TestKind kind, final Comparison comparison) {
final List<Diff> differences = comparison.getDifferences();
// We should have no less and no more than 5 differences
assertEquals(5, differences.size());
Predicate<? super Diff> addProfileApplicationDescription = null;
Predicate<? super Diff> addAppliedProfileInProfileApplicationDescription = null;
Predicate<? super Diff> addUMLAnnotationDescription = null;
Predicate<? super Diff> addReferencesInUMLAnnotationDescription = null;
if (kind.equals(TestKind.DELETE)) {
addProfileApplicationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.DELETE),
onRealFeature(UMLPackage.Literals.PACKAGE__PROFILE_APPLICATION));
// addAppliedProfileInProfileApplicationDescription = and(instanceOf(ReferenceChange.class),
// ofKind(DifferenceKind.CHANGE),
// onRealFeature(UMLPackage.Literals.PROFILE_APPLICATION__APPLIED_PROFILE),
// not(isChangeAdd()));
addUMLAnnotationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.DELETE),
onRealFeature(EcorePackage.Literals.EMODEL_ELEMENT__EANNOTATIONS));
addReferencesInUMLAnnotationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.DELETE),
onRealFeature(EcorePackage.Literals.EANNOTATION__REFERENCES));
} else {
addProfileApplicationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.ADD),
onRealFeature(UMLPackage.Literals.PACKAGE__PROFILE_APPLICATION));
// addAppliedProfileInProfileApplicationDescription = and(instanceOf(ReferenceChange.class),
// ofKind(DifferenceKind.CHANGE),
// onRealFeature(UMLPackage.Literals.PROFILE_APPLICATION__APPLIED_PROFILE), isChangeAdd());
addUMLAnnotationDescription = and(instanceOf(ReferenceChange.class), ofKind(DifferenceKind.ADD),
onRealFeature(EcorePackage.Literals.EMODEL_ELEMENT__EANNOTATIONS));
addReferencesInUMLAnnotationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.ADD), onRealFeature(EcorePackage.Literals.EANNOTATION__REFERENCES));
}
addAppliedProfileInProfileApplicationDescription = and(instanceOf(ReferenceChange.class),
ofKind(DifferenceKind.CHANGE), onFeature("appliedProfile"));
final Diff addProfileApplication = Iterators.find(differences.iterator(),
addProfileApplicationDescription);
final Diff addAppliedProfileInProfileApplication = Iterators.find(differences.iterator(),
addAppliedProfileInProfileApplicationDescription);
final Diff addUMLAnnotation = Iterators.find(differences.iterator(), addUMLAnnotationDescription);
final Diff addReferencesInUMLAnnotation = Iterators.find(differences.iterator(),
addReferencesInUMLAnnotationDescription);
assertNotNull(addProfileApplication);
assertNotNull(addAppliedProfileInProfileApplication);
assertNotNull(addUMLAnnotation);
assertNotNull(addReferencesInUMLAnnotation);
// CHECK EXTENSION
assertEquals(1, count(differences, instanceOf(ProfileApplicationChange.class)));
Diff addUMLProfileApplication = null;
if (kind.equals(TestKind.ADD)) {
addUMLProfileApplication = Iterators.find(differences.iterator(),
and(instanceOf(ProfileApplicationChange.class), ofKind(DifferenceKind.ADD)));
} else {
addUMLProfileApplication = Iterators.find(differences.iterator(),
and(instanceOf(ProfileApplicationChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLProfileApplication);
assertEquals(4, addUMLProfileApplication.getRefinedBy().size());
assertTrue(addUMLProfileApplication.getRefinedBy().contains(addReferencesInUMLAnnotation));
assertTrue(addUMLProfileApplication.getRefinedBy().contains(addAppliedProfileInProfileApplication));
assertTrue(addUMLProfileApplication.getRefinedBy().contains(addProfileApplication));
assertTrue(addUMLProfileApplication.getRefinedBy().contains(addUMLAnnotation));
// CHECK REQUIREMENT
assertEquals(0, addUMLProfileApplication.getRequires().size());
if (kind.equals(TestKind.ADD)) {
assertEquals(0, addProfileApplication.getRequires().size());
assertEquals(1, addUMLAnnotation.getRequires().size());
assertTrue(addUMLAnnotation.getRequires().contains(addProfileApplication));
assertEquals(1, addReferencesInUMLAnnotation.getRequires().size());
assertTrue(addReferencesInUMLAnnotation.getRequires().contains(addUMLAnnotation));
} else {
assertEquals(2, addProfileApplication.getRequires().size());
assertTrue(addProfileApplication.getRequires().contains(addAppliedProfileInProfileApplication));
assertTrue(addProfileApplication.getRequires().contains(addUMLAnnotation));
assertEquals(1, addUMLAnnotation.getRequires().size());
assertTrue(addUMLAnnotation.getRequires().contains(addReferencesInUMLAnnotation));
assertEquals(0, addReferencesInUMLAnnotation.getRequires().size());
}
// CHECK EQUIVALENCE
assertEquals(0, comparison.getEquivalences().size());
testIntersections(comparison);
}
@Override
protected AbstractUMLInputData getInput() {
return input;
}
}