blob: 1df8e1f8ea817e1f2cd355165b324c8bd019a9bb [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:
* Simon McDuff - initial API and implementation
* Eike Stepper - maintenance
*/
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl;
import org.eclipse.emf.cdo.internal.server.mem.MEMStore;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
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.model1.SalesOrder;
import org.eclipse.emf.cdo.tests.model3.NodeD;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
/**
* See bug 201266
*
* @author Simon McDuff
*/
public class RevisionDeltaTest extends AbstractCDOTest
{
public RevisionDeltaTest()
{
}
public void testBasicRevisionDelta() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource1 = transaction.createResource(getResourcePath("/test1"));
Company company1 = getModel1Factory().createCompany();
Category category1 = getModel1Factory().createCategory();
resource1.getContents().add(company1);
company1.getCategories().add(category1);
company1.setName("TEST");
InternalCDORevision rev1 = getCopyCDORevision(company1);
// Test simple attributes
company1.setName("TEST3");
InternalCDORevision rev2 = getCopyCDORevision(company1);
CDORevisionDelta revisionDelta = rev2.compare(rev1);
assertEquals(1, revisionDelta.getFeatureDeltas().size());
CDOSetFeatureDelta setDelta = (CDOSetFeatureDelta)revisionDelta.getFeatureDeltas().get(0);
assertEquals("TEST3", setDelta.getValue());
// Test List clear
company1.getCategories().clear();
InternalCDORevision rev3 = getCopyCDORevision(company1);
CDORevisionDelta revisionDelta3 = rev3.compare(rev2);
assertEquals(1, revisionDelta3.getFeatureDeltas().size());
CDOListFeatureDeltaImpl delta3List = (CDOListFeatureDeltaImpl)revisionDelta3.getFeatureDeltas().get(0);
assertEquals(1, delta3List.getListChanges().size());
assertEquals(true, delta3List.getListChanges().get(0) instanceof CDOClearFeatureDelta);
// Test List Add
for (int i = 0; i < 5; i++)
{
Category category = getModel1Factory().createCategory();
company1.getCategories().add(category);
}
InternalCDORevision rev4 = getCopyCDORevision(company1);
CDORevisionDelta revisionDelta4 = rev4.compare(rev3);
assertEquals(1, revisionDelta4.getFeatureDeltas().size());
CDOListFeatureDeltaImpl delta4List = (CDOListFeatureDeltaImpl)revisionDelta4.getFeatureDeltas().get(0);
assertEquals(5, delta4List.getListChanges().size());
assertEquals(true, delta4List.getListChanges().get(0) instanceof CDOAddFeatureDelta);
transaction.rollback();
transaction.close();
session.close();
}
/**
* Sending deltas doesn't adjust CDOIDs
* <p>
* See bug 214374
*/
public void testBugzilla214374() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
SalesOrder salesOrder = getModel1Factory().createSalesOrder();
resource.getContents().add(salesOrder);
transaction.commit();
Customer customer = getModel1Factory().createCustomer();
salesOrder.setCustomer(customer);
resource.getContents().add(customer);
transaction.commit();
transaction.close();
CDOTransaction transaction2 = session.openTransaction();
SalesOrder salesOrder2 = (SalesOrder)CDOUtil
.getEObject(transaction2.getObject(CDOUtil.getCDOObject(salesOrder).cdoID(), true));
CDORevision salesRevision = CDOUtil.getCDOObject(salesOrder2).cdoRevision();
EStructuralFeature customerFeature = getModel1Package().getSalesOrder_Customer();
Object value = salesRevision.data().get(customerFeature, 0);
assertEquals(true, value instanceof CDOID);
transaction2.close();
session.close();
}
/**
* CDOView.getRevision() does not work for transactions/dirty objects (INVALID)
* <p>
* See bug 214431
*/
public void testBugzilla214431() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
SalesOrder salesOrder = getModel1Factory().createSalesOrder();
resource.getContents().add(salesOrder);
transaction.commit();
salesOrder.setId(4711);
assertNotSame(CDOUtil.getCDOObject(salesOrder).cdoRevision(),
((InternalCDOTransaction)transaction).getRevision(CDOUtil.getCDOObject(salesOrder).cdoID(), true));
assertEquals(CDOUtil.getCDOObject(salesOrder).cdoRevision(),
transaction.getDirtyObjects().get(CDOUtil.getCDOObject(salesOrder).cdoID()).cdoRevision());
transaction.close();
session.close();
}
/**
* CDOView.getRevision() does not work for transactions/dirty objects (INVALID)
* <p>
* See bug 214374
*/
public void testBugzilla214374_HandleClear() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
Customer customer = getModel1Factory().createCustomer();
resource.getContents().add(customer);
SalesOrder salesOrder = getModel1Factory().createSalesOrder();
resource.getContents().add(salesOrder);
customer.getSalesOrders().add(salesOrder);
customer.getSalesOrders().add(salesOrder);
transaction.commit();
salesOrder = getModel1Factory().createSalesOrder();
customer = getModel1Factory().createCustomer();
resource.getContents().add(salesOrder);
resource.getContents().add(customer);
salesOrder.setCustomer(customer);
transaction.commit();
transaction.close();
session.close();
}
/**
* java.lang.IllegalStateException with MEMStore
* <p>
* See bug 243282
*/
public void testBugzilla243282_Exception() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
Customer customer = getModel1Factory().createCustomer();
resource.getContents().add(customer);
transaction.commit();
InternalCDORevisionManager revisionManager = getRepository().getRevisionManager();
CDORevision revision = CDOUtil.getCDOObject(customer).cdoRevision();
revisionManager.getCache().removeRevision(revision.getID(), revision);
SalesOrder salesOrder = getModel1Factory().createSalesOrder();
resource.getContents().add(salesOrder);
customer.getSalesOrders().add(salesOrder);
IStore store = getRepository().getStore();
if (store instanceof MEMStore)
{
MEMStore memStore = (MEMStore)store;
CDORevisionUtil.dumpAllRevisions(memStore.getAllRevisions(), IOUtil.OUT());
}
transaction.commit();
transaction.close();
session.close();
}
@SuppressWarnings("unused")
public void testDetachWithXRef() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
NodeD a = getModel3Factory().createNodeD();
NodeD b = getModel3Factory().createNodeD();
NodeD c = getModel3Factory().createNodeD();
a.getChildren().add(b);
c.getOtherNodes().add(b);
resource.getContents().add(a);
resource.getContents().add(c);
if (true)
{
transaction.commit();
transaction.close();
transaction = session.openTransaction();
resource = transaction.getResource(getResourcePath("/test1"));
}
// Start test logic
a = (NodeD)resource.getContents().get(0);
b = a.getChildren().get(0);
c = (NodeD)resource.getContents().get(1);
a.getChildren().remove(0);
Object[] cB = c.getOtherNodes().toArray();
CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID());
CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID());
session.close();
}
@SuppressWarnings("unused")
public void testDetachWithXRef_Remove() throws Exception
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
NodeD a = getModel3Factory().createNodeD();
NodeD b = getModel3Factory().createNodeD();
NodeD c = getModel3Factory().createNodeD();
a.getChildren().add(b);
c.getOtherNodes().add(b);
resource.getContents().add(a);
resource.getContents().add(c);
if (true)
{
transaction.commit();
transaction.close();
transaction = session.openTransaction();
resource = transaction.getResource(getResourcePath("/test1"));
}
// Start test logic
a = (NodeD)resource.getContents().get(0);
b = a.getChildren().get(0);
c = (NodeD)resource.getContents().get(1);
a.getChildren().remove(0);
c.getOtherNodes().remove(0);
Object[] cB = c.getOtherNodes().toArray();
CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID());
CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID());
CDOListFeatureDelta list = (CDOListFeatureDelta)cDelta.getFeatureDelta(getModel3Package().getNodeD_OtherNodes());
assertEquals(1, list.getListChanges().size());
session.close();
}
public void testListRemoveMiddle()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.remove(5);
}
});
}
public void testListRemoveLast()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.remove(list.size() - 1);
}
});
}
public void testListRemoveFirst()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.remove(0);
}
});
}
public void testListSimpleMove()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.move(2, 7);
}
});
}
public void testListMoveToLast()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.move(2, list.size() - 1);
}
});
}
public void testListMoveToFirst()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.move(2, 0);
}
});
}
public void testListTwoIndependentMoves()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.move(1, 3);
list.move(7, 4);
}
});
}
public void testListTwoIntersectingMoves()
{
testStoreDelta(new ListManipulator()
{
public void doManipulations(EList<?> list)
{
list.move(1, 7);
list.move(3, 4);
}
});
}
public void testListInsertFirst()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry");
l.add(0, company);
}
});
}
public void testListInsertMiddle()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry");
l.add(5, company);
}
});
}
public void testListInsertLast()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry");
l.add(company);
}
});
}
public void testListMultipleOpsWithClear()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
l.remove(4);
l.remove(7);
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(5, company);
l.move(1, 2);
l.move(7, 0);
l.clear();
company = getModel1Factory().createCompany();
company.setName("NewEntry 2");
l.add(company);
company = getModel1Factory().createCompany();
company.setName("NewEntry 3");
l.add(company);
company = getModel1Factory().createCompany();
company.setName("NewEntry 4");
l.add(0, company);
l.move(1, 2);
}
});
}
public void testListMultipleOps()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
l.remove(7);
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(5, company);
l.move(1, 2);
company = getModel1Factory().createCompany();
company.setName("NewEntry 2");
l.add(company);
l.move(7, 0);
company = getModel1Factory().createCompany();
company.setName("NewEntry 3");
l.add(company);
l.remove(4);
company = getModel1Factory().createCompany();
company.setName("NewEntry 4");
l.add(0, company);
l.move(1, 2);
}
});
}
public void testMultipleInserts()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(7, company);
company = getModel1Factory().createCompany();
company.setName("NewEntry 2");
l.add(12, company);
}
});
}
public void testInsertAndRemove()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(7, company);
l.remove(12);
}
});
}
public void testInsertAndMove()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(7, company);
l.move(12, 7);
}
});
}
public void testMoveAndDelete()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
l.move(12, 7);
l.remove(12);
}
});
}
public void testInsertAndMoveAndRemove()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(7, company);
l.move(12, 7);
l.remove(12);
}
});
}
public void testInsertAndSet()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
l.add(7, company);
Company company2 = getModel1Factory().createCompany();
company2.setName("NewEntry 2");
l.set(7, company2);
l.add(19, company); // <- needed because the set operation makes the company a dangling reference
}
});
}
public void testSetAndRemove()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
Company company = getModel1Factory().createCompany();
company.setName("NewEntry 1");
Company oldCompany = l.get(7);
l.set(7, company);
l.add(19, oldCompany);
l.remove(7); // <- needed because the set operation makes the company a dangling reference
}
});
}
public void testMultipleRemoves()
{
testStoreDelta(new ListManipulator()
{
@SuppressWarnings("unchecked")
public void doManipulations(EList<?> list)
{
EList<Company> l = (EList<Company>)list;
l.remove(7);
l.remove(12);
}
});
}
private InternalCDORevision getCopyCDORevision(Object object)
{
return (InternalCDORevision)CDOUtil.getCDOObject((EObject)object).cdoRevision().copy();
}
protected void testStoreDelta(ListManipulator manipulator)
{
BasicEList<Company> reference = new BasicEList<Company>();
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/test1"));
for (int i = 0; i < 20; i++)
{
String name = "company " + i;
Company company = getModel1Factory().createCompany();
company.setName(name);
resource.getContents().add(company);
company = getModel1Factory().createCompany();
company.setName(name);
reference.add(company);
}
try
{
transaction.commit();
}
catch (CommitException ex)
{
throw WrappedException.wrap(ex);
}
transaction.close();
session.close();
}
clearCache(getRepository().getRevisionManager());
{
CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.getResource(getResourcePath("/test1"));
manipulator.doManipulations(resource.getContents());
manipulator.doManipulations(reference);
try
{
transaction.commit();
}
catch (CommitException ex)
{
throw WrappedException.wrap(ex);
}
transaction.close();
session.close();
}
clearCache(getRepository().getRevisionManager());
{
CDOSession session = openSession();
CDOView view = session.openView();
CDOResource resource = view.getResource(getResourcePath("/test1"));
assertEquals(reference.size(), resource.getContents().size());
for (int i = 0; i < reference.size(); i++)
{
assertEquals(reference.get(i).getName(), ((Company)resource.getContents().get(i)).getName());
}
view.close();
session.close();
}
}
/**
* @author Simon McDuff
*/
protected static interface ListManipulator
{
public void doManipulations(EList<?> list);
}
}