/** * <copyright> Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel. 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 </copyright> */ package org.eclipse.emf.emfstore.client.test.conflictDetection; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.emf.emfstore.client.model.ProjectSpace; import org.eclipse.emf.emfstore.client.model.impl.ProjectSpaceImpl; import org.eclipse.emf.emfstore.client.model.util.EMFStoreCommand; import org.eclipse.emf.emfstore.client.test.model.document.DocumentFactory; import org.eclipse.emf.emfstore.client.test.model.document.LeafSection; import org.eclipse.emf.emfstore.client.test.model.requirement.Actor; import org.eclipse.emf.emfstore.client.test.model.requirement.RequirementFactory; import org.eclipse.emf.emfstore.client.test.model.task.ActionItem; import org.eclipse.emf.emfstore.client.test.model.task.TaskFactory; import org.eclipse.emf.emfstore.common.model.ModelElementId; import org.eclipse.emf.emfstore.common.model.Project; import org.eclipse.emf.emfstore.server.conflictDetection.ConflictDetector; import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.CompositeOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.CreateDeleteOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.MultiReferenceOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.SingleReferenceOperation; import org.junit.Test; /** * Test conflict detection behaviour during a selective commit. * * @author mck */ public class ConflictDetectionSelectiveCommitSpecialCases extends ConflictDetectionTest { /** * Test the special case. */ @Test public void conflictSpecialCase() { final LeafSection leafSection1 = DocumentFactory.eINSTANCE.createLeafSection(); final LeafSection leafSection2 = DocumentFactory.eINSTANCE.createLeafSection(); final ActionItem ai = TaskFactory.eINSTANCE.createActionItem(); final Actor actor = RequirementFactory.eINSTANCE.createActor(); final Project project1 = getProject(); final ProjectSpace ps1 = getProjectSpace(); // 1. init first project and simulate commit new EMFStoreCommand() { @Override protected void doRun() { project1.addModelElement(leafSection1); project1.addModelElement(leafSection2); project1.addModelElement(actor); clearOperations(); } }.run(false); // 2. simulate checkout final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); final Project project2 = ps2.getProject(); // 3. simulate create actionItem and a selective commit of the create operation final List<AbstractOperation> commitedOperations = new ArrayList<AbstractOperation>(); new EMFStoreCommand() { @Override protected void doRun() { leafSection1.getModelElements().add(ai); } }.run(false); assertTrue("Create actionItem failed", ps1.getOperations().size() == 2); assertTrue("Create actionItem has wrong operations", ps1.getOperations().get(0) instanceof CreateDeleteOperation || ps1.getOperations().get(0) instanceof MultiReferenceOperation); assertTrue("Create actionItem has wrong operations", ps1.getOperations().get(1) instanceof CreateDeleteOperation || ps1.getOperations().get(1) instanceof MultiReferenceOperation); new EMFStoreCommand() { @Override protected void doRun() { for (AbstractOperation op : ps1.getOperations()) { if (op instanceof CreateDeleteOperation) { commitedOperations.add(op); ps1.getOperations().remove(op); } } } }.run(false); assertTrue("Commit actionItem failed", ps1.getOperations().size() == 1); assertTrue("Commit actionItem has wrong operation", ps1.getOperations().get(0) instanceof MultiReferenceOperation); assertTrue("Commit commitedOperations.size() is wrong", commitedOperations.size() == 1); assertTrue("Commited operation is wrong", commitedOperations.get(0) instanceof CreateDeleteOperation); // 4. simulate update of project 2 new EMFStoreCommand() { @Override protected void doRun() { ((ProjectSpaceImpl) ps2).applyOperations(commitedOperations, false); } }.run(false); // 5. move actionItem in project 2 from "orphans" to section2 new EMFStoreCommand() { @Override protected void doRun() { assertTrue("Not allowed operations in ps2", ps2.getOperations().isEmpty()); ModelElementId leafSection2Id = getProject().getModelElementId(leafSection2); ModelElementId aiId = getProject().getModelElementId(ai); LeafSection tmpLSection2 = (LeafSection) project2.getModelElement(leafSection2Id); ActionItem tmpAi = (ActionItem) project2.getModelElement(aiId); tmpLSection2.getModelElements().add(tmpAi); } }.run(false); assertTrue("Wrong number of operations in ps2 afer moving actionItem", ps2.getOperations().size() == 1); assertTrue("Move actionItem has wrong operation", ps2.getOperations().get(0) instanceof CompositeOperation); CompositeOperation compOp = (CompositeOperation) ps2.getOperations().get(0); assertTrue("CompositeOperation contains wrong operations", compOp.getSubOperations().get(0) instanceof MultiReferenceOperation || compOp.getSubOperations().get(0) instanceof SingleReferenceOperation); assertTrue("CompositeOperation contains wrong operations", compOp.getSubOperations().get(1) instanceof MultiReferenceOperation || compOp.getSubOperations().get(1) instanceof SingleReferenceOperation); // 6. commit the multireferenceoperation in ps1 // nothing to do here // 7. update ps2 -> conflictdetector List<AbstractOperation> endOps1 = ps1.getLocalOperations().getOperations(); assertTrue("endOps1.size() != 1", endOps1.size() == 1); assertTrue("endOps1.get(0) !instanceof MultiRefOp", endOps1.get(0) instanceof MultiReferenceOperation); List<AbstractOperation> endOps2 = ps2.getLocalOperations().getOperations(); assertTrue("endOps2.size() != 1", endOps2.size() == 1); assertTrue("endOps2.get(0) !instanceof CompositeOp", endOps2.get(0) instanceof CompositeOperation); compOp = (CompositeOperation) endOps2.get(0); assertTrue("CompositeOperation contains wrong operations", compOp.getSubOperations().get(0) instanceof MultiReferenceOperation || compOp.getSubOperations().get(0) instanceof SingleReferenceOperation); assertTrue("CompositeOperation contains wrong operations", compOp.getSubOperations().get(1) instanceof MultiReferenceOperation || compOp.getSubOperations().get(1) instanceof SingleReferenceOperation); ConflictDetector detec = new ConflictDetector(getConflictDetectionStrategy()); assertEquals("Different number of conflicts is not allowed", detec.getConflicting(endOps1, endOps2).size(), detec.getConflicting(endOps2, endOps1).size()); Set<AbstractOperation> conflicting = detec.getConflicting(endOps1, endOps2); assertFalse("There has to be a conflict in conflicting-Set", conflicting.size() == 0); boolean neverConflicted = true; for (AbstractOperation op1 : endOps1) { for (AbstractOperation op2 : endOps2) { if (detec.doConflict(op1, op2)) { neverConflicted = false; } } } assertFalse("No conflict after Conflicttest - doConflict", neverConflicted); } }