Author: bstansberry(a)jboss.com
Date: 2007-09-17 23:25:32 -0400 (Mon, 17 Sep 2007)
New Revision: 4480
Added:
core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
Log:
[JBCACHE-1175] Option to force call sync/async
Added: core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
(rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java 2007-09-18
03:25:32 UTC (rev 4480)
@@ -0,0 +1,489 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+package org.jboss.cache.options;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.concurrent.CountDownLatch;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.misc.TestingUtil;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeEvicted;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.event.NodeEvent;
+import org.jboss.cache.notifications.event.NodeEvictedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests functionality of {@link Option#setForceAsynchronous(boolean)} and
+ * {@link Option#setForceSynchronous(boolean)}.
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani
(manik(a)jboss.org)</a>
+ */
+@Test(groups = {"functional"})
+public class ForceCacheModeTest
+{
+ private static final Log log = LogFactory.getLog(ForceCacheModeTest.class);
+
+ private static final Fqn FQNA = Fqn.fromString("/A");
+ private static final String KEY = "key";
+ private static final String VALUE1 = "value1";
+ private static final String VALUE2 = "value2";
+
+ private CacheImpl<Object, Object> cache1, cache2;
+ private Option asyncOption;
+ private Option syncOption;
+ private static CountDownLatch latch;
+ private BlockingListener listener;
+
+ private void createCaches(NodeLockingScheme scheme, CacheMode mode) throws Exception
+ {
+ cache1 = (CacheImpl<Object,
Object>)DefaultCacheFactory.getInstance().createCache(false);
+ Configuration c = new Configuration();
+ cache1.setConfiguration(c);
+ c.setNodeLockingScheme(scheme);
+ c.setCacheMode(mode);
+
c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+
+ cache2 = (CacheImpl<Object,
Object>)DefaultCacheFactory.getInstance().createCache(false);
+ c = new Configuration();
+ cache2.setConfiguration(c);
+ c.setNodeLockingScheme(scheme);
+ c.setCacheMode(mode);
+
c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+
+ cache1.start();
+ cache2.start();
+
+ asyncOption = new Option();
+ asyncOption.setForceAsynchronous(true);
+
+ syncOption = new Option();
+ syncOption.setForceSynchronous(true);
+
+ Option local = new Option();
+ local.setCacheModeLocal(true);
+
+ cache1.getInvocationContext().setOptionOverrides(local);
+ cache1.put(FQNA, KEY, VALUE1);
+
+ cache2.getInvocationContext().setOptionOverrides(local);
+ cache2.put(FQNA, KEY, VALUE1);
+
+ listener = new BlockingListener();
+ cache2.addCacheListener(listener);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ latch = new CountDownLatch(1);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ if (cache1 != null)
+ {
+ cache1.stop();
+ cache1.destroy();
+ cache1 = null;
+ }
+
+ if (cache2 != null)
+ {
+ if (listener != null)
+ cache2.removeCacheListener(listener);
+ cache2.stop();
+ cache2.destroy();
+ cache2 = null;
+ }
+
+ latch.countDown();
+ }
+
+ public void testPessimisticReplicationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testPessimisticReplicationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testPessimisticReplicationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testPessimisticInvalidationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testPessimisticInvalidationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testPessimisticInvalidationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testPessimisticReplicationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testPessimisticReplicationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testPessimisticReplicationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testPessimisticInvalidationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testPessimisticInvalidationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testPessimisticInvalidationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testOptimisticReplicationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testOptimisticReplicationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testOptimisticReplicationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testOptimisticInvalidationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testOptimisticInvalidationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testOptimisticInvalidationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testOptimisticReplicationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testOptimisticReplicationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testOptimisticReplicationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testOptimisticInvalidationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testOptimisticInvalidationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testOptimisticInvalidationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ /**
+ * Confirms the updater is not blocked and that the cache state is as
+ * expected at the end.
+ *
+ * @param tm transction manager Updater should use. For non-transactional
+ * tests, should be <code>null</code>
+ * @param option Option to set before doing put
+ * @param removeTest true if we're testing a remove; false if a put
+ * @throws InterruptedException
+ * @throws CacheException
+ */
+ private void checkNoBlocking(TransactionManager tm, Option option, boolean removeTest)
throws InterruptedException, CacheException
+ {
+ Updater updater = new Updater(tm, option, removeTest);
+ updater.start();
+
+ updater.join(250);
+ assertTrue("Updater finished", updater.finished);
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertTrue("Listener blocked", listener.blocked);
+ assertEquals("Cache1 correct", removeTest ? null : VALUE2,
cache1.get(FQNA, KEY));
+
+ latch.countDown();
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (!listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ // sleep a bit more to ensure the cache2 thread completes
+ TestingUtil.sleepThread(5);
+ CacheMode mode = cache2.getConfiguration().getCacheMode();
+ boolean expectNull = (removeTest || mode == CacheMode.INVALIDATION_ASYNC || mode ==
CacheMode.INVALIDATION_SYNC);
+ assertEquals("Cache2 correct", expectNull ? null : VALUE2,
cache2.get(FQNA, KEY));
+ }
+
+ /**
+ * Confirms the updater is blocked and that the cache state is as
+ * expected at the end.
+ *
+ * @param tm transction manager Updater should use. For non-transactional
+ * tests, should be <code>null</code>
+ * @param option Option to set before doing put
+ * @param removeTest true if we're testing a remove; false if a put
+ * @throws InterruptedException
+ * @throws CacheException
+ */
+ private void checkBlocking(TransactionManager tm, Option option, boolean removeTest)
throws InterruptedException, CacheException
+ {
+ Updater updater = new Updater(tm, option, removeTest);
+ updater.start();
+
+ updater.join(250);
+ assertFalse("Updater blocked", updater.finished);
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertTrue("Listener blocked", listener.blocked);
+
+ latch.countDown();
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (updater.finished && !listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertEquals("Cache1 correct", removeTest ? null : VALUE2,
cache1.get(FQNA, KEY));
+
+ // sleep a bit more to ensure the cache2 thread completes
+ TestingUtil.sleepThread(5);
+ CacheMode mode = cache2.getConfiguration().getCacheMode();
+ boolean expectNull = (removeTest || mode == CacheMode.INVALIDATION_ASYNC || mode ==
CacheMode.INVALIDATION_SYNC);
+ assertEquals("Cache2 correct", expectNull ? null : VALUE2,
cache2.get(FQNA, KEY));
+ }
+
+ class Updater extends Thread
+ {
+ TransactionManager tm;
+ Option option;
+ boolean remove;
+ Throwable failure;
+ boolean finished;
+
+ Updater(TransactionManager tm, Option option)
+ {
+ this(tm, option, false);
+ }
+
+ Updater(TransactionManager tm, Option option, boolean remove)
+ {
+ this.tm = tm;
+ this.option = option;
+ this.remove = remove;
+ }
+
+ public void run()
+ {
+ try
+ {
+ Transaction tx = null;
+
+ try
+ {
+ if (tm != null)
+ {
+ tm.begin();
+ tx = tm.getTransaction();
+ }
+
+ cache1.getInvocationContext().setOptionOverrides(option);
+ if (remove)
+ cache1.remove(FQNA, KEY);
+ else
+ cache1.put(FQNA, KEY, VALUE2);
+ }
+ catch (Exception e)
+ {
+ if (tx != null)
+ tx.setRollbackOnly();
+ throw e;
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ tx.commit();
+ }
+ finished = true;
+ }
+ }
+ catch (Throwable t)
+ {
+ failure = t;
+ }
+ }
+ }
+
+ @CacheListener
+ public static class BlockingListener
+ {
+ boolean blocked;
+
+ @NodeModified
+ public void nodeModified(NodeModifiedEvent event)
+ {
+ block(event);
+ }
+
+ @NodeRemoved
+ public void nodeRemoved(NodeRemovedEvent event)
+ {
+ block(event);
+ }
+
+ @NodeEvicted
+ public void nodeEvicted(NodeEvictedEvent event)
+ {
+ block(event);
+ }
+
+ private void block(NodeEvent event)
+ {
+ if (event.isPre() == false && FQNA.equals(event.getFqn()))
+ {
+ blocked = true;
+ try
+ {
+ latch.await();
+ }
+ catch (InterruptedException e) {}
+
+ blocked = false;
+ }
+ }
+ }
+
+}
Property changes on:
core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native