+ * By "extra API" we mean those methods that are superfluous to the + * function of the JBC integration, where the impl is a no-op or a static + * false return value, UnsupportedOperationException, etc. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase { + + private static CollectionRegionAccessStrategy localAccessStrategy; + + /** + * Create a new PessimisticAccessStrategyExtraAPITestCase. + * + * @param name + */ + public MvccReadOnlyExtraAPITestCase(String name) { + super(name); + } + + @Override + protected String getCacheConfigName() { + return "mvcc-entity"; + } + + @Override + protected CollectionRegionAccessStrategy getCollectionAccessStrategy() { + return localAccessStrategy; + } + + @Override + protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) { + localAccessStrategy = strategy; + } + + @Override + public void testCacheConfiguration() { + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + } + +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReadOnlyTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReadOnlyTestCase.java new file mode 100644 index 0000000000..ee0ab78259 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReadOnlyTestCase.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.collection; + +import org.hibernate.test.util.CacheTestUtil; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Tests READ_ONLY access when pessimistic locking and invalidation are used. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReadOnlyTestCase extends AbstractReadOnlyAccessTestCase { + + /** + * Create a new PessimisticTransactionalAccessTestCase. + * + * @param name + */ + public MvccReadOnlyTestCase(String name) { + super(name); + } + + public static Test suite() throws Exception { + TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccReadOnlyTestCase.class); + return getTestSetup(suite, "mvcc-entity"); + } + + // Known failures + + // Overrides + + @Override + public void testCacheConfiguration() { + assertTrue("Using Invalidation", isUsingInvalidation()); + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + } + +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReplicatedTransactionalTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReplicatedTransactionalTestCase.java new file mode 100644 index 0000000000..cbf29dd181 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccReplicatedTransactionalTestCase.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.collection; + +import junit.framework.Test; + +/** + * Tests TRANSACTIONAL access when pessimistic locking and replication are used. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase { + + /** + * Create a new PessimisticTransactionalAccessTestCase. + * + * @param name + */ + public MvccReplicatedTransactionalTestCase(String name) { + super(name); + } + + public static Test suite() throws Exception { + return getTestSetup(MvccReplicatedTransactionalTestCase.class, "mvcc-shared"); + } + + @Override + public void testCacheConfiguration() { + assertFalse("Using Invalidation", isUsingInvalidation()); + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + assertTrue("Synchronous mode", isSynchronous()); + } + + + +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccTransactionalExtraAPITestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccTransactionalExtraAPITestCase.java new file mode 100644 index 0000000000..d566c6cd59 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/MvccTransactionalExtraAPITestCase.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.collection; + +import org.hibernate.cache.access.CollectionRegionAccessStrategy; + +/** + * Tests for the "extra API" in EntityRegionAccessStrategy; in this base + * version using Optimistic locking with TRANSACTIONAL access. + *
+ * By "extra API" we mean those methods that are superfluous to the + * function of the JBC integration, where the impl is a no-op or a static + * false return value, UnsupportedOperationException, etc. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase { + + private static CollectionRegionAccessStrategy localAccessStrategy; + + /** + * Create a new PessimisticAccessStrategyExtraAPITestCase. + * + * @param name + */ + public MvccTransactionalExtraAPITestCase(String name) { + super(name); + } + + @Override + protected String getCacheConfigName() { + return "mvcc-entity"; + } + + @Override + protected CollectionRegionAccessStrategy getCollectionAccessStrategy() { + return localAccessStrategy; + } + + @Override + protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) { + localAccessStrategy = strategy; + } + + @Override + public void testCacheConfiguration() { + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + } + +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java index 43b671de6e..d73f9f833d 100644 --- a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java @@ -55,9 +55,9 @@ import org.jboss.cache.Node; import org.jboss.cache.NodeSPI; import org.jboss.cache.transaction.BatchModeTransactionManager; -/** +/** * Base class for tests of EntityRegionAccessStrategy impls. - * + * * @author Brian Stansberry * @version $Revision: 1 $ */ @@ -67,46 +67,54 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac public static final String KEY_BASE = "KEY"; public static final String VALUE1 = "VALUE1"; public static final String VALUE2 = "VALUE2"; - + protected static int testCount; - + protected static Configuration localCfg; protected static JBossCacheRegionFactory localRegionFactory; protected static Cache localCache; protected static Configuration remoteCfg; protected static JBossCacheRegionFactory remoteRegionFactory; protected static Cache remoteCache; - + protected static boolean invalidation; protected static boolean optimistic; protected static boolean synchronous; - + protected EntityRegion localEntityRegion; protected EntityRegionAccessStrategy localAccessStrategy; protected EntityRegion remoteEntityRegion; protected EntityRegionAccessStrategy remoteAccessStrategy; - + protected Exception node1Exception; protected Exception node2Exception; - + protected AssertionFailedError node1Failure; protected AssertionFailedError node2Failure; - - + + public static Test getTestSetup(Class testClass, String configName) { - TestSuite suite = new TestSuite(testClass); - return new AccessStrategyTestSetup(suite, configName); + return getTestSetup(testClass, configName, null); } - + public static Test getTestSetup(Test test, String configName) { - return new AccessStrategyTestSetup(test, configName); + return getTestSetup(test, configName, null); } - - + + public static Test getTestSetup(Class testClass, String configName, String configResource) { + TestSuite suite = new TestSuite(testClass); + return new AccessStrategyTestSetup(suite, configName, configResource); + } + + public static Test getTestSetup(Test test, String configName, String configResource) { + return new AccessStrategyTestSetup(test, configName, configResource); + } + + /** * Create a new TransactionalAccessTestCase. - * + * * @param name */ public AbstractEntityRegionAccessStrategyTestCase(String name) { @@ -117,35 +125,35 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac protected void setUp() throws Exception { super.setUp(); - + // Sleep a bit to avoid concurrent FLUSH problem avoidConcurrentFlush(); - + localEntityRegion = localRegionFactory.buildEntityRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription()); localAccessStrategy = localEntityRegion.buildAccessStrategy(getAccessType()); - + // Sleep a bit to avoid concurrent FLUSH problem avoidConcurrentFlush(); - + remoteEntityRegion = remoteRegionFactory.buildEntityRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription()); remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy(getAccessType()); - + node1Exception = null; node2Exception = null; - + node1Failure = null; node2Failure = null; } protected void tearDown() throws Exception { - + super.tearDown(); - + if (localEntityRegion != null) localEntityRegion.destroy(); if (remoteEntityRegion != null) remoteEntityRegion.destroy(); - + try { localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true); localCache.removeNode(Fqn.ROOT); @@ -153,7 +161,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac catch (Exception e) { log.error("Problem purging local cache" ,e); } - + try { remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true); remoteCache.removeNode(Fqn.ROOT); @@ -161,36 +169,39 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac catch (Exception e) { log.error("Problem purging remote cache" ,e); } - + node1Exception = null; node2Exception = null; - + node1Failure = null; node2Failure = null; } - - protected static Configuration createConfiguration(String configName) { + + protected static Configuration createConfiguration(String configName, String configResource) { Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false); cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName); + if (configResource != null) { + cfg.setProperty(MultiplexingCacheInstanceManager.CACHE_FACTORY_RESOURCE_PROP, configResource); + } return cfg; } - + protected CacheDataDescription getCacheDataDescription() { return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE); } - + protected boolean isUsingOptimisticLocking() { return optimistic; } - + protected boolean isUsingInvalidation() { return invalidation; } - + protected boolean isSynchronous() { return synchronous; } - + protected Fqn getRegionFqn(String regionName, String regionPrefix) { return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE); } @@ -201,24 +212,24 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac throw node1Failure; if (node2Failure != null) throw node2Failure; - + if (node1Exception != null) { log.error("node1 saw an exception", node1Exception); assertEquals("node1 saw no exceptions", null, node1Exception); } - + if (node2Exception != null) { log.error("node2 saw an exception", node2Exception); assertEquals("node2 saw no exceptions", null, node2Exception); } } - + /** * This is just a setup test where we assert that the cache config is * as we expected. */ public abstract void testCacheConfiguration(); - + /** * Test method for {@link TransactionalAccess#getRegion()}. */ @@ -239,7 +250,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac public void testPutFromLoadMinimal() throws Exception { putFromLoadTest(true); } - + /** * Simulate 2 nodes, both start, tx do a get, experience a cache miss, * then 'read from db.' First does a putFromLoad, then an update. @@ -248,39 +259,39 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac * both start a new tx and get. First should see the updated data; * second should either see the updated data (isInvalidation() == false) * or null (isInvalidation() == true). - * + * * @param useMinimalAPI * @throws Exception */ private void putFromLoadTest(final boolean useMinimalAPI) throws Exception { - + final String KEY = KEY_BASE + testCount++; - + final CountDownLatch writeLatch1 = new CountDownLatch(1); final CountDownLatch writeLatch2 = new CountDownLatch(1); final CountDownLatch completionLatch = new CountDownLatch(2); - - Thread node1 = new Thread() { - + + Thread node1 = new Thread() { + public void run() { - - try { + + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + assertNull("node1 starts clean", localAccessStrategy.get(KEY, txTimestamp)); - + writeLatch1.await(); - + if (useMinimalAPI) { - localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true); + localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true); } else { localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1)); } - + localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1)); - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -299,29 +310,29 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } } }; - + Thread node2 = new Thread() { - - public void run() { - - try { + + public void run() { + + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp)); - + // Let node1 write writeLatch1.countDown(); // Wait for node1 to finish writeLatch2.await(); - + if (useMinimalAPI) { - remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true); + remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true); } else { remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1)); } - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -338,32 +349,32 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } } }; - + node1.setDaemon(true); node2.setDaemon(true); - + node1.start(); - node2.start(); - + node2.start(); + assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS)); - + assertThreadsRanCleanly(); - + long txTimestamp = System.currentTimeMillis(); assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp)); - + if (isUsingInvalidation()) { if (isUsingOptimisticLocking()) - // The node is "deleted" but it's ghost data version prevents the stale node2 PFER + // The node is "deleted" but it's ghost data version prevents the stale node2 PFER assertEquals("Correct node2 value", null, remoteAccessStrategy.get(KEY, txTimestamp)); else { // no data version to prevent the PFER; we count on db locks preventing this - assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp)); + assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp)); } } else { // The node1 update is replicated, preventing the node2 PFER - assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp)); + assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp)); } } @@ -371,28 +382,28 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac * Test method for {@link TransactionalAccess#insert(java.lang.Object, java.lang.Object, java.lang.Object)}. */ public void testInsert() throws Exception { - + final String KEY = KEY_BASE + testCount++; - + final CountDownLatch readLatch = new CountDownLatch(1); final CountDownLatch commitLatch = new CountDownLatch(1); final CountDownLatch completionLatch = new CountDownLatch(2); - - Thread inserter = new Thread() { - + + Thread inserter = new Thread() { + public void run() { - - try { + + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + assertNull("Correct initial value", localAccessStrategy.get(KEY, txTimestamp)); - + localAccessStrategy.insert(KEY, VALUE1, new Integer(1)); - + readLatch.countDown(); commitLatch.await(); - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -409,20 +420,20 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } } }; - - Thread reader = new Thread() { - + + Thread reader = new Thread() { + public void run() { - - try { + + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + readLatch.await(); - Object expected = isUsingOptimisticLocking() ? null : VALUE1; - + Object expected = !isBlockingReads() ? null : VALUE1; + assertEquals("Correct initial value", expected, localAccessStrategy.get(KEY, txTimestamp)); - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -440,13 +451,13 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } } }; - + inserter.setDaemon(true); reader.setDaemon(true); inserter.start(); reader.start(); - - if (isUsingOptimisticLocking()) + + if (! isBlockingReads()) assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS)); else { // Reader should be blocking for lock @@ -454,48 +465,53 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac commitLatch.countDown(); assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS)); } - + assertThreadsRanCleanly(); - + long txTimestamp = System.currentTimeMillis(); assertEquals("Correct node1 value", VALUE1, localAccessStrategy.get(KEY, txTimestamp)); Object expected = isUsingInvalidation() ? null : VALUE1; assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp)); } + public boolean isBlockingReads() + { + return !isUsingOptimisticLocking(); + } + /** * Test method for {@link TransactionalAccess#update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)}. */ public void testUpdate() throws Exception { - + final String KEY = KEY_BASE + testCount++; - + // Set up initial state localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); - + // Let the async put propagate sleep(250); - + final CountDownLatch readLatch = new CountDownLatch(1); final CountDownLatch commitLatch = new CountDownLatch(1); final CountDownLatch completionLatch = new CountDownLatch(2); - - Thread updater = new Thread() { - + + Thread updater = new Thread() { + public void run() { - - try { + + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp)); - + localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1)); - + readLatch.countDown(); commitLatch.await(); - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -512,22 +528,22 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } } }; - - Thread reader = new Thread() { - - public void run() { - try { + + Thread reader = new Thread() { + + public void run() { + try { long txTimestamp = System.currentTimeMillis(); BatchModeTransactionManager.getInstance().begin(); - + readLatch.await(); - + // This will block w/ pessimistic locking and then // read the new value; w/ optimistic it shouldn't // block and will read the old value - Object expected = isUsingOptimisticLocking() ? VALUE1 : VALUE2; + Object expected = !isBlockingReads() ? VALUE1 : VALUE2; assertEquals("Correct value", expected, localAccessStrategy.get(KEY, txTimestamp)); - + BatchModeTransactionManager.getInstance().commit(); } catch (Exception e) { @@ -542,28 +558,28 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac finally { commitLatch.countDown(); completionLatch.countDown(); - } + } } }; - + updater.setDaemon(true); reader.setDaemon(true); updater.start(); reader.start(); - - if (isUsingOptimisticLocking()) + + if (! isBlockingReads()) // Should complete promptly assertTrue(completionLatch.await(1, TimeUnit.SECONDS)); - else { + else { // Reader thread should be blocking assertFalse(completionLatch.await(250, TimeUnit.MILLISECONDS)); // Let the writer commit down commitLatch.countDown(); assertTrue(completionLatch.await(1, TimeUnit.SECONDS)); } - + assertThreadsRanCleanly(); - + long txTimestamp = System.currentTimeMillis(); assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp)); Object expected = isUsingInvalidation() ? null : VALUE2; @@ -586,7 +602,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac /** * Test method for {@link TransactionalAccess#evict(java.lang.Object)}. - * + * * FIXME add testing of the "immediately without regard for transaction * isolation" bit in the EntityRegionAccessStrategy API. */ @@ -596,7 +612,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac /** * Test method for {@link TransactionalAccess#evictAll()}. - * + * * FIXME add testing of the "immediately without regard for transaction * isolation" bit in the EntityRegionAccessStrategy API. */ @@ -605,43 +621,43 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac } private void evictOrRemoveTest(boolean evict) { - + final String KEY = KEY_BASE + testCount++; - + assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis())); assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis())); - + localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis())); remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); - + // Wait for async propagation sleep(250); - + if (evict) localAccessStrategy.evict(KEY); else localAccessStrategy.remove(KEY); - + assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis())); - + // sleep(1000); - + assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); } private void evictOrRemoveAllTest(boolean evict) { - + final String KEY = KEY_BASE + testCount++; - + Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX); - + Node regionRoot = localCache.getRoot().getChild(regionFqn); assertFalse(regionRoot == null); assertEquals(0, getValidChildrenCount(regionRoot)); assertTrue(regionRoot.isResident()); - + if (isUsingOptimisticLocking()) { assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass()); } @@ -650,41 +666,41 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac assertFalse(regionRoot == null); assertEquals(0, getValidChildrenCount(regionRoot)); assertTrue(regionRoot.isResident()); - + if (isUsingOptimisticLocking()) { assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass()); } - + assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis())); assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis())); - + localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis())); - + // Wait for async propagation sleep(250); - + remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); - + // Wait for async propagation sleep(250); - + if (isUsingOptimisticLocking()) { regionRoot = localCache.getRoot().getChild(regionFqn); assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass()); regionRoot = remoteCache.getRoot().getChild(regionFqn); assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass()); } - + if (evict) localAccessStrategy.evictAll(); else localAccessStrategy.removeAll(); - + // This should re-establish the region root node in the optimistic case assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis())); - + regionRoot = localCache.getRoot().getChild(regionFqn); if (isUsingOptimisticLocking()) { assertFalse(regionRoot == null); @@ -696,7 +712,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid()); } - // Re-establishing the region root on the local node doesn't + // Re-establishing the region root on the local node doesn't // propagate it to other nodes. Do a get on the remote node to re-establish assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); @@ -707,15 +723,15 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac assertTrue(regionRoot.isResident()); // Not invalidation, so we didn't insert a child above assertEquals(0, getValidChildrenCount(regionRoot)); - } + } else { assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid()); } - + // Test whether the get above messes up the optimistic version remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); - + // Revalidate the region root regionRoot = remoteCache.getRoot().getChild(regionFqn); assertFalse(regionRoot == null); @@ -723,14 +739,14 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac assertTrue(regionRoot.isResident()); // Region root should have 1 child -- the one we added above assertEquals(1, getValidChildrenCount(regionRoot)); - + // Wait for async propagation sleep(250); - + assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis())); assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); } - + private int getValidChildrenCount(Node node) { int result = 0; for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { @@ -738,9 +754,9 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac result++; } } - return result; + return result; } - + protected void rollback() { try { BatchModeTransactionManager.getInstance().rollback(); @@ -748,19 +764,25 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac catch (Exception e) { log.error(e.getMessage(), e); } - + } - + private static class AccessStrategyTestSetup extends TestSetup { - + private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack"; - - private String configName; + + private final String configResource; + private final String configName; private String preferIPv4Stack; - + public AccessStrategyTestSetup(Test test, String configName) { + this(test, configName, null); + } + + public AccessStrategyTestSetup(Test test, String configName, String configResource) { super(test); this.configName = configName; + this.configResource = configResource; } @Override @@ -771,39 +793,39 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac finally { if (preferIPv4Stack == null) System.clearProperty(PREFER_IPV4STACK); - else - System.setProperty(PREFER_IPV4STACK, preferIPv4Stack); + else + System.setProperty(PREFER_IPV4STACK, preferIPv4Stack); } - - // Try to ensure we use IPv4; otherwise cluster formation is very slow + + // Try to ensure we use IPv4; otherwise cluster formation is very slow preferIPv4Stack = System.getProperty(PREFER_IPV4STACK); System.setProperty(PREFER_IPV4STACK, "true"); - - localCfg = createConfiguration(configName); + + localCfg = createConfiguration(configName, configResource); localRegionFactory = CacheTestUtil.startRegionFactory(localCfg); localCache = localRegionFactory.getCacheInstanceManager().getEntityCacheInstance(); - - remoteCfg = createConfiguration(configName); + + remoteCfg = createConfiguration(configName, configResource); remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg); remoteCache = remoteRegionFactory.getCacheInstanceManager().getEntityCacheInstance(); - + invalidation = CacheHelper.isClusteredInvalidation(localCache); synchronous = CacheHelper.isSynchronous(localCache); optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC; } @Override - protected void tearDown() throws Exception { + protected void tearDown() throws Exception { super.tearDown(); - + if (localRegionFactory != null) localRegionFactory.stop(); - + if (remoteRegionFactory != null) remoteRegionFactory.stop(); } - - + + } } diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccInvalidatedTransactionalTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccInvalidatedTransactionalTestCase.java new file mode 100644 index 0000000000..84c5a79d89 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccInvalidatedTransactionalTestCase.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.entity; + +import org.hibernate.test.util.CacheTestUtil; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Tests TRANSACTIONAL access when MVCC locking and invalidation are used. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase { + + /** + * Create a new PessimisticTransactionalAccessTestCase. + * + * @param name + */ + public MvccInvalidatedTransactionalTestCase(String name) { + super(name); + } + + public static Test suite() throws Exception { + TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccInvalidatedTransactionalTestCase.class); + return getTestSetup(suite, "mvcc-entity"); + } + + // Known failures + + // Overrides + + @Override + public void testCacheConfiguration() { + assertTrue("Using Invalidation", isUsingInvalidation()); + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + assertTrue("Synchronous mode", isSynchronous()); + } + + @Override + public boolean isBlockingReads() { + return false; + } +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyExtraAPITestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyExtraAPITestCase.java new file mode 100644 index 0000000000..7a09044548 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyExtraAPITestCase.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.entity; + +import org.hibernate.cache.access.EntityRegionAccessStrategy; + +/** + * Tests for the "extra API" in EntityRegionAccessStrategy; in this + * version using pessimistic locking with READ_ONLY access. + *
+ * By "extra API" we mean those methods that are superfluous to the + * function of the JBC integration, where the impl is a no-op or a static + * false return value, UnsupportedOperationException, etc. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase { + + private static EntityRegionAccessStrategy localAccessStrategy; + + /** + * Create a new PessimisticAccessStrategyExtraAPITestCase. + * + * @param name + */ + public MvccReadOnlyExtraAPITestCase(String name) { + super(name); + } + + @Override + protected String getCacheConfigName() { + return "mvcc-entity"; + } + + @Override + protected EntityRegionAccessStrategy getEntityAccessStrategy() { + return localAccessStrategy; + } + + @Override + protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) { + localAccessStrategy = strategy; + } + + @Override + public void testCacheConfiguration() { + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + } +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyTestCase.java new file mode 100644 index 0000000000..c4c063f956 --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReadOnlyTestCase.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.entity; + +import org.hibernate.test.util.CacheTestUtil; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Tests READ_ONLY access when pessimistic locking and invalidation are used. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReadOnlyTestCase extends AbstractReadOnlyAccessTestCase { + + /** + * Create a new PessimisticTransactionalAccessTestCase. + * + * @param name + */ + public MvccReadOnlyTestCase(String name) { + super(name); + } + + public static Test suite() throws Exception { + TestSuite suite = CacheTestUtil.createFailureExpectedSuite(MvccReadOnlyTestCase.class); + return getTestSetup(suite, "mvcc-entity"); + } + + // Known failures + + // Overrides + + + @Override + public void testCacheConfiguration() { + assertTrue("Using Invalidation", isUsingInvalidation()); + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + } + + @Override + public boolean isBlockingReads() { + return false; + } +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReplicatedTransactionalTestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReplicatedTransactionalTestCase.java new file mode 100644 index 0000000000..8f4ce6448d --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccReplicatedTransactionalTestCase.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.entity; + +import junit.framework.Test; + +/** + * Tests TRANSACTIONAL access when pessimistic locking and replication are used. + * + * @author Brian Stansberry + * @version $Revision: 1 $ + */ +public class MvccReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase { + + /** + * Create a new PessimisticTransactionalAccessTestCase. + * + * @param name + */ + public MvccReplicatedTransactionalTestCase(String name) { + super(name); + } + + public static Test suite() throws Exception { + return getTestSetup(MvccReplicatedTransactionalTestCase.class, "mvcc-shared"); + } + + @Override + public void testCacheConfiguration() { + assertFalse("Using Invalidation", isUsingInvalidation()); + assertFalse("Using Optimistic locking", isUsingOptimisticLocking()); + assertTrue("Synchronous mode", isSynchronous()); + } + + @Override + public boolean isBlockingReads() { + return false; + } + + +} diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccTransactionalExtraAPITestCase.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccTransactionalExtraAPITestCase.java new file mode 100644 index 0000000000..fa80612e7a --- /dev/null +++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/MvccTransactionalExtraAPITestCase.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.jbc2.entity; + +import org.hibernate.cache.access.EntityRegionAccessStrategy; + +/** + * Tests for the "extra API" in EntityRegionAccessStrategy; in this base + * version using Optimistic locking with TRANSACTIONAL access. + *
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class MvccTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new PessimisticAccessStrategyExtraAPITestCase.
+ *
+ * @param name
+ */
+ public MvccTransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getCacheConfigName() {
+ return "mvcc-entity";
+ }
+
+ @Override
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCEntityReplicationTest.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCEntityReplicationTest.java
new file mode 100644
index 0000000000..1784077139
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCEntityReplicationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.jbc2.functional;
+
+
+/**
+ * Executes the superclass tests, but with Hibernate and JBoss Cache
+ * configured for optimistic locking.
+ *
+ * @author Brian Stansberry
+ */
+public class MVCCEntityReplicationTest extends PessimisticEntityReplicationTest
+{
+
+ public MVCCEntityReplicationTest(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ protected String getEntityCacheConfigName()
+ {
+ return "mvcc-shared";
+ }
+
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCJBossCacheTest.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCJBossCacheTest.java
new file mode 100644
index 0000000000..6408825ac8
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCJBossCacheTest.java
@@ -0,0 +1,64 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * Basic functional test of a pessimistic locking entity + query cache.
+ *
+ * @author Brian Stansberry
+ */
+public class MVCCJBossCacheTest extends AbstractQueryCacheFunctionalTestCase {
+
+ private static final String JBC_CONFIG = "org/hibernate/test/cache/jbc2/functional/mvcc-treecache.xml";
+
+ public MVCCJBossCacheTest(String x) {
+ super(x);
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(MVCCJBossCacheTest.class);
+ }
+
+ protected Class extends RegionFactory> getCacheRegionFactory() {
+ return JBossCacheRegionFactory.class;
+ }
+
+ /**
+ * Apply any region-factory specific configurations.
+ *
+ * @param the Configuration to update.
+ */
+ protected void configureCacheFactory(Configuration cfg) {
+ cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, JBC_CONFIG);
+ }
+
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCSessionRefreshTest.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCSessionRefreshTest.java
new file mode 100644
index 0000000000..9a7caeb287
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/MVCCSessionRefreshTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.test.cache.jbc2.functional.util.IsolatedCacheTestSetup;
+
+/**
+ * A SessionRefreshTest that uses an OPTIMISTIC cache config.
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class MVCCSessionRefreshTest extends PessimisticSessionRefreshTest
+{
+
+ private static final String CACHE_CONFIG = "mvcc-entity";
+
+ /**
+ * Create a new OptimisticSessionRefreshTest.
+ *
+ * @param x
+ */
+ public MVCCSessionRefreshTest(String x)
+ {
+ super(x);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = new TestSuite(MVCCSessionRefreshTest.class);
+ String[] acctClasses = { OUR_PACKAGE + ".Account", OUR_PACKAGE + ".AccountHolder" };
+ return new IsolatedCacheTestSetup(suite, acctClasses, CACHE_CONFIG);
+ }
+
+ @Override
+ protected String getEntityCacheConfigName() {
+ return CACHE_CONFIG;
+ }
+
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/MVCCBulkOperationsTest.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/MVCCBulkOperationsTest.java
new file mode 100644
index 0000000000..73bf52af39
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/MVCCBulkOperationsTest.java
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.hibernate.test.cache.jbc2.functional.bulk;
+
+import junit.framework.Test;
+
+import org.hibernate.test.cache.jbc2.collection.OptimisticInvalidatedTransactionalTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+
+
+/**
+ * Optimistic version of BulkOperationsUnitTestCase.
+ *
+ * @author Brian Stansberry
+ *
+ */
+public class MVCCBulkOperationsTest
+ extends PessimisticBulkOperationsTest
+{
+
+ public static Test suite() throws Exception {
+ return CacheTestUtil.createFailureExpectedSuite(MVCCBulkOperationsTest.class);
+ }
+
+ /**
+ * @param name
+ */
+ public MVCCBulkOperationsTest(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ protected String getEntityCacheConfigName()
+ {
+ return "mvcc-entity";
+ }
+
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/classloader/MVCCIsolatedClassLoaderTest.java b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/classloader/MVCCIsolatedClassLoaderTest.java
new file mode 100644
index 0000000000..67fc9f12ce
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/classloader/MVCCIsolatedClassLoaderTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.functional.classloader;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.test.cache.jbc2.functional.util.IsolatedCacheTestSetup;
+
+/**
+ * Optimistic locking version of IsolatedClassLoaderTest.
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class MVCCIsolatedClassLoaderTest extends PessimisticIsolatedClassLoaderTest
+{
+ private static final String CACHE_CONFIG = "mvcc-shared";
+
+ /**
+ * Create a new OptimisticIsolatedClassLoaderTest.
+ *
+ * @param name
+ */
+ public MVCCIsolatedClassLoaderTest(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = new TestSuite(MVCCIsolatedClassLoaderTest.class);
+ String[] acctClasses = { OUR_PACKAGE + ".Account", OUR_PACKAGE + ".AccountHolder" };
+ return new IsolatedCacheTestSetup(suite, acctClasses, CACHE_CONFIG);
+ }
+
+ protected String getEntityCacheConfigName() {
+ return CACHE_CONFIG;
+ }
+
+}
diff --git a/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/mvcc-treecache.xml b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/mvcc-treecache.xml
new file mode 100644
index 0000000000..002af9c5fc
--- /dev/null
+++ b/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/mvcc-treecache.xml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+