/**
* Copyright (c) 2012, 2014 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*/
package org.eclipse.emf.compare.tests.fullcomparison;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.emf.compare.AttributeChange;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ResourceAttachmentChange;
import org.eclipse.emf.compare.match.IMatchEngine;
import org.eclipse.emf.compare.match.eobject.EcoreWeightProvider;
import org.eclipse.emf.compare.match.eobject.WeightProvider;
import org.eclipse.emf.compare.match.eobject.WeightProviderDescriptorRegistryImpl;
import org.eclipse.emf.compare.match.eobject.internal.WeightProviderDescriptorImpl;
import org.eclipse.emf.compare.match.impl.MatchEngineFactoryImpl;
import org.eclipse.emf.compare.match.impl.MatchEngineFactoryRegistryImpl;
import org.eclipse.emf.compare.scope.DefaultComparisonScope;
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.emf.compare.tests.framework.EMFCompareAssert;
import org.eclipse.emf.compare.tests.framework.EMFCompareTestBase;
import org.eclipse.emf.compare.tests.fullcomparison.data.distance.DistanceMatchInputData;
import org.eclipse.emf.compare.tests.suite.AllTests;
import org.eclipse.emf.compare.utils.EMFComparePrettyPrinter;
import org.eclipse.emf.compare.utils.UseIdentifiers;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.junit.Before;
import org.junit.Test;
@SuppressWarnings("nls")
public class ProximityComparisonTest extends EMFCompareTestBase {
@Before
public void setUp() throws Exception {
AllTests.fillEMFRegistries();
}
private DistanceMatchInputData inputData = new DistanceMatchInputData();
@Test
public void singleEObjectTest() throws Exception {
EPackage v1 = EcoreUtil.copy(EcorePackage.eINSTANCE);
EPackage v2 = EcoreUtil.copy(EcorePackage.eINSTANCE);
v1.getEClassifiers().clear();
v2.getEClassifiers().clear();
final IComparisonScope scope = new DefaultComparisonScope(v1, v2, null);
Comparison result = EMFCompare.builder().build().compare(scope);
assertAllMatched(Lists.newArrayList(v1), result);
assertEquals("We are supposed to have zero diffs", 0, result.getDifferences().size());
}
@Test
public void matchingSmallRenameChanges() throws Exception {
Resource left = inputData.getCompareLeft();
Resource right = inputData.getCompareRight();
final IComparisonScope scope = new DefaultComparisonScope(left, right, null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
assertEquals("We are supposed to have one rename diff", 1, result.getDifferences().size());
}
@Test
public void matchingIndenticInstances() throws Exception {
EPackage v1 = EcoreUtil.copy(EcorePackage.eINSTANCE);
EPackage v2 = EcoreUtil.copy(EcorePackage.eINSTANCE);
final IComparisonScope scope = new DefaultComparisonScope(v1, v2, null);
Comparison result = EMFCompare.builder().build().compare(scope);
assertAllMatched(Lists.newArrayList(v1), result);
assertEquals("We are supposed to have zero diffs", 0, result.getDifferences().size());
}
@Test
public void smallChangeOnEPackage() throws Exception {
EPackage v1 = EcoreUtil.copy(EcorePackage.eINSTANCE);
EPackage v2 = EcoreUtil.copy(EcorePackage.eINSTANCE);
v2.setName("renamed");
final IComparisonScope scope = new DefaultComparisonScope(v1, v2, null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
assertAllMatched(Lists.newArrayList(v1), result);
assertEquals("We are supposed to have a rename", 1, result.getDifferences().size());
}
@Test
public void packageAddDelete() throws Exception {
final IComparisonScope scope = new DefaultComparisonScope(inputData.getPackageAddDeleteLeft(),
inputData.getPackageAddDeleteRight(), null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
EMFComparePrettyPrinter.printComparison(result, System.out);
final List<Diff> differences = result.getDifferences();
EMFCompareAssert.assertAddedToReference(differences, "p1.p2", "eSubpackages", "p1.p2.subPackage",
DifferenceSource.LEFT);
EMFCompareAssert.assertRemovedFromReference(differences, "p1", "eSubpackages", "p1.another",
DifferenceSource.LEFT);
assertEquals("We are supposed to have zero diffs", 2, result.getDifferences().size());
}
@Test
public void packageAddRemoveNoRename() throws Exception {
final IComparisonScope scope = new DefaultComparisonScope(inputData.getPackageAddRemoveNoRenameLeft(),
inputData.getPackageAddRemoveNoRenameRight(), null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
EMFComparePrettyPrinter.printComparison(result, System.out);
assertEquals("We are supposed to have zero diffs", 2, result.getDifferences().size());
}
@Test
public void alwaysTakeTheClosestNoMatterTheIterationOrder() throws Exception {
final IComparisonScope scope = new DefaultComparisonScope(inputData.getVerySmallLeft(),
inputData.getVerySmallRight(), null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
assertEquals(
"The Match took on element which is close enough (in the limits) preventing the next iteration to take it (it was closest)",
1, result.getDifferences().size());
}
@Test
public void addRemoveAndNotRename() throws Exception {
final IComparisonScope scope = new DefaultComparisonScope(inputData.get391657Left(),
inputData.get391657Right(), null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
WeightProvider.Descriptor.Registry weightProviderRegistry = new WeightProviderDescriptorRegistryImpl();
EcoreWeightProvider weightProvider = new EcoreWeightProvider();
WeightProviderDescriptorImpl descriptor = new WeightProviderDescriptorImpl(weightProvider, 100,
Pattern.compile(".*"));
weightProviderRegistry.put(weightProvider.getClass().getName(), descriptor);
matchEngineFactoryRegistry
.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER, weightProviderRegistry));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
Iterator<AttributeChange> attrChanges = Iterators.filter(result.getDifferences().iterator(),
AttributeChange.class);
assertFalse("We are supposed to detect an addition/remove (and not a rename if that's what we get)",
attrChanges.hasNext());
}
@Test
public void resourceRootChange() throws Exception {
final IComparisonScope scope = new DefaultComparisonScope(inputData.get390666Left(),
inputData.get390666Right(), inputData.get390666Ancestor());
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
Iterator<ResourceAttachmentChange> attrChanges = Iterators.filter(result.getDifferences().iterator(),
ResourceAttachmentChange.class);
assertTrue("We are supposed to detect a new attachment to a resource", attrChanges.hasNext());
}
@Test
public void moveInAReferenceShouldNotAffectMatch() throws Exception {
/*
* See bug #391798 : moving elements a lot in a reference (like in changing index) should not affect
* the matching very much.
*/
final IComparisonScope scope = new DefaultComparisonScope(inputData.get391798Left(),
inputData.get391798Right(), null);
IMatchEngine.Factory.Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineFactoryRegistry.add(new MatchEngineFactoryImpl(UseIdentifiers.NEVER));
Comparison result = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineFactoryRegistry)
.build().compare(scope);
for (Diff dif : result.getDifferences()) {
if (dif instanceof ReferenceChange && dif.getKind() == DifferenceKind.MOVE) {
} else {
fail("We should only detect moves in the reference.");
}
}
}
private void assertAllMatched(Iterable<? extends EObject> eObjects, Comparison comparison) {
for (EObject eObject : eObjects) {
final Match match = comparison.getMatch(eObject);
assertTrue(eObject + " has no match", match != null);
}
}
}