| /******************************************************************************* |
| * 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: |
| * chodnick |
| ******************************************************************************/ |
| package org.eclipse.emf.emfstore.client.conflictdetection.test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.util.List; |
| |
| import org.eclipse.emf.emfstore.client.test.common.dsl.Add; |
| import org.eclipse.emf.emfstore.client.test.common.dsl.Create; |
| import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace; |
| 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.ConflictBucket; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation; |
| import org.eclipse.emf.emfstore.test.model.TestElement; |
| import org.junit.Test; |
| |
| /** |
| * Tests conflict detection behaviour on attributes. |
| * |
| * @author chodnick |
| */ |
| public class ConflictDetectionDeleteTest extends ConflictDetectionTest { |
| |
| private static final String CHANGE_TO_UNRELATED_OBJECT_ON_ANOTHER_WORKING_COPY = "change to unrelated object on another working copy"; //$NON-NLS-1$ |
| private static final String CHANGE_TO_OBJECT_INSIDE_DELTREE_ON_ANOTHER_WORKING_COPY = "change to object inside deltree on another working copy"; //$NON-NLS-1$ |
| private static final String CHANGE_TO_THE_DELETED_OBJECT_ON_ANOTHER_WORKING_COPY = "change to the deleted object on another working copy"; //$NON-NLS-1$ |
| private static final String OLD_NAME = "old name"; //$NON-NLS-1$ |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDelete() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement actor = Create.testElement(); |
| actor.setName(OLD_NAME); |
| |
| Add.toProject(getLocalProject(), section); |
| Add.toContainedElements(section, actor); |
| clearOperations(); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId actorId = getProject().getModelElementId(actor); |
| |
| final TestElement actor1 = (TestElement) getProject().getModelElement(actorId); |
| final TestElement actor2 = (TestElement) project2.getModelElement(actorId); |
| |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().deleteModelElement(actor1); |
| actor2.setName(CHANGE_TO_THE_DELETED_OBJECT_ON_ANOTHER_WORKING_COPY); |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| |
| final ConflictBucket bucket = conflicts.get(0); |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| |
| assertEquals(conflicts.size(), 1); |
| |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDeleteAttributeChangesInDeltree() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement actor = Create.testElement(); |
| actor.setName(OLD_NAME); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| section.getContainedElements().add(actor); |
| clearOperations(); |
| |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId section1Id = getProject().getModelElementId(section); |
| final ModelElementId actorId = getProject().getModelElementId(actor); |
| |
| final TestElement section1 = (TestElement) getProject().getModelElement(section1Id); |
| final TestElement actor2 = (TestElement) project2.getModelElement(actorId); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().deleteModelElement(section1); |
| actor2.setName(CHANGE_TO_OBJECT_INSIDE_DELTREE_ON_ANOTHER_WORKING_COPY); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| final ConflictBucket bucket = conflicts.get(0); |
| |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| assertEquals(conflicts.size(), 1); |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDeleteAttributeChangesInDelObject() { |
| |
| final TestElement section = Create.testElement(); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| clearOperations(); |
| |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId sectionId = getProject().getModelElementId(section); |
| |
| final TestElement section1 = (TestElement) getProject().getModelElement(sectionId); |
| final TestElement section2 = (TestElement) project2.getModelElement(sectionId); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().deleteModelElement(section1); |
| section2.setName(CHANGE_TO_OBJECT_INSIDE_DELTREE_ON_ANOTHER_WORKING_COPY); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| final ConflictBucket bucket = conflicts.get(0); |
| |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| assertEquals(conflicts.size(), 1); |
| |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void noConflictDeleteUnrelated() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement actor = Create.testElement(); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| getProject().addModelElement(actor); |
| clearOperations(); |
| |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project clonedProject = ps2.getProject(); |
| |
| final ModelElementId actorId = getProject().getModelElementId(actor); |
| final ModelElementId sectionId = getProject().getModelElementId(section); |
| |
| final TestElement actor1 = (TestElement) getProject().getModelElement(actorId); |
| final TestElement clonedSection = (TestElement) clonedProject.getModelElement(sectionId); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| actor1.setName(CHANGE_TO_UNRELATED_OBJECT_ON_ANOTHER_WORKING_COPY); |
| clonedProject.deleteModelElement(clonedSection); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| assertTrue(conflicts.isEmpty()); |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDeleteContainmentChangesInDeltree() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement pack = Create.testElement(); |
| final TestElement br = Create.testElement(); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| getProject().addModelElement(pack); |
| getProject().addModelElement(br); |
| section.getContainedElements().add(pack); |
| clearOperations(); |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId brId = getProject().getModelElementId(br); |
| final ModelElementId packId = getProject().getModelElementId(pack); |
| final ModelElementId sectionId = getProject().getModelElementId(section); |
| |
| final TestElement br1 = (TestElement) getProject().getModelElement(brId); |
| final TestElement pack1 = (TestElement) getProject().getModelElement(packId); |
| final TestElement section2 = (TestElement) project2.getModelElement(sectionId); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| br1.setContainer(pack1); |
| project2.deleteModelElement(section2); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| final ConflictBucket bucket = conflicts.get(0); |
| |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| assertEquals(conflicts.size(), 1); |
| |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDeleteNonContainmentChangesInDeltree() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement useCase = Create.testElement(); |
| final TestElement mileStone = Create.testElement(); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| getProject().addModelElement(useCase); |
| getProject().addModelElement(mileStone); |
| section.getContainedElements().add(useCase); |
| clearOperations(); |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId mileStoneId = getProject().getModelElementId(mileStone); |
| final ModelElementId useCaseId = getProject().getModelElementId(useCase); |
| final ModelElementId sectionId = getProject().getModelElementId(section); |
| |
| final TestElement mileStone1 = (TestElement) getProject().getModelElement(mileStoneId); |
| final TestElement useCase1 = (TestElement) getProject().getModelElement(useCaseId); |
| final TestElement section2 = (TestElement) project2.getModelElement(sectionId); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| useCase1.getContainedElements().add(mileStone1); |
| project2.deleteModelElement(section2); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| // technically no conflict, since annotated milestone will not be deleted, |
| // but there is no way to tell containment from non-containment changes, |
| // therefore it is expected that this will be detected as a hard conflict |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| assertEquals(conflicts.size(), 1); |
| final ConflictBucket bucket = conflicts.get(0); |
| |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| assertEquals(conflicts.size(), 1); |
| } |
| |
| /** |
| * Tests if deleting an object is detected as conflict. |
| */ |
| @Test |
| public void conflictDeleteMoveChangesInDeltree() { |
| |
| final TestElement section = Create.testElement(); |
| final TestElement pack = Create.testElement(); |
| final TestElement br1 = Create.testElement(); |
| final TestElement br2 = Create.testElement(); |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(section); |
| getProject().addModelElement(pack); |
| getProject().addModelElement(br1); |
| |
| br1.setContainer(pack); |
| br2.setContainer(pack); |
| |
| } |
| }.run(false); |
| |
| assertEquals(pack.getContainedElements().get(0), br1); |
| assertEquals(pack.getContainedElements().get(1), br2); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| section.getContainedElements().add(pack); |
| clearOperations(); |
| } |
| }.run(false); |
| |
| final ProjectSpace ps2 = cloneProjectSpace(getProjectSpace()); |
| final Project project2 = ps2.getProject(); |
| |
| final ModelElementId packId = getProject().getModelElementId(pack); |
| final ModelElementId sectionId = getProject().getModelElementId(section); |
| |
| final TestElement pack1 = (TestElement) getProject().getModelElement(packId); |
| final TestElement section2 = (TestElement) project2.getModelElement(sectionId); |
| |
| new EMFStoreCommand() { |
| |
| @Override |
| protected void doRun() { |
| pack1.getContainedElements().move(1, 0); |
| project2.deleteModelElement(section2); |
| |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> ops1 = forceGetOperations(); |
| final List<AbstractOperation> ops2 = forceGetOperations(ps2); |
| |
| // a move change is a change... from users perspective it should not be lost, probably.. |
| // currently considered to be a hard conflict, because the user should know |
| final List<ConflictBucket> conflicts = getConflicts(ops1, ops2); |
| assertEquals(conflicts.size(), 1); |
| final ConflictBucket bucket = conflicts.get(0); |
| |
| assertEquals(1, bucket.getMyOperations().size()); |
| assertEquals(1, bucket.getTheirOperations().size()); |
| assertEquals(conflicts.size(), 1); |
| |
| } |
| } |