| /** |
| * <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.changeTracking.canonization; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.List; |
| |
| import org.eclipse.emf.emfstore.client.model.CompositeOperationHandle; |
| import org.eclipse.emf.emfstore.client.model.exceptions.InvalidHandleException; |
| import org.eclipse.emf.emfstore.client.model.util.EMFStoreCommand; |
| import org.eclipse.emf.emfstore.client.test.WorkspaceTest; |
| import org.eclipse.emf.emfstore.common.model.Project; |
| import org.eclipse.emf.emfstore.common.model.util.ModelUtil; |
| 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.util.OperationsCanonizer; |
| import org.junit.Test; |
| |
| /** |
| * Tests canonization of composite operations. |
| * |
| * @author chodnick |
| */ |
| public class CompositeTest extends WorkspaceTest { |
| |
| /** |
| * Tests canonization of empty composite operations. |
| * |
| * @throws InvalidHandleException if an error occurrs |
| */ |
| @Test |
| public void emptyComposite() throws InvalidHandleException { |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| // create an empty composite, should be canonized out |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| try { |
| handle.end("sectionCreation", "description", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| |
| assertEquals(operations.size(), 1); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| |
| assertEquals(operations.size(), 0); |
| |
| } |
| |
| /** |
| * Tests canonization for consecutive attribute changes, resulting in a noop. |
| * |
| * @throws InvalidHandleException if error occurs |
| */ |
| @Test |
| public void noOpComposite() throws InvalidHandleException { |
| |
| final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(useCase); |
| useCase.setName("oldName"); |
| } |
| }.run(false); |
| |
| final Project expectedProject = ModelUtil.clone(getProject()); |
| assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| clearOperations(); |
| |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| |
| useCase.setName("A"); |
| useCase.setName("B"); |
| useCase.setName("C"); |
| useCase.setName("oldName"); |
| |
| assertEquals("oldName", useCase.getName()); |
| |
| assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); |
| |
| try { |
| handle.end("blubb", "blibb", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| assertEquals(operations.size(), 1); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| |
| // should not have left any operations, we were just resetting the name to its original value |
| assertEquals(operations.size(), 0); |
| |
| } |
| |
| /** |
| * Tests canonization for consecutive attribute changes, resulting in a noop. |
| * |
| * @throws InvalidHandleException if error occurs |
| */ |
| @Test |
| public void multiFeatureNoOpComposite() throws InvalidHandleException { |
| |
| final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(useCase); |
| useCase.setName("oldName"); |
| useCase.setDescription("oldDescription"); |
| } |
| }.run(false); |
| |
| final Project expectedProject = ModelUtil.clone(getProject()); |
| assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| clearOperations(); |
| |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| |
| useCase.setName("A"); |
| useCase.setDescription("X"); |
| useCase.setName("B"); |
| useCase.setDescription("Y"); |
| useCase.setName("C"); |
| |
| useCase.setDescription("oldDescription"); |
| useCase.setName("oldName"); |
| |
| assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); |
| |
| try { |
| handle.end("blubb", "blibb", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| assertEquals(operations.size(), 1); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| |
| // should not have left any operations, we were just resetting the name to its original value |
| assertEquals(operations.size(), 0); |
| |
| } |
| |
| /** |
| * Tests canonization for composite ops, where main operation might be canonized away. |
| * |
| * @throws InvalidHandleException if error occurs |
| */ |
| @Test |
| public void mainDeleteCompositeImplicitRestore() throws InvalidHandleException { |
| |
| final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(useCase); |
| useCase.setName("oldName"); |
| clearOperations(); |
| |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| |
| useCase.setName("A"); |
| useCase.setName("B"); |
| useCase.setName("newName"); |
| |
| try { |
| handle.end("blubb", "blibb", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| assertEquals(operations.size(), 1); |
| final CompositeOperation comp = (CompositeOperation) operations.get(0); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| comp.setMainOperation(comp.getSubOperations().get(1)); // setName to from "A" to "B" |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| |
| // the main one was a candidate for removal, but since it is the main one, it may not be touched |
| // in this case it will not even be modified |
| assertTrue(comp.getSubOperations().contains(comp.getMainOperation())); |
| } |
| |
| /** |
| * Tests canonization for composite ops, where main operation might be canonized away. |
| * |
| * @throws InvalidHandleException if error occurs |
| */ |
| @Test |
| public void mainDeleteCompositeImplicitMainOpModification() throws InvalidHandleException { |
| |
| final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(useCase); |
| useCase.setName("oldName"); |
| |
| clearOperations(); |
| |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| |
| useCase.setName("A"); |
| useCase.setName("B"); |
| useCase.setName("newName"); |
| |
| try { |
| handle.end("blubb", "blibb", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| assertEquals(operations.size(), 1); |
| final CompositeOperation comp = (CompositeOperation) operations.get(0); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| comp.setMainOperation(comp.getSubOperations().get(0)); // setName to from "oldName" to "A" |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| |
| // the main one was a candidate for removal, but since it is the main one, it may not be removed |
| // it might have been altered though (newValue, oldValue etc., might have changed in the canonization |
| // process) |
| assertTrue(comp.getSubOperations().contains(comp.getMainOperation())); |
| } |
| |
| /** |
| * Tests canonization for composite ops, where main operation might be canonized away. |
| * |
| * @throws InvalidHandleException if error occurs |
| */ |
| @Test |
| public void mainDeleteNoOpComposite() throws InvalidHandleException { |
| |
| final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); |
| |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| getProject().addModelElement(useCase); |
| useCase.setName("oldName"); |
| |
| clearOperations(); |
| |
| CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation(); |
| |
| useCase.setName("A"); |
| useCase.setName("B"); |
| useCase.setName("oldName"); |
| |
| try { |
| handle.end("blubb", "blibb", null); |
| } catch (InvalidHandleException e) { |
| fail(); |
| } |
| } |
| }.run(false); |
| |
| final List<AbstractOperation> operations = getProjectSpace().getOperations(); |
| assertEquals(operations.size(), 1); |
| final CompositeOperation comp = (CompositeOperation) operations.get(0); |
| new EMFStoreCommand() { |
| @Override |
| protected void doRun() { |
| comp.setMainOperation(comp.getSubOperations().get(1)); // setName to from "A" to "B" |
| OperationsCanonizer.canonize(operations); |
| } |
| }.run(false); |
| // since this composite is a noop, everything should have been removed |
| assertEquals(comp.getSubOperations().size(), 0); |
| } |
| |
| } |