blob: 10d8c811a0b46a99356a84e66c8130a3dd3f5dd9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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:
* wesendon
******************************************************************************/
package org.eclipse.emf.emfstore.client.conflictdetection.test.merging;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.emfstore.client.test.common.cases.ESTest;
import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.internal.client.model.changeTracking.merging.DecisionManager;
import org.eclipse.emf.emfstore.internal.client.model.changeTracking.merging.conflict.VisualConflict;
import org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommand;
import org.eclipse.emf.emfstore.internal.common.model.ModelElementId;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ChangeConflictSet;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ConflictDetector;
import org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
/**
* Helper super class for merge tests.
*
* @author wesendon
*/
public class MergeTest extends ESTest {
private MergeCase mergeCase;
/**
* Default Constructor.
*
* @return case helper
*/
public MergeCase newMergeCase() {
return newMergeCase(new EObject[0]);
}
public MergeCase newMergeCase(EObject... objs) {
mergeCase = new MergeCase();
mergeCase.add(objs);
mergeCase.ensureCopy();
return mergeCase;
}
public List<ModelElementId> getIds(EObject... objs) {
final ArrayList<ModelElementId> result = new ArrayList<ModelElementId>();
for (final EObject obj : objs) {
result.add(mergeCase.getMyId(obj));
}
return result;
}
public ModelElementId getId(EObject obj) {
return mergeCase.getMyId(obj);
}
public ModelElementId getMyId(EObject obj) {
return mergeCase.getMyId(obj);
}
public ModelElementId getTheirId(EObject obj) {
return mergeCase.getTheirId(obj);
}
/**
* Helper class for merge tests. It manages the two projectspaces and offers covenience methods.
*
* @author wesendon
*/
public class MergeCase {
private ProjectSpace theirProjectSpace;
private void add(final EObject... objs) {
new EMFStoreCommand() {
@Override
protected void doRun() {
for (final EObject obj : objs) {
getProject().addModelElement(obj);
}
}
}.run(false);
}
public void addTheirs(final EObject... objs) {
new EMFStoreCommand() {
@Override
protected void doRun() {
for (final EObject obj : objs) {
getTheirProject().addModelElement(obj);
}
}
}.run(false);
}
@SuppressWarnings("unchecked")
public <T extends EObject> T getMyItem(T id) {
ensureCopy();
return (T) getProject().getModelElement(byId(id));
}
public ModelElementId getMyId(EObject obj) {
return getProject().getModelElementId(obj);
}
public ModelElementId getTheirId(EObject obj) {
return getTheirProject().getModelElementId(getTheirItem(obj));
}
@SuppressWarnings("unchecked")
public <T extends EObject> T getTheirItem(T id) {
ensureCopy();
return (T) getTheirProject().getModelElement(byId(id));
}
private ModelElementId byId(EObject id) {
return getProject().getModelElementId(id);
}
public void ensureCopy() {
if (theirProjectSpace == null) {
new EMFStoreCommand() {
@Override
protected void doRun() {
clearOperations();
theirProjectSpace = cloneProjectSpace(getProjectSpace());
}
}.run(false);
}
}
public Project getTheirProject() {
ensureCopy();
return theirProjectSpace.getProject();
}
public ProjectSpace getTheirProjectSpace() {
ensureCopy();
return theirProjectSpace;
}
public DecisionManager execute() {
ensureCopy();
final List<AbstractChangePackage> myChangePackages = Arrays.asList(getProjectSpace().getLocalChangePackage(
true));
final List<AbstractChangePackage> theirChangePackages = Arrays.asList(getTheirProjectSpace()
.getLocalChangePackage(true));
final ChangeConflictSet changeConflictSet = new ConflictDetector().calculateConflicts(
myChangePackages,
theirChangePackages,
getProject());
final DecisionManager manager = new DecisionManager(getProject(), changeConflictSet, false);
return manager;
}
public <T extends VisualConflict> MergeTestQuery hasConflict(Class<T> clazz, int expectedConflicts) {
final MergeTestQuery query = new MergeTestQuery(execute());
return query.hasConflict(clazz, expectedConflicts);
}
public <T extends VisualConflict> MergeTestQuery hasConflict(Class<T> clazz) {
if (clazz == null) {
final ArrayList<VisualConflict> conflicts = execute().getConflicts();
assertEquals(0, conflicts.size());
return null;
}
return hasConflict(clazz, 1);
}
public ProjectSpace getMyProjectSpace() {
return getProjectSpace();
}
}
public class MergeTestQuery {
private final DecisionManager manager;
private ArrayList<VisualConflict> conflicts;
private Object lastObject;
private final HashSet<AbstractOperation> mySeen;
private final HashSet<AbstractOperation> theirSeen;
public MergeTestQuery(DecisionManager manager) {
this.manager = manager;
mySeen = new LinkedHashSet<AbstractOperation>();
theirSeen = new LinkedHashSet<AbstractOperation>();
}
public <T extends VisualConflict> MergeTestQuery hasConflict(Class<T> clazz, int i) {
conflicts = manager.getConflicts();
assertEquals("Number of conflicts", i, conflicts.size()); //$NON-NLS-1$
final VisualConflict currentConflict = currentConflict();
if (!clazz.isInstance(currentConflict)) {
throw new AssertionError("Expected: " + clazz.getName() + " but found: " //$NON-NLS-1$ //$NON-NLS-2$
+ (currentConflict == null ? "null" : currentConflict.getClass().getName())); //$NON-NLS-1$
}
return this;
}
private VisualConflict currentConflict() {
return conflicts.get(0);
}
@SuppressWarnings("unchecked")
public <T extends AbstractOperation> T getMy(Class<T> class1) {
final AbstractOperation myOp = currentConflict().getMyOperation();
if (!class1.isInstance(myOp)) {
throw new AssertionError("Expected: " + class1.getName() + " but found: " //$NON-NLS-1$ //$NON-NLS-2$
+ (myOp == null ? "null" : myOp.getClass().getName())); //$NON-NLS-1$
}
return (T) myOp;
}
@SuppressWarnings("unchecked")
public <T extends AbstractOperation> T getTheir(Class<T> class1) {
final AbstractOperation theirOp = currentConflict().getTheirOperation();
assertTrue(class1.isInstance(theirOp));
return (T) theirOp;
}
public <T extends AbstractOperation> MergeTestQuery myIs(Class<T> class1) {
last(true, getMy(class1));
return this;
}
public <T extends AbstractOperation> MergeTestQuery myOtherContains(Class<T> class1) {
final Set<AbstractOperation> ops = currentConflict().getMyOperations();
for (final AbstractOperation op : ops) {
if (class1.isInstance(op) && op != currentConflict().getMyOperation()) {
last(true, op);
return this;
}
}
throw new AssertionError("Expected: " + class1.getName() + " in other my operations but was not found"); //$NON-NLS-1$ //$NON-NLS-2$
}
public <T extends AbstractOperation> MergeTestQuery theirsIs(Class<T> class1) {
last(false, getTheir(class1));
return this;
}
private void last(boolean my, AbstractOperation op) {
lastObject = op;
if (my) {
mySeen.add(op);
} else {
theirSeen.add(op);
}
}
public MergeTestQuery andNoOtherMyOps() {
final HashSet<AbstractOperation> my = new LinkedHashSet<AbstractOperation>(currentConflict()
.getMyOperations());
my.removeAll(mySeen);
assertEquals(0, my.size());
return this;
}
public MergeTestQuery andNoOtherTheirOps() {
final HashSet<AbstractOperation> theirs = new LinkedHashSet<AbstractOperation>(currentConflict()
.getTheirOperations());
theirs.removeAll(theirSeen);
assertEquals(0, theirs.size());
return this;
}
public MergeTestQuery andReturns(String methodName, Object b) {
assertTrue(lastObject != null);
try {
for (final Method method : lastObject.getClass().getMethods()) {
if (method.getName().equals(methodName)) {
final Object invoke = method.invoke(lastObject, (Object[]) null);
assertEquals(b, invoke);
return this;
}
}
} catch (final IllegalArgumentException e) {
} catch (final IllegalAccessException e) {
} catch (final InvocationTargetException e) {
}
throw new AssertionError("No such method"); //$NON-NLS-1$
}
}
}