/* * Copyright (c) 2010-2012 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: * Caspar De Groot - initial API and implementation */ package org.eclipse.emf.cdo.tests; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.server.IRepository; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.tests.config.IRepositoryConfig; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires; import org.eclipse.emf.cdo.tests.model1.Category; import org.eclipse.emf.cdo.tests.model1.Company; 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.util.ObjectNotFoundException; import org.eclipse.emf.common.util.EList; /** * @author Caspar De Groot */ // Sticky behavior is only enabled when store supports auditing, so these tests are // meaningless and/or guaranteed to fail if this is not the case @Requires(IRepositoryConfig.CAPABILITY_AUDITING) public class StickyViewsTest extends AbstractCDOTest { private static final int N_CATEGORIES = 3; public void test_removeLast() throws CommitException { test(new AbstractClosure() { public void doChange(EList<Category> categories) { categories.remove(N_CATEGORIES - 1); } }); } public void test_removeFirst() throws CommitException { test(new AbstractClosure() { public void doChange(EList<Category> categories) { categories.remove(0); } }); } public void test_changeName() throws CommitException { test(new AbstractClosure() { public void doChange(EList<Category> categories) { categories.get(0).setName("zzz"); } @Override public void verify(EList<Category> categories) { assertEquals("category0", categories.get(0).getName()); } }); } private void test(Closure closure) throws CommitException { // Create a company with N categories Company company1 = getModel1Factory().createCompany(); company1.setName("company"); for (int i = 0; i < N_CATEGORIES; i++) { Category category = getModel1Factory().createCategory(); company1.getCategories().add(category); category.setName("category" + i); } // Persist it CDOSession session = openSession(); CDOTransaction transaction1 = session.openTransaction(); CDOResource res = transaction1.createResource(getResourcePath("/res1")); res.getContents().add(company1); transaction1.commit(); assertEquals(N_CATEGORIES, company1.getCategories().size()); // Fetch the same company in another session/tx CDOSession session2 = openSession(); session2.options().setPassiveUpdateEnabled(false); CDOTransaction transaction2 = session2.openTransaction(); CDOResource res2 = transaction2.getResource(getResourcePath("/res1")); Company company2 = (Company)res2.getContents().get(0); // In the 1st session, manipulate the categories closure.doChange(company1.getCategories()); transaction1.commit(); // Clear server-side cache to force loading of revisions from IStore IRepository repo = getRepositoryConfig().getRepository(IRepositoryConfig.REPOSITORY_NAME); ((InternalCDORevisionManager)repo.getRevisionManager()).getCache().clear(); // Verify that in 2nd session, all categories still appear to be present closure.verify(company2.getCategories()); msg("Done"); transaction1.close(); session.close(); session2.close(); transaction2.close(); } /** * Ensures that a newly committed object in this tx, can be reloaded from the server. */ public void test_newCommittedObject() throws CommitException { CDOSession session = openSession(); session.options().setPassiveUpdateEnabled(false); CDOTransaction tx = session.openTransaction(); CDOResource res = tx.createResource(getResourcePath("/res1")); Company company1 = getModel1Factory().createCompany(); res.getContents().add(company1); tx.commit(); // Make dirty, then roll back, so as to force PROXY state // company1.setName("company1"); tx.rollback(); // Clear cache to force loading of revisions from server // ((InternalCDORevisionManager)session.getRevisionManager()).getCache().clear(); // Clear server-side cache to force loading of revisions from IStore // IRepository repo = getRepositoryConfig().getRepository(IRepositoryConfig.REPOSITORY_NAME); ((InternalCDORevisionManager)repo.getRevisionManager()).getCache().clear(); assertClean(CDOUtil.getCDOObject(company1), tx); msg(company1.getName()); CDOID id = CDOUtil.getCDOObject(company1).cdoID(); company1 = null; CDOObject obj = tx.getObject(id); assertNotNull(obj); session.close(); } /** * Ensures that an object that was updated and committed in this tx, can be reloaded in its *updated* state from the * server. */ public void test_dirtyCommittedObject() throws CommitException { // Put a company in the repo { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); CDOResource res = tx.createResource(getResourcePath("/res1")); Company company1 = getModel1Factory().createCompany(); company1.setName("aaa"); res.getContents().add(company1); tx.commit(); sess.close(); } // Load it up in a different, sticky session { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); sess.options().setPassiveUpdateEnabled(false); CDOResource res = tx.getResource(getResourcePath("/res1")); // Save with a new name Company company1 = (Company)res.getContents().get(0); company1.setName("bbb"); tx.commit(); // Make dirty then roll back, so as to force PROXY state company1.setName("ccc"); tx.rollback(); assertClean(CDOUtil.getCDOObject(company1), tx); // Clear cache to force loading of revisions from server ((InternalCDORevisionManager)sess.getRevisionManager()).getCache().clear(); // Clear server-side cache to force loading of revisions from IStore IRepository repo = getRepositoryConfig().getRepository(IRepositoryConfig.REPOSITORY_NAME); ((InternalCDORevisionManager)repo.getRevisionManager()).getCache().clear(); String name = company1.getName(); assertEquals("bbb", name); sess.close(); } } /** * Ensures that an object that was removed in this tx, can no longer be loaded (even though the sticky time is still * set to a time when the object still existed!) */ public void test_detachedCommittedObject() throws CommitException { // Put a company in the repo { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); CDOResource res = tx.createResource(getResourcePath("/res1")); Company company1 = getModel1Factory().createCompany(); company1.setName("aaa"); res.getContents().add(company1); tx.commit(); sess.close(); } // Load it up in a different, sticky session { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); sess.options().setPassiveUpdateEnabled(false); CDOResource res = tx.getResource(getResourcePath("/res1")); // Remove it Company company1 = (Company)res.getContents().get(0); CDOID companyID = CDOUtil.getCDOObject(company1).cdoID(); res.getContents().remove(company1); tx.commit(); // Clear cache to force loading of revisions from server // ((InternalCDORevisionManager)sess.getRevisionManager()).getCache().clear(); // Clear server-side cache to force loading of revisions from IStore // IRepository repo = getRepositoryConfig().getRepository(IRepositoryConfig.REPOSITORY_NAME); ((InternalCDORevisionManager)repo.getRevisionManager()).getCache().clear(); try { tx.getObject(companyID); fail("Should have thrown " + ObjectNotFoundException.class.getSimpleName()); } catch (ObjectNotFoundException e) { // Good } sess.close(); } } public void test_refresh() throws CommitException { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); sess.options().setPassiveUpdateEnabled(false); CDOResource res = tx.createResource(getResourcePath("/res1")); Company company1 = getModel1Factory().createCompany(); company1.setName("aaa"); res.getContents().add(company1); tx.commit(); // Puts the company in committedSinceLastRefresh sess.refresh(); // Removes the company from committedSinceLastRefresh // Make dirty then rollback to force proxy company1.setName("bbb"); tx.rollback(); // Clear cache to force loading of revisions from server // ((InternalCDORevisionManager)sess.getRevisionManager()).getCache().clear(); doOtherSession(); // Creates a new revision on the server assertClean(CDOUtil.getCDOObject(company1), tx); assertEquals("The company name should not have the value set in the other session", "aaa", company1.getName()); sess.close(); } public void test_otherSessionCommittedLatest() throws CommitException { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); sess.options().setPassiveUpdateEnabled(false); CDOResource res = tx.createResource(getResourcePath("/res1")); Company company1 = getModel1Factory().createCompany(); company1.setName("aaa"); res.getContents().add(company1); tx.commit(); // Puts the company in committedSinceLastRefresh // Make dirty then rollback to force proxy company1.setName("bbb"); tx.rollback(); // Clear cache to force loading of revisions from server ((InternalCDORevisionManager)sess.getRevisionManager()).getCache().clear(); doOtherSession(); // Creates a new revision on the server assertClean(CDOUtil.getCDOObject(company1), tx); // Verify that this session still fetches the revision that *this* session just committed, // rather than the latest revision, which was committed by the other session assertEquals("aaa", company1.getName()); sess.close(); } private void doOtherSession() throws CommitException { CDOSession sess = openSession(); CDOTransaction tx = sess.openTransaction(); CDOResource res = tx.getResource(getResourcePath("/res1")); Company company1 = (Company)res.getContents().get(0); company1.setName("ccc"); tx.commit(); tx.close(); sess.close(); } /** * @author Caspar De Groot */ private interface Closure { public void doChange(EList<Category> categories); public void verify(EList<Category> categories); } /** * @author Caspar De Groot */ private abstract class AbstractClosure implements Closure { public void verify(EList<Category> categories) { assertEquals(N_CATEGORIES, categories.size()); // Now fetch each category in the 2nd session for (int i = 0; i < N_CATEGORIES; i++) { msg("Getting index " + i); assertEquals(N_CATEGORIES, categories.size()); try { Category cat = categories.get(i); assertNotNull(cat); } catch (ObjectNotFoundException e) { fail("Should not have thrown " + ObjectNotFoundException.class.getName()); } } } } }