| /******************************************************************************* |
| * Copyright (c) 2012-2013 EclipseSource Muenchen GmbH and others. |
| * |
| * 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: |
| ******************************************************************************/ |
| package org.eclipse.emf.emfstore.server.test; |
| |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.addElement; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.checkout; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.cloneProject; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.computeChecksum; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.revert; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.share; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.startRecording; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.stopRecording; |
| import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.update; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.util.List; |
| import java.util.concurrent.Callable; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.emf.emfstore.client.ESLocalProject; |
| import org.eclipse.emf.emfstore.client.ESWorkspaceProvider; |
| import org.eclipse.emf.emfstore.client.callbacks.ESCommitCallback; |
| import org.eclipse.emf.emfstore.client.callbacks.ESUpdateCallback; |
| import org.eclipse.emf.emfstore.client.test.common.cases.ESTestWithLoggedInUser; |
| 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.client.test.common.dsl.TestElementFeatures; |
| import org.eclipse.emf.emfstore.client.test.common.dsl.Update; |
| import org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil; |
| import org.eclipse.emf.emfstore.client.util.RunESCommand; |
| import org.eclipse.emf.emfstore.common.model.ESModelElementIdToEObjectMapping; |
| import org.eclipse.emf.emfstore.internal.client.model.Configuration; |
| import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl; |
| import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace; |
| import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl; |
| import org.eclipse.emf.emfstore.internal.client.model.util.ChecksumErrorHandler; |
| import org.eclipse.emf.emfstore.internal.common.model.ModelElementId; |
| import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil; |
| import org.eclipse.emf.emfstore.internal.common.model.util.SerializationException; |
| import org.eclipse.emf.emfstore.internal.server.model.impl.api.versionspec.ESPrimaryVersionSpecImpl; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CreateDeleteOperation; |
| import org.eclipse.emf.emfstore.server.ESConflictSet; |
| import org.eclipse.emf.emfstore.server.exceptions.ESException; |
| import org.eclipse.emf.emfstore.server.model.ESChangePackage; |
| import org.eclipse.emf.emfstore.server.model.versionspec.ESPrimaryVersionSpec; |
| import org.eclipse.emf.emfstore.test.model.TestElement; |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| public class ChecksumTest extends ESTestWithLoggedInUser { |
| |
| private static final String C = "C"; //$NON-NLS-1$ |
| private static final String SOME_COMMIT_MESSAGE = "SomeCommitMessage"; //$NON-NLS-1$ |
| private static final String BOOL = "BOOL"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE2 = "attribute"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_NAME = "attributeName"; //$NON-NLS-1$ |
| private static final String VALUE2 = "value"; //$NON-NLS-1$ |
| private static final String A = "A"; //$NON-NLS-1$ |
| |
| @Override |
| @Before |
| public void before() { |
| org.junit.Assume.assumeTrue(transactionalEditingDomainNotInUse()); |
| super.before(); |
| } |
| |
| public boolean transactionalEditingDomainNotInUse() { |
| return !ESWorkspaceProviderImpl.getInstance().getEditingDomain().getClass().getName().contains("Transactional"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| @After |
| public void after() { |
| super.after(); |
| } |
| |
| @BeforeClass |
| public static void beforeClass() { |
| startEMFStore(); |
| } |
| |
| @AfterClass |
| public static void afterClass() { |
| stopEMFStore(); |
| } |
| |
| @Test |
| public void testRevert() throws SerializationException { |
| |
| final TestElement table = Create.testElement(A); |
| final TestElement value = Create.testElement(VALUE2); |
| final TestElement attributeName = Create.testElement(ATTRIBUTE_NAME); |
| final TestElement attribute = Create.testElement(ATTRIBUTE2); |
| |
| Add.toProject(getLocalProject(), table); |
| Add.toProject(getLocalProject(), value); |
| Add.toProject(getLocalProject(), attributeName); |
| Add.toProject(getLocalProject(), attribute); |
| |
| attribute.getContainedElements().add(value); |
| table.getElementMap().put(attributeName, value); |
| |
| final long checksum = computeChecksum(getLocalProject()); |
| |
| clearOperations(); |
| |
| assertTrue(getProjectSpace().getLocalChangePackage().isEmpty()); |
| |
| final ProjectSpace clonedProjectSpace = cloneProjectSpace(getProjectSpace()); |
| final ModelElementId attributeId = getProject().getModelElementId(attribute); |
| |
| // Delete.fromProject(getLocalProject(), attribute); |
| ProjectUtil.removeModelElement(getLocalProject(), attribute); |
| |
| final List<AbstractOperation> forceGetOperations = forceGetOperations(); |
| final CreateDeleteOperation createDeleteOperation = (CreateDeleteOperation) forceGetOperations.get(0); |
| |
| assertEquals(attributeId, createDeleteOperation.getModelElementId()); |
| assertTrue(createDeleteOperation.isDelete()); |
| |
| revert(getLocalProject()); |
| |
| assertTrue(ModelUtil.areEqual(getProject(), clonedProjectSpace.getProject())); |
| final long checksumAfterRevert = computeChecksum(getLocalProject()); |
| |
| assertEquals(checksum, checksumAfterRevert); |
| } |
| |
| @Test |
| public void testOrderOfRootElementsInvariance() throws SerializationException { |
| |
| final TestElement a = Create.testElement(A); |
| final TestElement b = Create.testElement(BOOL); |
| |
| addElement(getLocalProject(), a); |
| addElement(getLocalProject(), b); |
| assertEquals(2, getLocalProject().getModelElements().size()); |
| |
| final long computeChecksum = computeChecksum(getLocalProject()); |
| |
| RunESCommand.run(new Callable<Void>() { |
| public Void call() throws Exception { |
| // we must clear and add again in one command |
| getLocalProject().getModelElements().clear(); |
| getLocalProject().getModelElements().add(b); |
| getLocalProject().getModelElements().add(a); |
| return null; |
| } |
| }); |
| |
| final long checksum = computeChecksum(getLocalProject()); |
| assertEquals(computeChecksum, checksum); |
| } |
| |
| @Test |
| public void testAutocorrectErrorHandlerAtCommit() throws ESException, SerializationException { |
| |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.AUTOCORRECT); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), addElement(getLocalProject(), testElement)); |
| |
| assertEquals(0, forceGetOperations().size()); |
| |
| Update.testElement(TestElementFeatures.name(), |
| testElement, A); |
| |
| final long expectedChecksum = computeChecksum(getLocalProject()); |
| final ESLocalProject clonedProject = cloneProject(getLocalProject()); |
| |
| stopRecording(getLocalProject()); |
| |
| Update.testElement(TestElementFeatures.name(), |
| testElement, BOOL); |
| |
| startRecording(getLocalProject()); |
| |
| // FIXME: ugly |
| assertEquals(1, |
| forceGetOperations().size()); |
| |
| // re-checkout should be triggered |
| final ESPrimaryVersionSpec commit = commitWithoutCommand(getLocalProject()); |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| final ESLocalProject restoredProject = ESWorkspaceProvider.INSTANCE.getWorkspace().getLocalProjects().get(0); |
| final long computedChecksum = computeChecksum(restoredProject); |
| |
| assertTrue(ModelUtil.areEqual( |
| ESLocalProjectImpl.class.cast(restoredProject).toInternalAPI().getProject(), |
| ESLocalProjectImpl.class.cast(clonedProject).toInternalAPI().getProject())); |
| assertEquals(expectedChecksum, |
| ESPrimaryVersionSpecImpl.class.cast(commit).toInternalAPI().getProjectStateChecksum()); |
| assertEquals(computedChecksum, |
| ESPrimaryVersionSpecImpl.class.cast(commit).toInternalAPI().getProjectStateChecksum()); |
| } |
| |
| @Test |
| public void testChangeTrackingAfterAutocorrectErrorHandler() throws ESException, SerializationException { |
| |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.AUTOCORRECT); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), getLocalProject()); |
| |
| final ESLocalProject checkout = checkout(getLocalProject()); |
| addElement(getLocalProject(), testElement); |
| Update.testElement(TestElementFeatures.name(), |
| testElement, A); |
| |
| commitWithoutCommand(getLocalProject()); |
| |
| assertEquals(0, forceGetOperations().size()); |
| |
| addElement(checkout, |
| Update.testElement(TestElementFeatures.name(), |
| Create.testElement(), BOOL)); |
| |
| update(checkout); |
| commitWithoutCommand(checkout); |
| |
| assertEquals(0, forceGetOperations(ESLocalProjectImpl.class.cast(checkout).toInternalAPI()).size()); |
| assertEquals(0, forceGetOperations().size()); |
| |
| Update.testElement(TestElementFeatures.name(), |
| testElement, BOOL); |
| |
| stopRecording(getLocalProject()); |
| Update.testElement(TestElementFeatures.name(), |
| testElement, C); |
| |
| startRecording(getLocalProject()); |
| |
| assertEquals(1, forceGetOperations().size()); |
| |
| // cancel should be triggered via exception |
| update(getLocalProject(), new MyUpdateCallback()); |
| |
| assertEquals(1, forceGetOperations().size()); |
| } |
| |
| @Test(expected = ESException.class) |
| public void testCancelErrorHandlerAtCommit() throws ESException, SerializationException { |
| |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.CANCEL); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), getLocalProject()); |
| |
| addElement(getLocalProject(), testElement); |
| Update.testElement(TestElementFeatures.name(), testElement, A); |
| |
| stopRecording(getLocalProject()); |
| Update.testElement(TestElementFeatures.name(), testElement, BOOL); |
| startRecording(getLocalProject()); |
| |
| // cancel should be triggered |
| commitWithoutCommand(getLocalProject()); |
| } |
| |
| @Test(expected = ESException.class) |
| public void testCancelErrorHandlerAtUpdateAfterOneCommit() throws ESException, SerializationException { |
| |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.CANCEL); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), getLocalProject()); |
| |
| final ESLocalProject checkout = checkout(getLocalProject()); |
| addElement(getLocalProject(), testElement); |
| Update.testElement(TestElementFeatures.name(), testElement, A); |
| |
| commitWithoutCommand(getLocalProject()); |
| |
| addElement(checkout, Create.testElement(BOOL)); |
| |
| update(checkout); |
| |
| commitWithoutCommand(checkout); |
| stopRecording(getLocalProject()); |
| Update.testElement(TestElementFeatures.name(), testElement, BOOL); |
| startRecording(getLocalProject()); |
| |
| // cancel should be triggered via exception |
| update(getLocalProject(), new MyUpdateCallback()); |
| } |
| |
| @Test |
| public void testCorrectChecksumsAtUpdate() throws ESException, SerializationException { |
| |
| assertEquals(1, |
| ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.CANCEL); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), getLocalProject()); |
| |
| final ESLocalProject checkout = checkout(getLocalProject(), getLocalProject().getBaseVersion()); |
| |
| addElement(getLocalProject(), testElement); |
| Update.testElement(TestElementFeatures.name(), testElement, A); |
| |
| commitWithoutCommand(getLocalProject()); |
| |
| addElement(checkout, Create.testElement()); |
| |
| update(checkout); |
| commitWithoutCommand(checkout); |
| |
| final ESPrimaryVersionSpec baseVersion = update(getLocalProject()).getBaseVersion(); |
| |
| assertTrue(ModelUtil.areEqual( |
| ESLocalProjectImpl.class.cast(getLocalProject()).toInternalAPI().getProject(), |
| ESLocalProjectImpl.class.cast(checkout).toInternalAPI().getProject())); |
| |
| assertEquals( |
| computeChecksum(getLocalProject()), |
| ESPrimaryVersionSpecImpl.class.cast(baseVersion).toInternalAPI().getProjectStateChecksum()); |
| } |
| |
| @Test |
| public void testCorruptChecksumsAtUpdateWithLocalOperation() throws ESException, SerializationException { |
| |
| assertEquals(1, ESWorkspaceProviderImpl.getInstance().getWorkspace().getLocalProjects().size()); |
| |
| Configuration.getClientBehavior().setChecksumErrorHandler(ChecksumErrorHandler.AUTOCORRECT); |
| |
| final TestElement testElement = Create.testElement(); |
| share(getUsersession(), getLocalProject()); |
| |
| final ESLocalProject checkout = checkout(getLocalProject()); |
| addElement(getLocalProject(), testElement); |
| |
| Update.testElement(TestElementFeatures.name(), testElement, A); |
| |
| commitWithoutCommand(getLocalProject()); |
| addElement(checkout, Create.testElement()); |
| |
| update(checkout); |
| commitWithoutCommand(checkout); |
| |
| Update.testElement(TestElementFeatures.name(), testElement, BOOL); |
| |
| stopRecording(getLocalProject()); |
| Update.testElement(TestElementFeatures.name(), testElement, C); |
| startRecording(getLocalProject()); |
| |
| assertEquals(1, forceGetOperations().size()); |
| |
| // autocorrect should be triggered, will fail |
| update(getLocalProject()); |
| assertEquals(1, forceGetOperations().size()); |
| } |
| |
| private class MyCommitCallback implements ESCommitCallback { |
| |
| public boolean baseVersionOutOfDate(ESLocalProject projectSpace, IProgressMonitor progressMonitor) { |
| return ESCommitCallback.NOCALLBACK.baseVersionOutOfDate(projectSpace, progressMonitor); |
| } |
| |
| public boolean inspectChanges(ESLocalProject projectSpace, ESChangePackage changePackage, |
| ESModelElementIdToEObjectMapping idToEObjectMapping) { |
| return ESCommitCallback.NOCALLBACK.inspectChanges(projectSpace, changePackage, idToEObjectMapping); |
| } |
| |
| public void noLocalChanges(ESLocalProject projectSpace) { |
| ESCommitCallback.NOCALLBACK.noLocalChanges(projectSpace); |
| } |
| |
| } |
| |
| private class MyUpdateCallback implements ESUpdateCallback { |
| |
| public boolean inspectChanges(ESLocalProject projectSpace, List<ESChangePackage> changes, |
| ESModelElementIdToEObjectMapping idToEObjectMapping) { |
| return ESUpdateCallback.NOCALLBACK.inspectChanges(projectSpace, changes, idToEObjectMapping); |
| } |
| |
| public void noChangesOnServer() { |
| ESUpdateCallback.NOCALLBACK.noChangesOnServer(); |
| } |
| |
| public boolean conflictOccurred(ESConflictSet changeConflictException, |
| IProgressMonitor progressMonitor) { |
| return ESUpdateCallback.NOCALLBACK.conflictOccurred(changeConflictException, progressMonitor); |
| } |
| |
| } |
| |
| protected ESPrimaryVersionSpec commitWithoutCommand(final ESLocalProject project) throws ESException { |
| return project.commit(SOME_COMMIT_MESSAGE, new MyCommitCallback(), |
| new NullProgressMonitor()); |
| } |
| |
| } |