blob: f155344bc3533cfaa2aa961c7004292a82b28019 [file] [log] [blame]
/*
* Copyright (c) 2007-2012, 2015 Eike Stepper (Berlin, 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
* Simon McDuff - maintenance
*/
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent;
import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
import org.eclipse.emf.cdo.tests.model1.Category;
import org.eclipse.emf.cdo.tests.model1.Company;
import org.eclipse.emf.cdo.tests.model1.Customer;
import org.eclipse.emf.cdo.tests.util.TestAdapter;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.InvalidObjectException;
import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.session.CDOSessionImpl;
import org.eclipse.emf.internal.cdo.view.CDOViewImpl;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.ReflectUtil;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.spi.cdo.FSMUtil;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* @author Eike Stepper
*/
public class InvalidationTest extends AbstractCDOTest
{
public void _testIvalidationMemoryLeak() throws Exception
{
final CDOSession session = openSession();
/**
* @author Eike Stepper
*/
class MyTransTest implements Runnable
{
private int nr;
public MyTransTest(int nr)
{
this.nr = nr;
}
public void run()
{
for (int i = 0; i < 10; i++)
{
Category category = getModel1Factory().createCategory();
category.setName("Category " + System.currentTimeMillis());
CDOTransaction transaction = session.openTransaction();
try
{
CDOResource resource = transaction.getOrCreateResource(getResourcePath("/test1_" + nr));
resource.getContents().add(category);
transaction.commit();
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
transaction.close();
}
}
}
}
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 20; i++)
{
threads.add(new Thread(new MyTransTest(i + 1)));
}
for (Thread thread : threads)
{
thread.start();
}
for (Thread thread : threads)
{
thread.join();
}
// session.refresh();
// sleep(2000);
new MyTransTest(0).run();
sleep(60000);
// session.refresh();
Field field = ReflectUtil.getField(CDOSessionImpl.class, "outOfSequenceInvalidations");
Map<?, ?> outOfSequenceInvalidations = (Map<?, ?>)ReflectUtil.getValue(field, session);
int size = outOfSequenceInvalidations.size();
assertEquals(0, size);
}
public void testSeparateView() throws Exception
{
final CDOSession session = openSession();
// ************************************************************* //
final Category category1A = getModel1Factory().createCategory();
category1A.setName("category1");
final Category category2A = getModel1Factory().createCategory();
category2A.setName("category2");
final Category category3A = getModel1Factory().createCategory();
category3A.setName("category3");
final Company companyA = getModel1Factory().createCompany();
companyA.getCategories().add(category1A);
category1A.getCategories().add(category2A);
category2A.getCategories().add(category3A);
final CDOTransaction transaction = session.openTransaction();
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(companyA);
transaction.commit();
// ************************************************************* //
final CDOView view = session.openTransaction();
final CDOResource resourceB = view.getResource(getResourcePath("/test1"));
assertProxy(resourceB);
EList<EObject> contents = resourceB.getContents();
final Company companyB = (Company)contents.get(0);
assertClean(companyB, view);
assertClean(resourceB, view);
assertContent(resourceB, companyB);
final Category category1B = companyB.getCategories().get(0);
assertClean(category1B, view);
assertClean(companyB, view);
assertContent(companyB, category1B);
final Category category2B = category1B.getCategories().get(0);
assertClean(category2B, view);
assertClean(category1B, view);
assertContent(category1B, category2B);
final Category category3B = category2B.getCategories().get(0);
assertClean(category3B, view);
assertClean(category2B, view);
assertContent(category2B, category3B);
assertClean(category3B, view);
// ************************************************************* //
category1A.setName("CHANGED NAME");
assertEquals("category1", category1B.getName());
transaction.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
String name = category1B.getName();
return "CHANGED NAME".equals(name);
}
}.assertNoTimeOut();
}
public void testSeparateViewNotification() throws Exception
{
final CDOSession session = openSession();
// ************************************************************* //
final Category category1A = getModel1Factory().createCategory();
category1A.setName("category1");
final Category category2A = getModel1Factory().createCategory();
category2A.setName("category2");
final Category category3A = getModel1Factory().createCategory();
category3A.setName("category3");
final Company companyA = getModel1Factory().createCompany();
companyA.getCategories().add(category1A);
category1A.getCategories().add(category2A);
category2A.getCategories().add(category3A);
final CDOTransaction transaction = session.openTransaction();
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(companyA);
transaction.commit();
// ************************************************************* //
final CDOView viewB = session.openTransaction();
final CDOResource resourceB = viewB.getResource(getResourcePath("/test1"));
assertProxy(resourceB);
EList<EObject> contents = resourceB.getContents();
final Company companyB = (Company)contents.get(0);
assertClean(companyB, viewB);
assertClean(resourceB, viewB);
assertContent(resourceB, companyB);
final Category category1B = companyB.getCategories().get(0);
assertClean(category1B, viewB);
assertClean(companyB, viewB);
assertContent(companyB, category1B);
final Category category2B = category1B.getCategories().get(0);
assertClean(category2B, viewB);
assertClean(category1B, viewB);
assertContent(category1B, category2B);
final Category category3B = category2B.getCategories().get(0);
assertClean(category3B, viewB);
assertClean(category2B, viewB);
assertContent(category2B, category3B);
assertClean(category3B, viewB);
// ************************************************************* //
final CountDownLatch latch = new CountDownLatch(1);
viewB.getSession().addListener(new IListener()
{
public void notifyEvent(IEvent event)
{
if (event instanceof CDOSessionInvalidationEvent)
{
CDOSessionInvalidationEvent e = (CDOSessionInvalidationEvent)event;
if (e.getLocalTransaction() == transaction)
{
msg("CDOSessionInvalidationEvent: " + e);
latch.countDown();
}
}
}
});
category1A.setName("CHANGED NAME");
transaction.commit();
boolean notified = latch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
assertEquals(true, notified);
}
public void testConflictSameSession() throws Exception, IOException
{
CDOSession session = openSession();
CDOTransaction trans1 = session.openTransaction();
CDOTransaction trans2 = session.openTransaction();
testConflict(trans1, trans2);
}
public void testConflictDifferentSession() throws Exception, IOException
{
CDOSession session1 = openSession();
CDOTransaction trans1 = session1.openTransaction();
CDOSession session2 = openSession();
CDOTransaction trans2 = session2.openTransaction();
testConflict(trans1, trans2);
}
private void testConflict(CDOTransaction trans1, CDOTransaction trans2) throws Exception
{
final CDOResource res1 = trans1.getOrCreateResource(getResourcePath("/test"));
trans1.commit();
final CDOResource res2 = trans2.getOrCreateResource(getResourcePath("/test"));
final Customer customerA1 = getModel1Factory().createCustomer();
res1.getContents().add(customerA1);
final Customer customerB2 = getModel1Factory().createCustomer();
res2.getContents().add(customerB2);
trans1.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return CDOUtil.getCDOObject(res2).cdoState() == CDOState.CONFLICT;
}
}.assertNoTimeOut();
final Customer customerA2 = getModel1Factory().createCustomer();
res1.getContents().add(customerA2);
trans1.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return CDOUtil.getCDOObject(res2).cdoState() == CDOState.CONFLICT;
}
}.assertNoTimeOut();
trans2.rollback();
assertEquals(2, res1.getContents().size());
}
public void testDetachedConflictSameSession() throws Exception, IOException
{
CDOSession session = openSession();
CDOTransaction trans1 = session.openTransaction();
trans1.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT);
CDOTransaction trans2 = session.openTransaction();
trans2.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT);
testDetachedConflict(trans1, trans2);
}
public void testDetachedConflictDifferentSession() throws Exception, IOException
{
CDOSession session1 = openSession();
CDOTransaction trans1 = session1.openTransaction();
trans1.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT);
CDOSession session2 = openSession();
CDOTransaction trans2 = session2.openTransaction();
trans2.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT);
testDetachedConflict(trans1, trans2);
}
private void testDetachedConflict(CDOTransaction trans1, CDOTransaction trans2) throws Exception
{
final CDOResource res1 = trans1.getOrCreateResource(getResourcePath("/test"));
trans1.commit();
final CDOResource res2 = trans2.getResource(getResourcePath("/test"));
res1.delete(null);
res2.getContents().add(getModel1Factory().createCustomer());
assertEquals(true, res2.isExisting());
commitAndSync(trans1, trans2);
assertEquals(CDOState.INVALID_CONFLICT, CDOUtil.getCDOObject(res2).cdoState());
trans2.rollback();
assertEquals(CDOState.INVALID, CDOUtil.getCDOObject(res2).cdoState());
assertEquals(false, res2.isExisting());
try
{
res2.getContents().get(0);
fail("InvalidObjectException expected");
}
catch (InvalidObjectException expected)
{
// SUCCESS
}
}
public void testSeparateSession() throws Exception
{
final Category category1A = getModel1Factory().createCategory();
category1A.setName("category1");
final Category category2A = getModel1Factory().createCategory();
category2A.setName("category2");
final Category category3A = getModel1Factory().createCategory();
category3A.setName("category3");
final Company companyA = getModel1Factory().createCompany();
companyA.getCategories().add(category1A);
category1A.getCategories().add(category2A);
category2A.getCategories().add(category3A);
final CDOSession sessionA = openSession();
final CDOTransaction transaction = sessionA.openTransaction();
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(companyA);
transaction.commit();
// ************************************************************* //
final CDOSession sessionB = openSession();
final CDOView viewB = sessionB.openTransaction();
final CDOResource resourceB = viewB.getResource(getResourcePath("/test1"));
assertProxy(resourceB);
EList<EObject> contents = resourceB.getContents();
final Company companyB = (Company)contents.get(0);
assertClean(companyB, viewB);
assertClean(resourceB, viewB);
assertContent(resourceB, companyB);
final Category category1B = companyB.getCategories().get(0);
assertClean(category1B, viewB);
assertClean(companyB, viewB);
assertContent(companyB, category1B);
final Category category2B = category1B.getCategories().get(0);
assertClean(category2B, viewB);
assertClean(category1B, viewB);
assertContent(category1B, category2B);
final Category category3B = category2B.getCategories().get(0);
assertClean(category3B, viewB);
assertClean(category2B, viewB);
assertContent(category2B, category3B);
assertClean(category3B, viewB);
// ************************************************************* //
category1A.setName("CHANGED NAME");
transaction.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return "CHANGED NAME".equals(category1B.getName());
}
}.assertNoTimeOut();
}
/**
* See bug 236784
*/
public void testInvalidateAndCache() throws Exception
{
msg("Opening sessionA");
CDOSession sessionA = openSession();
msg("Opening transactionA");
final CDOTransaction transactionA = sessionA.openTransaction();
final CDOID cdoidA;
// *************************************************************
{
msg("Creating categoryA");
Category categoryA = getModel1Factory().createCategory();
categoryA.setName("categoryA");
msg("Creating companyA");
Company companyA = getModel1Factory().createCompany();
msg("Adding categories");
companyA.getCategories().add(categoryA);
msg("Creating resource");
CDOResource resourceA = transactionA.createResource(getResourcePath("/test1"));
msg("Adding companyA");
resourceA.getContents().add(companyA);
msg("Committing");
transactionA.commit();
cdoidA = CDOUtil.getCDOObject(categoryA).cdoID();
((CDOViewImpl)transactionA).removeObject(cdoidA);
}
// *************************************************************
msg("Opening sessionB");
CDOSession sessionB = openSession();
msg("Opening transactionB");
CDOTransaction transactionB = sessionB.openTransaction();
Category categoryB;
categoryB = (Category)CDOUtil.getEObject(transactionB.getObject(cdoidA, true));
msg("Changing name");
categoryB.setName("CHANGED NAME");
msg("\n\n\n\n\n\n\n\n\n\n\nCommitting");
transactionB.commit();
msg("Checking after commit");
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
Category categoryA = (Category)CDOUtil.getEObject(transactionA.getObject(cdoidA, true));
String name = categoryA.getName();
return "CHANGED NAME".equals(name);
}
}.assertNoTimeOut();
}
public void testRefreshEmptyRepository() throws Exception
{
CDOSession session = openSession();
assertEquals(0, session.refresh());
session.close();
}
public void testSeparateSession_PassiveUpdateDisable() throws Exception
{
Category category1A = getModel1Factory().createCategory();
category1A.setName("category1");
Category category2A = getModel1Factory().createCategory();
category2A.setName("category2");
Category category3A = getModel1Factory().createCategory();
category3A.setName("category3");
Company companyA = getModel1Factory().createCompany();
companyA.getCategories().add(category1A);
category1A.getCategories().add(category2A);
category2A.getCategories().add(category3A);
CDOSession sessionA = openSession();
CDOTransaction transaction = sessionA.openTransaction();
CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(companyA);
transaction.commit();
URI uriCategory1 = EcoreUtil.getURI(category1A);
// ************************************************************* //
CDOSession sessionB = openSession();
sessionB.options().setPassiveUpdateEnabled(false);
CDOView viewB = sessionB.openTransaction();
final Category category1B = (Category)viewB.getResourceSet().getEObject(uriCategory1, true);
// ************************************************************* //
category1A.setName("CHANGED NAME");
transaction.commit();
sessionB.refresh();
// TODO Why poll? refresh is synchonous...
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return "CHANGED NAME".equals(category1B.getName());
}
}.assertNoTimeOut();
}
public void testPassiveUpdateOnAndOff() throws Exception
{
msg("Creating category1");
final Category category1A = getModel1Factory().createCategory();
category1A.setName("category1");
msg("Creating category2");
final Category category2A = getModel1Factory().createCategory();
category2A.setName("category2");
msg("Creating category3");
final Category category3A = getModel1Factory().createCategory();
category3A.setName("category3");
msg("Creating company");
final Company companyA = getModel1Factory().createCompany();
msg("Adding categories");
companyA.getCategories().add(category1A);
category1A.getCategories().add(category2A);
category2A.getCategories().add(category3A);
msg("Opening sessionA");
final CDOSession sessionA = openSession();
msg("Attaching transaction");
final CDOTransaction transaction = sessionA.openTransaction();
msg("Creating resource");
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
msg("Adding company");
resourceA.getContents().add(companyA);
msg("Committing");
transaction.commit();
URI uriCategory1 = EcoreUtil.getURI(category1A);
// ************************************************************* //
msg("Opening sessionB");
final CDOSession sessionB = openSession();
sessionB.options().setPassiveUpdateEnabled(false);
msg("Attaching viewB");
final CDOView viewB = sessionB.openTransaction();
final Category category1B = (Category)viewB.getResourceSet().getEObject(uriCategory1, true);
// ************************************************************* //
msg("Opening sessionB");
final CDOSession sessionC = openSession();
assertEquals(true, sessionC.options().isPassiveUpdateEnabled());
msg("Attaching viewB");
final CDOView viewC = sessionC.openTransaction();
final Category category1C = (Category)viewC.getResourceSet().getEObject(uriCategory1, true);
msg("Changing name");
category1A.setName("CHANGED NAME");
class TimeOuterB extends PollingTimeOuter
{
@Override
protected boolean successful()
{
return "CHANGED NAME".equals(category1B.getName());
}
}
class TimeOuterC extends PollingTimeOuter
{
@Override
protected boolean successful()
{
return "CHANGED NAME".equals(category1C.getName());
}
}
transaction.commit();
new TimeOuterC().assertNoTimeOut();
// It should refresh the session
sessionB.options().setPassiveUpdateEnabled(true);
msg("Checking after sync");
new TimeOuterB().assertNoTimeOut();
new TimeOuterC().assertNoTimeOut();
category1A.setName("CHANGED NAME-VERSION2");
class TimeOuterB_2 extends PollingTimeOuter
{
@Override
protected boolean successful()
{
return "CHANGED NAME-VERSION2".equals(category1B.getName());
}
}
class TimeOuterC_2 extends PollingTimeOuter
{
@Override
protected boolean successful()
{
return "CHANGED NAME-VERSION2".equals(category1C.getName());
}
}
transaction.commit();
new TimeOuterB_2().assertNoTimeOut();
new TimeOuterC_2().assertNoTimeOut();
}
public void testDetach() throws Exception
{
final Category categoryA = getModel1Factory().createCategory();
categoryA.setName("category1");
final CDOSession sessionA = openSession();
final CDOTransaction transaction = sessionA.openTransaction();
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(categoryA);
transaction.commit();
// ************************************************************* //
final CDOSession sessionB = openSession();
final CDOView viewB = sessionB.openTransaction();
viewB.options().setInvalidationNotificationEnabled(true);
final CDOResource resourceB = viewB.getResource(getResourcePath("/test1"));
assertProxy(resourceB);
EList<EObject> contents = resourceB.getContents();
final Category categoryB = (Category)contents.get(0);
final TestAdapter testAdapter = new TestAdapter();
categoryB.eAdapters().add(testAdapter);
// ************************************************************* //
resourceA.getContents().remove(categoryA);
assertEquals(0, testAdapter.getNotifications().length);
transaction.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return FSMUtil.isInvalid(CDOUtil.getCDOObject(categoryB));
}
}.assertNoTimeOut();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return testAdapter.getNotifications().length == 1;
}
}.assertNoTimeOut();
}
public void testDetachAndPassiveUpdate() throws Exception
{
detachAndPassiveUpdate(false);
}
public void testDetachAndPassiveUpdateWithoutRevisionTimestamp() throws Exception
{
detachAndPassiveUpdate(true);
}
private void detachAndPassiveUpdate(boolean isRemoveRevision) throws Exception
{
msg("Creating category1");
final Category categoryA = getModel1Factory().createCategory();
categoryA.setName("category1");
msg("Opening sessionA");
final CDOSession sessionA = openSession();
msg("Attaching transaction");
final CDOTransaction transaction = sessionA.openTransaction();
msg("Creating resource");
final CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
msg("Adding company");
resourceA.getContents().add(categoryA);
msg("Committing");
transaction.commit();
// ************************************************************* //
msg("Opening sessionB");
final CDOSession sessionB = openSession();
sessionB.options().setPassiveUpdateEnabled(false);
msg("Attaching viewB");
final CDOView viewB = sessionB.openTransaction();
viewB.options().setInvalidationNotificationEnabled(true);
msg("Loading resource");
final CDOResource resourceB = viewB.getResource(getResourcePath("/test1"));
assertProxy(resourceB);
EList<EObject> contents = resourceB.getContents();
final Category categoryB = (Category)contents.get(0);
final TestAdapter testAdapter = new TestAdapter();
categoryB.eAdapters().add(testAdapter);
// ************************************************************* //
resourceA.getContents().remove(categoryA);
assertEquals(0, testAdapter.getNotifications().length);
transaction.commit();
final Category categoryA2 = getModel1Factory().createCategory();
categoryA2.setName("categoryA2");
resourceA.getContents().add(categoryA2);
transaction.commit();
if (isRemoveRevision)
{
clearCache(getRepository().getRevisionManager());
getRepository().getRevisionManager().getCache().removeRevision(resourceA.cdoID(),
resourceA.cdoRevision().getBranch().getVersion(1));
getRepository().getRevisionManager().getCache().removeRevision(resourceA.cdoID(),
resourceA.cdoRevision().getBranch().getVersion(2));
}
assertEquals(0, testAdapter.getNotifications().length);
sessionB.refresh();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return FSMUtil.isInvalid(CDOUtil.getCDOObject(categoryB));
}
}.assertNoTimeOut();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
return testAdapter.getNotifications().length == 1;
}
}.assertNoTimeOut();
}
public void testPassiveUpdateMode_CHANGES() throws Exception
{
Category categoryA = getModel1Factory().createCategory();
categoryA.setName("category1");
CDOSession sessionA = openSession();
CDOTransaction transaction = sessionA.openTransaction();
CDOResource resourceA = transaction.createResource(getResourcePath("/test1"));
resourceA.getContents().add(categoryA);
transaction.commit();
// ************************************************************* //
CDOSession sessionB = openSession();
sessionB.options().setPassiveUpdateMode(PassiveUpdateMode.CHANGES);
CDOView viewB = sessionB.openTransaction();
CDOResource resourceB = viewB.getResource(getResourcePath("/test1"));
Category categoryB = (Category)resourceB.getContents().get(0);
final TestAdapter testAdapter = new TestAdapter();
categoryB.eAdapters().add(testAdapter);
// ************************************************************* //
categoryA.setName("CHANGED");
assertEquals(0, testAdapter.getNotifications().length);
transaction.commit();
new PollingTimeOuter()
{
@Override
protected boolean successful()
{
Notification[] notifications = testAdapter.getNotifications();
if (notifications.length != 0)
{
if (!ObjectUtil.equals(notifications[0].getOldStringValue(), "category1"))
{
fail("No old value");
}
if (!ObjectUtil.equals(notifications[0].getNewStringValue(), "CHANGED"))
{
fail("No new value");
}
return true;
}
return false;
}
}.assertNoTimeOut();
}
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
public void testDeleteFromOtherBranch() throws Exception
{
Company companyA = getModel1Factory().createCompany();
Category categoryA = getModel1Factory().createCategory();
companyA.getCategories().add(categoryA);
CDOSession session = openSession();
session.options().setPassiveUpdateEnabled(true);
session.options().setPassiveUpdateMode(PassiveUpdateMode.CHANGES);
CDOTransaction transactionA = session.openTransaction();
CDOResource resourceA = transactionA.createResource(getResourcePath("/test1"));
resourceA.getContents().add(companyA);
CDOBranch mainBranch = transactionA.getBranch();
transactionA.commit(); // company v1
assertEquals(mainBranch, CDOUtil.getCDOObject(companyA).cdoRevision().getBranch());
assertEquals(1, CDOUtil.getCDOObject(companyA).cdoRevision().getVersion());
companyA.setName("ESC");
transactionA.commit(); // company v2
assertEquals(mainBranch, CDOUtil.getCDOObject(companyA).cdoRevision().getBranch());
assertEquals(2, CDOUtil.getCDOObject(companyA).cdoRevision().getVersion());
CDOTransaction transactionB = session.openTransaction();
CDOResource resourceB = transactionB.getResource(getResourcePath("/test1"));
Company companyB = (Company)resourceB.getContents().get(0);
companyB.getCategories().get(0);
CDOObject cdoCompanyB = CDOUtil.getCDOObject(companyB);
CDOBranch branch1 = mainBranch.createBranch("branch1");
transactionB.setBranch(branch1);
transactionA.setBranch(branch1);
assertEquals(mainBranch, cdoCompanyB.cdoRevision().getBranch());
assertEquals(2, cdoCompanyB.cdoRevision().getVersion());
companyA.getCategories().remove(0);
commitAndSync(transactionA, transactionB);
assertEquals(CDOState.CLEAN, cdoCompanyB.cdoState());
assertEquals(branch1, cdoCompanyB.cdoRevision().getBranch());
assertEquals(1, cdoCompanyB.cdoRevision().getVersion());
}
}