/******************************************************************************* | |
* 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.getOperationSize; | |
import static org.eclipse.emf.emfstore.client.test.common.util.ProjectUtil.removeModelElement; | |
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.Delete; | |
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.util.ESVoidCallable; | |
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.impl.api.ESLocalProjectImpl; | |
import org.eclipse.emf.emfstore.internal.client.model.util.ChecksumErrorHandler; | |
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.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); | |
Add.toContainedElements(getLocalProject(), attribute, value); | |
getLocalProject().run(new ESVoidCallable() { | |
@Override | |
public void run() { | |
table.getElementMap().put(attributeName, value); | |
} | |
}); | |
final long checksum = computeChecksum(getLocalProject()); | |
clearOperations(); | |
Delete.fromProject(getLocalProject(), attribute); | |
removeModelElement(getLocalProject(), attribute); | |
revert(getLocalProject()); | |
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; | |
} | |
}, getProjectSpace().getContentEditingDomain()); | |
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)); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), | |
testElement, A); | |
final long expectedChecksum = computeChecksum(getLocalProject()); | |
final ESLocalProject clonedProject = cloneProject(getLocalProject()); | |
stopRecording(getLocalProject()); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), | |
testElement, BOOL); | |
startRecording(getLocalProject()); | |
// FIXME: ugly | |
assertEquals(1, | |
((ESLocalProjectImpl) getLocalProject()).toInternalAPI().getOperations().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(getLocalProject(), TestElementFeatures.name(), | |
testElement, A); | |
commitWithoutCommand(getLocalProject()); | |
assertEquals(0, getOperationSize(getLocalProject())); | |
addElement(checkout, | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), | |
Create.testElement(), BOOL)); | |
update(checkout); | |
commitWithoutCommand(checkout); | |
assertEquals(0, getOperationSize(checkout)); | |
assertEquals(0, getOperationSize(getLocalProject())); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), | |
testElement, BOOL); | |
stopRecording(getLocalProject()); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), | |
testElement, C); | |
startRecording(getLocalProject()); | |
assertEquals(1, getOperationSize(getLocalProject())); | |
// cancel should be triggered via exception | |
update(getLocalProject(), new MyUpdateCallback()); | |
assertEquals(1, getOperationSize(getLocalProject())); | |
} | |
@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(getLocalProject(), TestElementFeatures.name(), testElement, A); | |
stopRecording(getLocalProject()); | |
Update.testElement(getLocalProject(), 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(getLocalProject(), TestElementFeatures.name(), testElement, A); | |
commitWithoutCommand(getLocalProject()); | |
addElement(checkout, Create.testElement(BOOL)); | |
update(checkout); | |
commitWithoutCommand(checkout); | |
stopRecording(getLocalProject()); | |
Update.testElement(getLocalProject(), 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(getLocalProject(), 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(getLocalProject(), TestElementFeatures.name(), testElement, A); | |
commitWithoutCommand(getLocalProject()); | |
addElement(checkout, Create.testElement()); | |
update(checkout); | |
commitWithoutCommand(checkout); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), testElement, BOOL); | |
stopRecording(getLocalProject()); | |
Update.testElement(getLocalProject(), TestElementFeatures.name(), testElement, C); | |
startRecording(getLocalProject()); | |
assertEquals(1, getOperationSize(getLocalProject())); | |
// autocorrect should be triggered, will fail | |
update(getLocalProject()); | |
assertEquals(1, getOperationSize(getLocalProject())); | |
} | |
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()); | |
} | |
} |