| /******************************************************************************* |
| * Copyright (c) 2016, 2017 EclipseSource Services 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: |
| * Martin Fleck - initial API and implementation |
| * Christian W. Damus - bug 528272 |
| *******************************************************************************/ |
| package org.eclipse.papyrus.compare.uml2.tests.profiles.migration; |
| |
| 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.assertTrue; |
| |
| import com.google.common.base.Predicate; |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.Iterables; |
| |
| import java.util.List; |
| |
| import org.eclipse.emf.common.util.Diagnostic; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.compare.AttributeChange; |
| 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.Match; |
| import org.eclipse.emf.compare.ReferenceChange; |
| import org.eclipse.emf.compare.ResourceAttachmentChange; |
| import org.eclipse.emf.compare.diff.DefaultDiffEngine; |
| import org.eclipse.emf.compare.ide.ui.tests.framework.RuntimeTestRunner; |
| import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.Compare; |
| import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.DiffEngines; |
| import org.eclipse.emf.compare.ide.ui.tests.framework.internal.CompareTestSupport; |
| import org.eclipse.emf.compare.uml2.internal.ProfileApplicationChange; |
| import org.eclipse.emf.compare.uml2.internal.StereotypeApplicationChange; |
| import org.eclipse.emf.compare.uml2.internal.StereotypeAttributeChange; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.FeatureMap.Entry; |
| import org.eclipse.emf.ecore.xml.type.AnyType; |
| import org.eclipse.papyrus.compare.uml2.internal.hook.ProfileMigrationHook; |
| import org.eclipse.papyrus.compare.uml2.internal.hook.migration.ProfileMigrationDiagnostic; |
| import org.eclipse.papyrus.compare.uml2.internal.hook.migration.ProfileNamespaceURIPatternAPI; |
| import org.eclipse.papyrus.compare.uml2.tests.blocks.Block; |
| import org.eclipse.papyrus.compare.uml2.tests.elements.Viewpoint; |
| import org.eclipse.uml2.uml.Class; |
| import org.eclipse.uml2.uml.util.UMLUtil; |
| import org.junit.ClassRule; |
| import org.junit.rules.TestRule; |
| import org.junit.runner.RunWith; |
| |
| /** |
| * <p> |
| * Tests whether the {@link ProfileMigrationHook profile migration} correctly migrates the models if their |
| * profile applications can not be found. |
| * </p> |
| * <p> |
| * The basic migrated, example structure is a MyML model with two stereotype applications on the same UML |
| * class element: One Block application from the package Blocks with the feature |
| * {@link Block#isEncapsulated()} set to true and one Viewpoint application from the package ModelElements |
| * with the feature {@link Viewpoint#getPurpose()} set to 'This is just for testing.'. |
| * </p> |
| * <ul> |
| * <li>Block definition: http://www.eclipse.org/papyrus/compare/test/profile/MyML/Blocks</li> |
| * <li>Viewpoint definition: http://www.eclipse.org/papyrus/compare/test/profile/MyML/ModelElements</li> |
| * </ul> |
| * <p> |
| * Artificial older profile versions of the model can not be found and therefore trigger the migration to an |
| * existing (newer) profile version, i.e., the versions as specified above. Since the migration is built on |
| * top of the Papyrus model repair mechanism, we need to ensure that packages are recognized correctly. This |
| * mainly implies that there needs to be a version number at the end of the URI. The older versions are |
| * therefore: |
| * </p> |
| * <ul> |
| * <li>Block package definition: http://www.eclipse.org/papyrus/compare/test/profile/MyML/Blocks<b>/1</b></li> |
| * <li>Viewpoint package definition: |
| * http://www.eclipse.org/papyrus/compare/test/profile/MyML/ModelElements<b>/1</b></li> |
| * </ul> |
| * <p> |
| * If the number at the end would not be given, both packages would be assumed to be the same and some |
| * stereotypes would be deleted. |
| * </p> |
| * |
| * @author Martin Fleck <mfleck@eclipsesource.com> |
| */ |
| @SuppressWarnings({"nls", "restriction" }) |
| @RunWith(RuntimeTestRunner.class) |
| @DiffEngines({DefaultDiffEngine.class }) |
| public class ProfileMigrationTest { |
| |
| /** Qualified name of the {@code Block} stereotype. */ |
| public static final String BLOCK = "MyML::Blocks::Block"; |
| |
| /** Qualified name of the {@code Viewpoint} stereotype. */ |
| public static final String VIEWPOINT = "MyML::ModelElements::Viewpoint"; |
| |
| /** |
| * Default value for the purpose feature of the Viewpoint stereotype. |
| */ |
| protected static final String VIEWPOINT_PURPOSE = "This is just for testing."; |
| |
| /** |
| * Changed value for the purpose feature of the Viewpoint stereotype. |
| */ |
| protected static final String VIEWPOINT_PURPOSE_CHANGE = "This is just for enhanced testing."; |
| |
| /** |
| * Changed value for the purpose feature of the Viewpoint stereotype, different from |
| * {@link #VIEWPOINT_PURPOSE_CHANGE}. |
| */ |
| protected static final String VIEWPOINT_PURPOSE_OTHER_CHANGE = "This is just for very enhanced testing."; |
| |
| /** |
| * Default value for the isEncapsulated feature of the Block stereotype. |
| */ |
| protected static final boolean BLOCK_ISENCAPSULATED = true; |
| |
| @ClassRule |
| public static final TestRule READ_ONLY_RULE = new TestResourceReadOnlyHandler.Rule(); |
| |
| /* |
| * ============================ Helper Methods ============================ |
| */ |
| |
| /** |
| * A predicate that matches if the given {@link EObject} is an {@link AnyType} and has the given class |
| * name. |
| * |
| * @param className |
| * class name of the anytype object |
| * @return true if object is anytype and its class has the given name |
| */ |
| protected Predicate<EObject> anyType(final String className) { |
| return Predicates.and(Predicates.instanceOf(AnyType.class), new Predicate<EObject>() { |
| public boolean apply(final EObject object) { |
| return ((AnyType)object).eClass().getName().equals(className); |
| } |
| }); |
| } |
| |
| /** |
| * Returns the provided object if it is not null and throws an error otherwise. |
| * |
| * @param object |
| * object to test |
| * @return object |
| */ |
| protected <T> T checkNotNull(final T object) { |
| return checkNotNull("Unexpected null value.", object); |
| } |
| |
| /** |
| * Returns the provided object if it is not null and throws an error with the given message otherwise. |
| * |
| * @param errorMessage |
| * message to be used in the error |
| * @param object |
| * object to test |
| * @return object |
| */ |
| protected <T> T checkNotNull(final String errorMessage, final T object) { |
| assertNotNull(errorMessage, object); |
| return object; |
| } |
| |
| /** |
| * Returns all profile migration warnings of the given resource. |
| * |
| * @param resource |
| * @return profile migration warnings |
| */ |
| protected Iterable<ProfileMigrationDiagnostic> getMigrationWarnings(final Resource resource) { |
| return Iterables.filter(resource.getWarnings(), ProfileMigrationDiagnostic.class); |
| } |
| |
| /** |
| * Returns all profile migration errors of the given resource. |
| * |
| * @param resource |
| * @return profile migration errors |
| */ |
| protected Iterable<ProfileMigrationDiagnostic> getMigrationErrors(final Resource resource) { |
| return Iterables.filter(resource.getErrors(), ProfileMigrationDiagnostic.class); |
| } |
| |
| /** |
| * Returns the root of this resource if it is not null. Throws an error otherwise. |
| * |
| * @param resource |
| * @return root of the resource |
| */ |
| protected EObject getRoot(final Resource resource) { |
| // let it fail if resource is null |
| return checkNotNull("Root null.", resource.getContents().get(0)); |
| } |
| |
| /** |
| * Asserts that the migrated resources contains the specified number of successful and failed package |
| * migrations. |
| * |
| * @param resource |
| * @param successfulPackageMigrations |
| * @param failedPackageMigrations |
| */ |
| protected void assertPartialMigration(final Resource resource, final int successfulPackageMigrations, |
| final int failedPackageMigrations) { |
| assertMigrationSuccess(resource, successfulPackageMigrations); |
| assertMigrationFails(resource, failedPackageMigrations); |
| } |
| |
| /** |
| * Asserts that the migrated resource contains the specified number of successful package migrations. |
| * |
| * @param resource |
| * @param successfulPackageMigrations |
| */ |
| protected void assertMigrationSuccess(final Resource resource, final int successfulPackageMigrations) { |
| // migration warnings: successful migrations |
| assertEquals(successfulPackageMigrations, Iterables.size(getMigrationWarnings(resource))); |
| } |
| |
| /** |
| * Asserts that the migrated resource contains the specified number of failed package migrations. |
| * |
| * @param resource |
| * @param successfulPackageMigrations |
| */ |
| protected void assertMigrationFails(final Resource resource, final int failedPackageMigrations) { |
| // migration errors: failed migrations |
| assertEquals(failedPackageMigrations, Iterables.size(getMigrationErrors(resource))); |
| } |
| |
| /** |
| * Asserts that the resource has not been migrated, i.e., it has no migration warnings and errors. |
| * |
| * @param resource |
| * @param successfulPackageMigrations |
| */ |
| protected void assertNoMigration(final Resource resource) { |
| assertPartialMigration(resource, 0, 0); |
| } |
| |
| /** |
| * Asserts that the migrated resources has been completely migrated, i.e., it has two migration warnings |
| * and no errors |
| * |
| * @param resource |
| */ |
| protected void assertMigration(final Resource resource) { |
| assertPartialMigration(resource, 2, 0); |
| } |
| |
| /** |
| * Returns the only UML class in the given resource. If no class is found or multiple classes are found, |
| * an error is thrown. |
| * |
| * @param resource |
| * @return the single UML class |
| */ |
| protected Class getSingleUMLClass(final Resource resource) { |
| final EObject root = getRoot(resource); |
| final Iterable<Class> umlClasses = Iterables.filter(root.eContents(), Class.class); |
| final Class umlClass = Iterables.getOnlyElement(umlClasses); |
| return umlClass; |
| } |
| |
| /** |
| * Asserts that there is the correct number of differences expected from the change of an attribute in the |
| * {@link Viewpoint} stereotype. |
| * |
| * @param comparison |
| * comparison containing the differences |
| * @param resource |
| * @param changeOnBothSides |
| * true if changes are expected on two sides |
| */ |
| protected void assertViewPointAttributeChange(final Comparison comparison, final Resource resource, |
| final boolean changeOnBothSides) { |
| final int expectedDifferences = changeOnBothSides ? 2 : 1; |
| |
| final Class singleUMLClass = getSingleUMLClass(resource); |
| final Viewpoint viewPoint = UMLUtil.getStereotypeApplication(singleUMLClass, Viewpoint.class); |
| |
| final Match classMatch = comparison.getMatch(singleUMLClass); |
| final EList<Diff> classDifferences = classMatch.getDifferences(); |
| |
| final Match viewPointMatch = comparison.getMatch(viewPoint); |
| final EList<Diff> viewPointDifferences = viewPointMatch.getDifferences(); |
| |
| assertEquals(expectedDifferences, viewPointDifferences.size()); |
| assertTrue(Iterables.all(viewPointDifferences, Predicates.instanceOf(AttributeChange.class))); |
| assertTrue( |
| Iterables.all(viewPointDifferences, PapyrusComparePredicates.ofKind(DifferenceKind.CHANGE))); |
| assertEquals(expectedDifferences, classDifferences.size()); |
| assertTrue(Iterables.all(classDifferences, Predicates.instanceOf(StereotypeAttributeChange.class))); |
| assertTrue(Iterables.all(classDifferences, PapyrusComparePredicates.ofKind(DifferenceKind.CHANGE))); |
| } |
| |
| /** |
| * Asserts that there is the correct number of differences expected from the addition of a stereotype. |
| * |
| * @param comparison |
| * comparison containing the differences |
| * @param resource |
| * migrated resource |
| * @param missingStereotypeClass |
| * added stereotype Application |
| * @param changeOnBothSides |
| * true if changes are expected on two sides |
| */ |
| protected void assertStereotypeAddition(final Comparison comparison, final Resource resource, |
| final java.lang.Class<? extends EObject> missingStereotypeClass, |
| final boolean changeOnBothSides) { |
| final int expectedDifferences = changeOnBothSides ? 2 : 1; |
| |
| final Class singleUMLClass = getSingleUMLClass(resource); |
| |
| final Match classMatch = comparison.getMatch(singleUMLClass); |
| final EList<Diff> classDifferences = classMatch.getDifferences(); |
| |
| final EObject stereotypeApplication = UMLUtil.getStereotypeApplication(singleUMLClass, |
| missingStereotypeClass); |
| |
| final Match stereotypeMatch = comparison.getMatch(stereotypeApplication); |
| final EList<Diff> stereotypeDifferences = stereotypeMatch.getDifferences(); |
| |
| assertEquals(expectedDifferences * 2, stereotypeDifferences.size()); |
| final Iterable<Diff> resourceAttachmentChanges = Iterables.filter(stereotypeDifferences, |
| Predicates.instanceOf(ResourceAttachmentChange.class)); |
| assertEquals(expectedDifferences, Iterables.size(resourceAttachmentChanges)); |
| assertTrue(Iterables.all(resourceAttachmentChanges, |
| PapyrusComparePredicates.ofKind(DifferenceKind.ADD))); |
| final Iterable<Diff> referenceChanges = Iterables.filter(stereotypeDifferences, |
| Predicates.instanceOf(ReferenceChange.class)); |
| assertEquals(expectedDifferences, Iterables.size(referenceChanges)); |
| assertTrue(Iterables.all(referenceChanges, PapyrusComparePredicates.ofKind(DifferenceKind.CHANGE))); |
| |
| assertEquals(expectedDifferences, classDifferences.size()); |
| assertTrue(Iterables.all(classDifferences, Predicates.instanceOf(StereotypeApplicationChange.class))); |
| assertTrue(Iterables.all(classDifferences, PapyrusComparePredicates.ofKind(DifferenceKind.ADD))); |
| } |
| |
| /** |
| * Asserts that there is the correct number of differences expected from the deletion of a profile |
| * application. |
| * |
| * @param comparison |
| * comparison containing the differences |
| * @param resource |
| * migrated resource |
| * @param changeOnBothSides |
| * true if changes are expected on two sides |
| */ |
| protected void assertProfileApplicationDeletion(final Comparison comparison, final Resource resource, |
| final boolean changeOnBothSides) { |
| final int expectedDifferences = changeOnBothSides ? 2 : 1; |
| |
| final EObject root = getRoot(resource); |
| final Match rootMatch = comparison.getMatch(root); |
| final EList<Diff> rootDifferences = rootMatch.getDifferences(); |
| |
| final Iterable<Diff> profileApplicationChanges = Iterables.filter(rootDifferences, |
| Predicates.instanceOf(ProfileApplicationChange.class)); |
| |
| assertEquals(expectedDifferences, Iterables.size(profileApplicationChanges)); |
| assertTrue(Iterables.all(profileApplicationChanges, |
| PapyrusComparePredicates.ofKind(DifferenceKind.DELETE))); |
| } |
| |
| /* |
| * ========================= Partial Migration Assertions ========================= |
| */ |
| |
| /** |
| * Asserts that the single UML class of this resource has the specified number of migrated stereotype |
| * applications. |
| * |
| * @param resource |
| * migrated resource |
| * @param migratedStereotypeApplications |
| * number of migrated stereotype applications |
| * @return the single UML class |
| * @see #getSingleUMLClass(Resource) |
| */ |
| protected Class assertPartiallyMigratedUmlClass(final Resource resource, |
| final int migratedStereotypeApplications) { |
| final Class umlClass = getSingleUMLClass(resource); |
| assertEquals("Expected " + migratedStereotypeApplications + " stereotype applications.", |
| migratedStereotypeApplications, umlClass.getStereotypeApplications().size()); |
| return umlClass; |
| } |
| |
| /** |
| * Asserts that part of the resource has been migrated. |
| * |
| * @param resource |
| * migrated resource |
| * @param migratedBlock |
| * whether the {@link Block} stereotype was migrated or not |
| * @param blockIsEncapsulated |
| * expected value of the {@link Block#isEncapsulated()} feature |
| * @param migratedViewpoint |
| * whether the {@link Viewpoint} stereotype was migrated or not |
| * @param viewPointPurpose |
| * expected value of the {@link Viewpoint#getPurpose()} feature |
| */ |
| protected void assertPartiallyMigratedStructure(final Resource resource, final boolean migratedBlock, |
| final boolean blockIsEncapsulated, final boolean migratedViewpoint, |
| final String viewPointPurpose) { |
| int migratedStereotypeApplications = 0; |
| if (migratedBlock) { |
| migratedStereotypeApplications++; |
| } |
| if (migratedViewpoint) { |
| migratedStereotypeApplications++; |
| } |
| Class umlClass = assertPartiallyMigratedUmlClass(resource, migratedStereotypeApplications); |
| if (migratedBlock) { |
| assertMigratedBlock(umlClass, blockIsEncapsulated); |
| } else { |
| assertUnmigratedBlock(resource, blockIsEncapsulated); |
| } |
| if (migratedViewpoint) { |
| assertMigratedViewPoint(umlClass, viewPointPurpose); |
| } else { |
| assertUnmigratedViewpoint(resource, viewPointPurpose); |
| } |
| } |
| |
| /* |
| * ========================= Migration Assertions ========================= |
| */ |
| |
| /** |
| * Asserts that the given UML class has a migrated {@link Block} stereotype applied that has the given |
| * encapsulated value. |
| * |
| * @param umlClass |
| * UML class to check |
| * @param isEncapsulated |
| * expected value of the {@link Block#isEncapsulated()} feature |
| * @return Block stereotype applied on the UML class |
| */ |
| @SuppressWarnings("boxing") |
| protected Block assertMigratedBlock(final Class umlClass, final boolean isEncapsulated) { |
| final Block block = UMLUtil.getStereotypeApplication(umlClass, Block.class); |
| assertNotNull("Block got deleted.", block); |
| assertEquals("Wrong value in Block.", isEncapsulated, block.isEncapsulated()); |
| return block; |
| } |
| |
| /** |
| * Asserts that the given UML class has a migrated {@link Viewpoint} stereotype applied that has the given |
| * encapsulated value. |
| * |
| * @param umlClass |
| * UML class to check |
| * @param purpose |
| * expected value of the {@link Viewpoint#getPurpose()} feature |
| * @return Viewpoint stereotype applied on the UML class |
| */ |
| protected Viewpoint assertMigratedViewPoint(final Class umlClass, final String purpose) { |
| final Viewpoint viewPoint = UMLUtil.getStereotypeApplication(umlClass, Viewpoint.class); |
| assertNotNull("Viewpoint got deleted.", viewPoint); |
| assertEquals("Wrong value in Viewpoint.", purpose, viewPoint.getPurpose()); |
| return viewPoint; |
| } |
| |
| /** |
| * Asserts the completely migrated structure with two migrated packages (Block and Viewpoint) and the |
| * resulting two stereotype applications. Furthermore, asserts that the stereotypes have the provided |
| * values. |
| * |
| * @param resource |
| * @param blockIsEncapsulated |
| * expected value of the {@link Block#isEncapsulated()} feature |
| * @param viewPointPurpose |
| * expected value of the {@link Viewpoint#getPurpose()} feature |
| */ |
| protected void assertMigratedStructure(final Resource resource, final boolean blockIsEncapsulated, |
| final String viewPointPurpose) { |
| assertPartiallyMigratedStructure(resource, true, blockIsEncapsulated, true, viewPointPurpose); |
| } |
| |
| /* |
| * ======================= No Migration Assertions ======================== |
| */ |
| |
| /** |
| * Asserts that the {@link Viewpoint} stereotype has not been migrated by checking that it is available as |
| * an {@link AnyType}. |
| * |
| * @param resource |
| * @param purpose |
| * expected value of the {@link Viewpoint#getPurpose()} feature |
| * @return the {@link AnyType} representing the {@link Viewpoint} stereotype application |
| */ |
| protected AnyType assertUnmigratedViewpoint(final Resource resource, final String purpose) { |
| final Iterable<EObject> viewPoints = Iterables.filter(resource.getContents(), anyType("Viewpoint")); |
| final AnyType viewPoint = (AnyType)Iterables.getOnlyElement(viewPoints); |
| boolean correctPropertyValue = false; |
| for (final Entry entry : viewPoint.getAnyAttribute()) { |
| if (entry.getEStructuralFeature().getName().equals("purpose") |
| && entry.getValue().toString().equals(purpose)) { |
| correctPropertyValue = true; |
| break; |
| } |
| } |
| assertTrue("Wrong value in Viewpoint.", correctPropertyValue); |
| return viewPoint; |
| } |
| |
| /** |
| * Asserts that the {@link Block} stereotype has not been migrated by checking that it is available as an |
| * {@link AnyType}. |
| * |
| * @param resource |
| * @param isEncapsulated |
| * expected value of the {@link Block#isEncapsulated()} feature |
| * @return the {@link AnyType} representing the {@link Block} stereotype application |
| */ |
| protected AnyType assertUnmigratedBlock(final Resource resource, final boolean isEncapsulated) { |
| final Iterable<EObject> viewPoints = Iterables.filter(resource.getContents(), anyType("Block")); |
| final AnyType block = (AnyType)Iterables.getOnlyElement(viewPoints); |
| boolean correctPropertyValue = false; |
| for (final Entry entry : block.getAnyAttribute()) { |
| if (entry.getEStructuralFeature().getName().equals("isEncapsulated") |
| && Boolean.parseBoolean(entry.getValue().toString()) == isEncapsulated) { |
| correctPropertyValue = true; |
| break; |
| } |
| } |
| assertTrue("Wrong value in Block.", correctPropertyValue); |
| return block; |
| } |
| |
| /** |
| * Asserts that the resource has not been migrated and contains {@link AnyType} for the missing stereotype |
| * applications. |
| * |
| * @param resource |
| * @param blockIsEncapsulated |
| * expected value of the {@link Block#isEncapsulated()} feature |
| * @param viewPointPurpose |
| * expected value of the {@link Viewpoint#getPurpose()} feature |
| */ |
| protected void assertUnmigratedStructure(final Resource resource, final boolean blockIsEncapsulated, |
| final String viewPointPurpose) { |
| assertPartiallyMigratedStructure(resource, false, blockIsEncapsulated, false, viewPointPurpose); |
| } |
| |
| /* |
| * ============================== Test Cases ============================== |
| */ |
| |
| /** |
| * All models follow the same, migrated structure. Therefore, no migration is executed. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/nodiff/left.uml", right = "data/myml/nodiff/right.uml", ancestor = "data/myml/nodiff/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testNoDifference(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertNoMigration(originResource); |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models (all models have same structure) |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // there are no conflicts and no differences since only the version changed |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the origin model even if the left and the right |
| * model are identical. There are no changes in the features. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/version/abb/left.uml", right = "data/myml/version/abb/right.uml", ancestor = "data/myml/version/abb/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testVersionChangeABB(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts and no differences since only the version changed |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the right and the origin model. There are no |
| * changes in the features. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/version/aba/left.uml", right = "data/myml/version/aba/right.uml", ancestor = "data/myml/version/aba/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testVersionChangeABA(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); |
| assertMigration(rightResource); // success: Block and Viewpoint package, no fails |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts and no differences since only the version changed |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the right and the origin model and feature |
| * changes are detected. In the left resource, the feature {@link Viewpoint#getPurpose()} has changed and |
| * the difference should be detected, but no conflict should be produced. This test is equivalent to |
| * {@link #testAttributeChangeAAB(Comparison, CompareTestSupport)} with reversed left and right sides. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/change/aba/left.uml", right = "data/myml/attribute/change/aba/right.uml", ancestor = "data/myml/attribute/change/aba/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testAttributeChangeABA(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); |
| assertMigration(rightResource); // success: Block and Viewpoint package, no fails |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_CHANGE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| // 2 differences related to viewPointChange: Attribute change refining a StereotypeAttributeChange |
| assertEquals(2, differences.size()); |
| assertViewPointAttributeChange(comparison, originResource, false); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the left and the origin model and feature |
| * changes are detected. In the right resource the feature {@link Viewpoint#getPurpose()} has changed and |
| * the difference should be detected, but no conflict should be produced. This test is equivalent to |
| * {@link #testAttributeChangeABA(Comparison, CompareTestSupport)} with reversed left and right sides. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/change/aab/left.uml", right = "data/myml/attribute/change/aab/right.uml", ancestor = "data/myml/attribute/change/aab/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testAttributeChangeAAB(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertMigration(leftResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_CHANGE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| // 2 differences related to viewPointChange: Attribute change refining a StereotypeAttributeChange |
| assertEquals(2, differences.size()); |
| assertViewPointAttributeChange(comparison, originResource, false); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the origin model and feature changes are |
| * detected. The {@link Viewpoint#getPurpose()} feature has changed in the left and right resource to the |
| * same value. So, differences should be detected, but no REAL conflict should be produced. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/change/abb/left.uml", right = "data/myml/attribute/change/abb/right.uml", ancestor = "data/myml/attribute/change/abb/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testAttributeChangeABB(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_CHANGE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_CHANGE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // 1 PSEUDO conflict: Viewpoint::purpose changed on both sides to equal value |
| assertEquals((conflicts.size() - 1) + " unexpected conflicts", 1, conflicts.size()); |
| assertTrue(Iterables.all(conflicts, |
| PapyrusComparePredicates.containsConflictOfTypes(ConflictKind.PSEUDO))); |
| |
| // 2 differences on both sides related to viewPointChange: Attribute change refining a |
| // StereotypeAttributeChange |
| assertEquals(4, differences.size()); |
| assertViewPointAttributeChange(comparison, originResource, true); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the origin model and feature changes are |
| * detected. The {@link Viewpoint#getPurpose()} feature has changed in the left and right resource to |
| * different values. So, differences should be detected and a REAL conflict should be produced. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/change/abc/left.uml", right = "data/myml/attribute/change/abc/right.uml", ancestor = "data/myml/attribute/change/abc/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testAttributeChangeABC(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_CHANGE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE_OTHER_CHANGE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| |
| // 1 REAL conflict: Viewpoint::purpose changed on both sides to equal value |
| assertEquals((conflicts.size() - 1) + " unexpected conflicts", 1, conflicts.size()); |
| assertTrue(Iterables.all(conflicts, |
| PapyrusComparePredicates.containsConflictOfTypes(ConflictKind.REAL))); |
| |
| // 2 differences on both sides related to viewPointChange: Attribute change refining a |
| // StereotypeAttributeChange |
| assertEquals(4, differences.size()); |
| assertViewPointAttributeChange(comparison, originResource, true); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the origin and right model and unknown features |
| * are removed as expected. The origin and the right model have a String attribute "oldAttribute" with the |
| * same value. This feature does not exist in the migrated version of the profile and should therefore be |
| * deleted. Since the profile migration happens before the comparison, this deletion is not part of the |
| * result. Therefore, all models are considered the same and no differences are detected. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/unmigrated/aba/left.uml", right = "data/myml/attribute/unmigrated/aba/right.uml", ancestor = "data/myml/attribute/unmigrated/aba/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testUnmigratedAttributeABA(final Comparison comparison, final CompareTestSupport support) { |
| // origin and right have oldAttribute="This is not available in the new version." in Viewpoint |
| // stereotype application, but this attribute is not in new version and gets lost |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); |
| assertMigration(rightResource); // success: Block and Viewpoint package, no fails |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts and differences |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests whether the profile migration correctly migrates the origin and right model and unknown features |
| * are created with their default value as expected. In this setup, the origin and the right model have no |
| * value for the {@link Viewpoint#getPurpose()} feature. Therefore the comparison should take the default |
| * value of this feature detect the change from the default value to the value in the left model. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/attribute/defaultval/aba/left.uml", right = "data/myml/attribute/defaultval/aba/right.uml", ancestor = "data/myml/attribute/defaultval/aba/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testAttributeDefaultValueABA(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| final Class singleUMLClass = getSingleUMLClass(originResource); |
| final Viewpoint viewPoint = UMLUtil.getStereotypeApplication(singleUMLClass, Viewpoint.class); |
| |
| assertNotNull("Viewpoint expected.", viewPoint); |
| |
| final String purposeDefaultValue = viewPoint.eClass().getEStructuralFeature("purpose") |
| .getDefaultValueLiteral(); |
| |
| // test migration |
| assertMigration(originResource); // success: Block and Viewpoint package, no fails |
| assertNoMigration(leftResource); |
| assertMigration(rightResource); // success: Block and Viewpoint package, no fails |
| |
| // test structure of models |
| assertMigratedStructure(originResource, BLOCK_ISENCAPSULATED, purposeDefaultValue); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, purposeDefaultValue); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| // 2 differences related to viewPointChange: Attribute change refining a StereotypeAttributeChange |
| assertEquals(2, differences.size()); |
| assertViewPointAttributeChange(comparison, originResource, false); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests the behavior if the a wrong profile definition is selected which does not contain the missing |
| * stereotype. As a result, the unmigratable stereotypes are deleted by the Papyrus model repair |
| * mechanism. For this example we use the following definitions for the origin model: |
| * <ul> |
| * <li>Block definition: http://www.eclipse.org/uml2/5.0.0/UML/WrongProfile/Standard/1</li> |
| * </ul> |
| * This definition is close enough to the UML Standard Profile with package URI |
| * http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard to automatically migrate the missing Block |
| * stereotype. As the UML Standard Profile does not contain a definition for Block, the stereotype is |
| * deleted since the correct Block class can not be determined. We therefore expect the comparison to |
| * yield an error since the profile definition changed and we can not handle it accordingly. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/uri/wrongmigrated/abb/left.uml", right = "data/myml/uri/wrongmigrated/abb/right.uml", ancestor = "data/myml/uri/wrongmigrated/abb/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testWrongMigratedPackageURIABB(final Comparison comparison, |
| final CompareTestSupport support) { |
| if (ProfileNamespaceURIPatternAPI.isAvailable()) { |
| // With the ProfileNamespaceURIPatternAPI, we don't perform string matching and therefore do not |
| // return a wrong profile. Instead, no profile is returned, leaving the Block stereotype intact. |
| return; |
| } |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| |
| assertMigration(originResource); // success: Viewpoint package, wrong success: Block package |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| |
| final Class umlClass = assertPartiallyMigratedUmlClass(originResource, 1); |
| assertMigratedViewPoint(umlClass, VIEWPOINT_PURPOSE); |
| |
| // Block was migrated to a wrong package, because the URI was not helpful enough |
| final Block blockApplication = UMLUtil.getStereotypeApplication(umlClass, Block.class); |
| assertNull("Block should have been deleted.", blockApplication); |
| // wrong migration -> deletion, so also no AnyType present |
| assertFalse(Iterables.tryFind(originResource.getContents(), Predicates.instanceOf(AnyType.class)) |
| .isPresent()); |
| |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // there are no conflicts and no differences since the comparison was not completed |
| assertEquals(Diagnostic.ERROR, comparison.getDiagnostic().getSeverity()); |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests the behavior if the profile definitions can not be migrated, but a wrong profile definition is |
| * selected instead. As a result, the unmigratable stereotypes are deleted by the Papyrus model repair |
| * mechanism. For this example we use the following definitions for the origin model: |
| * <ul> |
| * <li>Block definition: http://www.eclipse.org/fake/0/Lang/Fakes/1</li> |
| * </ul> |
| * Since we cannot find a proper profile containing such a package, the unresolved {@link AnyType}s remain |
| * in the resources. We expect the comparison to yield an error since the profile definition changed and |
| * we can not handle it accordingly. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/uri/notmigrated/abb/left.uml", right = "data/myml/uri/notmigrated/abb/right.uml", ancestor = "data/myml/uri/notmigrated/abb/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testNotMigratedPackageURIABB(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertPartialMigration(originResource, 1, 1); // could not migrate block |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertPartiallyMigratedStructure(originResource, false, BLOCK_ISENCAPSULATED, true, |
| VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // there are no conflicts and no differences since the comparison was not completed |
| assertEquals(Diagnostic.ERROR, comparison.getDiagnostic().getSeverity()); |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } |
| |
| /** |
| * Tests the behavior if the profile definitions can not be migrated, but a wrong profile definition is |
| * selected instead. As a result, the unmigratable stereotypes are deleted by the Papyrus model repair |
| * mechanism. For this example we use the following definitions for the left and origin model: |
| * <ul> |
| * <li>Block definition: http://www.eclipse.org/fake/0/Lang/Fakes/1</li> |
| * </ul> |
| * Since we cannot find a proper profile containing such a package, the unresolved {@link AnyType}s remain |
| * in the resources. We expect the comparison to yield an error since the profile definition changed and |
| * we can not handle it accordingly. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/uri/notmigrated/aab/left.uml", right = "data/myml/uri/notmigrated/aab/right.uml", ancestor = "data/myml/uri/notmigrated/aab/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testNotMigratedPackageURIAAB(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertPartialMigration(originResource, 1, 1); |
| assertPartialMigration(leftResource, 1, 1); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertPartiallyMigratedStructure(originResource, false, BLOCK_ISENCAPSULATED, true, |
| VIEWPOINT_PURPOSE); |
| assertPartiallyMigratedStructure(leftResource, false, BLOCK_ISENCAPSULATED, true, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // there are no conflicts and no differences since the comparison was not completed |
| assertEquals(Diagnostic.ERROR, comparison.getDiagnostic().getSeverity()); |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } |
| |
| /** |
| * Tests the behavior if the profile definitions follow not the expected URI scheme. As a result, |
| * stereotype applications are grouped incorrectly and deleted by the Papyrus model repair mechanism. For |
| * this example we use the following definitions for the origin model: |
| * <ul> |
| * <li>Block definition: http://www.eclipse.org/papyrus/compare/test/beta/profile/MyML/Blocks</li> |
| * <li>Viewpoint definition: |
| * http://www.eclipse.org/papyrus/compare/test/beta/profile/MyML/ModelElements</li> |
| * </ul> |
| * As a result, both definitions are assumed to be the same and the we only migrate stereotypes of the |
| * first found package. The remaining stereotypes can not be migrated with this package (as the definition |
| * would be in another package) and are deleted automatically together with their profile application. We |
| * therefore expect one stereotype to be added to the left and right model and therefore get differences |
| * and PSEUDO conflicts in the comparison. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/uri/wrongformat/abb/left.uml", right = "data/myml/uri/wrongformat/abb/right.uml", ancestor = "data/myml/uri/wrongformat/abb/origin.uml", resourceSetHooks = ProfileMigrationHook.class) |
| public void testWrongFormatPackageURIsABB(final Comparison comparison, final CompareTestSupport support) { |
| if (ProfileNamespaceURIPatternAPI.isAvailable()) { |
| // With the ProfileNamespaceURIPatternAPI, we don't perform string matching and therefore do not |
| // return a profile for URIs we cannot match. Instead, no profile is returned, resulting in an |
| // unsuccessful migration and not a wrong correct one. |
| return; |
| } |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertMigration(originResource); // success: Viewpoint package, wrong success: Block package |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| final Class umlClass = assertPartiallyMigratedUmlClass(originResource, 1); |
| // deletion is non-deterministic, sometimes Block is migrated, sometimes Viewpoint |
| final Viewpoint viewPointApplication = UMLUtil.getStereotypeApplication(umlClass, Viewpoint.class); |
| final Block blockApplication = UMLUtil.getStereotypeApplication(umlClass, Block.class); |
| java.lang.Class<? extends EObject> missingStereotypeClass = null; |
| if (viewPointApplication == null) { |
| // Block got migrated |
| missingStereotypeClass = Viewpoint.class; |
| assertNull("Viewpoint should have been deleted.", viewPointApplication); |
| assertMigratedBlock(umlClass, BLOCK_ISENCAPSULATED); |
| } else { |
| // Viewpoint got migrated |
| missingStereotypeClass = Block.class; |
| assertNull("Block should have been deleted.", blockApplication); |
| assertMigratedViewPoint(umlClass, VIEWPOINT_PURPOSE); |
| } |
| // no anytypes left as the stereotype got deleted and not only "not migrated" |
| assertFalse(Iterables.tryFind(originResource.getContents(), Predicates.instanceOf(AnyType.class)) |
| .isPresent()); |
| |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // test differences and conflicts |
| if (!PapyrusMigrationUtil.isLuna()) { |
| // 4 PSEUDO conflict: stereotype application (2) |
| assertEquals((conflicts.size() - 2) + " unexpected conflicts", 2, conflicts.size()); |
| assertTrue(Iterables.all(conflicts, |
| PapyrusComparePredicates.containsConflictOfTypes(ConflictKind.PSEUDO))); |
| |
| // 2 differences on both sides related to stereotype removal: ResourceAttachmentChange and |
| // ReferenceChange refining a StereotypeApplicationChange |
| assertEquals(6, differences.size()); |
| assertStereotypeAddition(comparison, rightResource, missingStereotypeClass, true); // both sides |
| } else { |
| // In the model repair mechanism of Luna, IDs were not preserved so we detect a lot of differences |
| // and PSEUDO conflicts through additions and removals as the elements are not matched as expected |
| } |
| } |
| |
| /** |
| * Tests the behavior without the profile migration capabilities, i.e., without the |
| * {@link ProfileMigrationHook}. We expect the comparison to yield an error since the profile definition |
| * changed and we can not handle it accordingly. |
| * |
| * @param comparison |
| * comparison object between the models |
| * @param support |
| * exposed by the testing framework |
| */ |
| @Compare(left = "data/myml/version/aba/left.uml", right = "data/myml/version/aba/right.uml", ancestor = "data/myml/version/aba/origin.uml") |
| public void testErrorWithoutMigration(final Comparison comparison, final CompareTestSupport support) { |
| final List<Diff> differences = comparison.getDifferences(); |
| final EList<Conflict> conflicts = comparison.getConflicts(); |
| |
| // does not use ProfileMigrationHook |
| final Resource originResource = support.getAncestorResource(); |
| final Resource leftResource = support.getLeftResource(); |
| final Resource rightResource = support.getRightResource(); |
| |
| // test migration |
| assertNoMigration(originResource); |
| assertNoMigration(leftResource); |
| assertNoMigration(rightResource); |
| |
| // test structure of models |
| assertUnmigratedStructure(originResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertMigratedStructure(leftResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| assertUnmigratedStructure(rightResource, BLOCK_ISENCAPSULATED, VIEWPOINT_PURPOSE); |
| |
| // there are no conflicts and no differences since the comparison was not completed |
| assertEquals(Diagnostic.ERROR, comparison.getDiagnostic().getSeverity()); |
| assertTrue("Unexpected conflicts: " + conflicts, conflicts.isEmpty()); |
| assertTrue("Unexpected differences: " + differences, differences.isEmpty()); |
| } |
| } |