blob: a1155a05be72c6c15c619acdf8c399ed4a91414c [file] [log] [blame]
/*
* Copyright (c) 2007-2013, 2016, 2019, 2020 Eike Stepper (Loehne, Germany) 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:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.model.CDOPackageTypeRegistry;
import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.net4j.CDONet4jUtil;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.session.CDORepositoryInfo;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalSession;
import org.eclipse.emf.cdo.spi.server.InternalTransaction;
import org.eclipse.emf.cdo.spi.server.InternalView;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUpdatable;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.object.CDOLegacyWrapper;
import org.eclipse.net4j.util.ReflectUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.ThrowableEvent;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.tests.AbstractOMTest;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl;
import org.eclipse.emf.spi.cdo.FSMUtil;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author Eike Stepper
*/
public abstract class AbstractCDOTest extends ConfigTest
{
static
{
// Make sure that the Net4j resource factories are registered before registrations become impossible.
CDONet4jUtil.createNet4jSessionConfiguration();
makeUnmodifiable("protocolToFactoryMap");
makeUnmodifiable("extensionToFactoryMap");
makeUnmodifiable("contentTypeIdentifierToFactoryMap");
}
private static void makeUnmodifiable(String fieldName)
{
Field field = ReflectUtil.getField(ResourceFactoryRegistryImpl.class, fieldName);
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>)ReflectUtil.getValue(field, Resource.Factory.Registry.INSTANCE);
ReflectUtil.setValue(field, Resource.Factory.Registry.INSTANCE, Collections.unmodifiableMap(map));
}
@Override
protected void doSetUp() throws Exception
{
try
{
super.doSetUp();
}
finally
{
org.eclipse.emf.cdo.internal.net4j.bundle.OM.PREF_COMMIT_MONITOR_PROGRESS_SECONDS.setValue(60);
org.eclipse.emf.cdo.internal.net4j.bundle.OM.PREF_COMMIT_MONITOR_TIMEOUT_SECONDS.setValue(60 * 60);
CDOPackageTypeRegistry.INSTANCE.reset();
startTransport();
}
}
@Override
protected void doTearDown() throws Exception
{
// This override adds no functionality.
// It just ensures that the IDE shows doSetUp() and doTearDown() in the same class.
super.doTearDown();
}
/**
* Closes the given session and waits until the server-side session is closed, too.
* In TCP scenarios the latter does not happen synchronously, which can confuse tests that count sessions.
*/
public void closeSession(CDOSession session) throws InterruptedException
{
final int sessionID = session.getSessionID();
session.close();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return getRepository().getSessionManager().getSession(sessionID) == null;
}
}.assertNoTimeOut();
}
public InternalSession serverSession(CDOSession session)
{
String repositoryName = session.getRepositoryInfo().getName();
InternalRepository repository = getRepository(repositoryName);
return repository.getSessionManager().getSession(session.getSessionID());
}
public InternalView serverView(CDOView view)
{
InternalSession serverSession = serverSession(view.getSession());
return serverSession.getView(view.getViewID());
}
public InternalTransaction serverTransaction(CDOTransaction transaction)
{
return (InternalTransaction)serverView(transaction);
}
public CDOBranch serverBranch(CDOBranch branch)
{
CDORepositoryInfo repositoryInfo = (CDORepositoryInfo)branch.getBranchManager().getRepository();
InternalRepository repository = getRepository(repositoryInfo.getName());
return repository.getBranchManager().getBranch(branch.getID());
}
public LockState<Object, IView> serverLockState(CDOSession session, CDOLockState lockState)
{
Object serverLockTarget = serverLockTarget(lockState.getLockedObject());
InternalSession serverSession = serverSession(session);
InternalLockManager lockingManager = serverSession.getRepository().getLockingManager();
return lockingManager.getLockState(serverLockTarget);
}
public Object serverLockTarget(Object lockTarget)
{
if (lockTarget instanceof CDOIDAndBranch)
{
CDOIDAndBranch idAndBranch = (CDOIDAndBranch)lockTarget;
CDOBranch serverBranch = serverBranch(idAndBranch.getBranch());
return CDOIDUtil.createIDAndBranch(idAndBranch.getID(), serverBranch);
}
return lockTarget;
}
public static void assertEquals(Object expected, Object actual)
{
if (expected instanceof CDOID || expected instanceof CDOBranch)
{
if (expected != actual)
{
failNotEquals(null, expected, actual);
}
return;
}
// IMPORTANT: Give possible CDOLegacyWrapper a chance for actual, too
if (actual != null && actual.equals(expected))
{
return;
}
AbstractOMTest.assertEquals(expected, actual);
}
protected static void assertTransient(EObject eObject)
{
CDOObject object = CDOUtil.getCDOObject(eObject);
if (object != null)
{
assertEquals(true, FSMUtil.isTransient(object));
assertNull(object.cdoID());
assertNull(object.cdoRevision());
assertNull(object.cdoView());
}
}
protected static void assertInvalid(EObject eObject)
{
CDOObject object = CDOUtil.getCDOObject(eObject);
if (object != null)
{
assertEquals(true, FSMUtil.isInvalid(object));
}
}
protected static void assertNotTransient(EObject eObject, CDOView view)
{
CDOObject object = FSMUtil.adapt(eObject, view);
assertEquals(false, FSMUtil.isTransient(object));
assertNotNull(object.cdoID());
assertNotNull(object.cdoRevision());
assertNotNull(object.cdoView());
assertNotNull(object.eResource());
assertEquals(view, object.cdoView());
assertEquals(object, view.getObject(object.cdoID(), false));
}
protected static void assertNew(EObject eObject, CDOView view)
{
CDOObject object = FSMUtil.adapt(eObject, view);
assertNotTransient(object, view);
assertEquals(CDOState.NEW, object.cdoState());
}
protected static void assertDirty(EObject eObject, CDOView view)
{
CDOObject object = FSMUtil.adapt(eObject, view);
assertNotTransient(object, view);
assertEquals(CDOState.DIRTY, object.cdoState());
}
protected static void assertClean(EObject eObject, CDOView view)
{
CDOObject object = FSMUtil.adapt(eObject, view);
assertNotTransient(object, view);
assertEquals(CDOState.CLEAN, object.cdoState());
}
protected static void assertProxy(EObject eObject)
{
CDOObject object = CDOUtil.getCDOObject(eObject);
if (object != null)
{
assertEquals(false, FSMUtil.isTransient(object));
assertNotNull(object.cdoID());
assertNotNull(object.cdoView());
assertEquals(CDOState.PROXY, object.cdoState());
}
}
protected static void assertContent(EObject eContainer, EObject eContained)
{
CDOObject container = CDOUtil.getCDOObject(eContainer);
CDOObject contained = CDOUtil.getCDOObject(eContained);
if (container != null && contained != null)
{
assertEquals(true, container.eContents().contains(contained));
if (container instanceof CDOResource)
{
assertEquals(container, contained.eResource());
assertEquals(null, contained.eContainer());
assertEquals(true, ((CDOResource)container).getContents().contains(contained));
}
else
{
assertEquals(container.eResource(), contained.eResource());
assertEquals(container, contained.eContainer());
}
}
}
protected static void assertNotProxy(Object object)
{
assertEquals(false, CDOLegacyWrapper.isLegacyProxy(object));
}
protected static void assertCreatedTime(EObject eObject, long timeStamp)
{
CDOObject object = CDOUtil.getCDOObject(eObject);
if (object != null)
{
assertEquals(timeStamp, object.cdoRevision().getTimeStamp());
}
}
protected static void dumpAllRevisions(Object allRevisionsProvider)
{
try
{
String label = allRevisionsProvider.toString();
IOUtil.OUT().println(label);
for (int i = 0; i < label.length(); i++)
{
IOUtil.OUT().print("=");
}
IOUtil.OUT().println();
if (allRevisionsProvider instanceof CDOAllRevisionsProvider)
{
CDOAllRevisionsProvider provider = (CDOAllRevisionsProvider)allRevisionsProvider;
Map<CDOBranch, List<CDORevision>> map = provider.getAllRevisions();
IOUtil.OUT().println(CDORevisionUtil.dumpAllRevisions(map));
}
}
catch (Exception ex)
{
IOUtil.print(ex);
}
}
protected static void dumpAllContents(Notifier root)
{
try
{
StringBuilder builder = new StringBuilder();
dumpAllContents(root, "", builder);
IOUtil.OUT().println(builder);
}
catch (Exception ex)
{
IOUtil.print(ex);
}
}
private static void dumpAllContents(Notifier object, String indent, StringBuilder builder)
{
builder.append(indent);
if (object instanceof ResourceSet)
{
ResourceSet resourceSet = (ResourceSet)object;
builder.append("ResourceSet");
builder.append(StringUtil.NL);
for (Resource resource : resourceSet.getResources())
{
dumpAllContents(resource, indent + " ", builder);
}
}
else if (object instanceof Resource)
{
Resource resource = (Resource)object;
if (object instanceof CDOResource)
{
builder.append("CDOResource[uri=" + ((CDOResource)resource).getName() + "]");
}
else
{
builder.append("Resource[uri=" + resource.getURI() + "]");
}
builder.append(StringUtil.NL);
for (EObject child : resource.getContents())
{
dumpAllContents(child, indent + " ", builder);
}
}
else
{
EObject eObject = (EObject)object;
CDOObject cdoObject = CDOUtil.getCDOObject(eObject);
builder.append(cdoObject.toString());
boolean added = false;
for (EStructuralFeature feature : cdoObject.eClass().getEAllStructuralFeatures())
{
if (feature instanceof EReference)
{
EReference reference = (EReference)feature;
if (reference.isContainment() || reference.isContainer())
{
continue;
}
}
if (cdoObject.eIsSet(feature))
{
if (added)
{
builder.append(", ");
}
else
{
builder.append("[");
}
added = true;
Object value = cdoObject.eGet(feature);
builder.append(feature.getName() + "=" + value);
}
}
if (added)
{
builder.append("]");
}
builder.append(StringUtil.NL);
for (TreeIterator<EObject> it = cdoObject.eAllContents(); it.hasNext();)
{
EObject child = it.next();
dumpAllContents(child, indent + " ", builder);
}
}
}
protected static CDOCommitInfo commitAndSync(CDOTransaction transaction, CDOUpdatable... updatables) throws CommitException
{
return commitAndSync(transaction, null, updatables);
}
protected static CDOCommitInfo commitAndSync(CDOTransaction transaction, String comment, CDOUpdatable... updatables) throws CommitException
{
final RuntimeException[] exception = { null };
IListener listener = new IListener()
{
@Override
public void notifyEvent(IEvent event)
{
if (exception[0] == null && event instanceof ThrowableEvent)
{
ThrowableEvent e = (ThrowableEvent)event;
exception[0] = new RuntimeException(e.getThrowable());
}
}
};
for (CDOUpdatable updatable : updatables)
{
if (updatable instanceof CDOView)
{
CDOView view = (CDOView)updatable;
view.addListener(listener);
}
}
try
{
if (comment != null)
{
transaction.setCommitComment(comment);
}
CDOCommitInfo info = transaction.commit();
if (info != null)
{
for (CDOUpdatable updatable : updatables)
{
if (!updatable.waitForUpdate(info.getTimeStamp(), DEFAULT_TIMEOUT))
{
if (exception[0] == null)
{
exception[0] = new TimeoutRuntimeException(updatable.toString() + " did not receive an update of " + info);
}
break;
}
}
}
if (exception[0] != null)
{
throw exception[0];
}
return info;
}
finally
{
for (CDOUpdatable updatable : updatables)
{
if (updatable instanceof CDOView)
{
CDOView view = (CDOView)updatable;
view.removeListener(listener);
}
}
}
}
}