/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.options.cachemodelocal;
import org.jboss.cache.CacheFactory;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.config.Configuration;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import java.util.HashMap;
import java.util.Map;
/**
* Tests the cache mode local override in various scenarios. To be subclassed to test REPL_SYNC, REPL_ASYNC, INVALIDATION_SYNC, INVALIDATION_ASYNC for Opt and Pess locking.
* <p/>
* Option.setCacheModeLocal() only applies to put() and remove() methods.
*
* @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
*/
@Test(groups = {"functional"})
public abstract class CacheModeLocalTestBase
{
// to be subclassed.
protected Configuration.CacheMode cacheMode;
protected String nodeLockingScheme;
/**
* set this to true if the implementing class plans to use an invalidating cache mode *
*/
protected boolean isInvalidation;
private CacheSPI<String, String> cache1;
private CacheSPI<String, String> cache2;
private Fqn fqn = Fqn.fromString("/a");
private String key = "key";
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception
{
// force a tear down if the test runner didn't run one before (happens in IDEA)
if (cache1 != null || cache2 != null)
tearDown();
CacheFactory<String, String> instance = new DefaultCacheFactory();
cache1 = (CacheSPI<String, String>) instance.createCache(false);
cache1.getConfiguration().setClusterName("test");
cache1.getConfiguration().setStateRetrievalTimeout(1000);
cache1.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
cache1.getConfiguration().setNodeLockingScheme(nodeLockingScheme);
cache1.getConfiguration().setCacheMode(cacheMode);
cache1.start();
cache2 = (CacheSPI<String, String>) instance.createCache(false);
cache2.getConfiguration().setClusterName("test");
cache2.getConfiguration().setStateRetrievalTimeout(1000);
cache2.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
cache2.getConfiguration().setNodeLockingScheme(nodeLockingScheme);
cache2.getConfiguration().setCacheMode(cacheMode);
cache2.start();
}
@AfterMethod(alwaysRun = true)
public void tearDown()
{
if (cache1 != null)
{
cache1.stop();
flushTxs(cache1.getTransactionManager());
cache1 = null;
}
if (cache2 != null)
{
cache2.stop();
flushTxs(cache2.getTransactionManager());
cache2 = null;
}
}
private void flushTxs(TransactionManager mgr)
{
if (mgr != null)
{
try
{
if (mgr.getTransaction() != null)
{
mgr.rollback();
}
}
catch (SystemException e)
{
// do nothing
}
}
}
public void testPutKeyValue() throws Exception
{
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.put(fqn, key, "value");
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should not
assertNull("Should be null", cache2.get(fqn, key));
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().reset();
cache1.put(fqn, key, "value");
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache2.put(fqn, key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
assertEquals("value", cache1.get(fqn, key));
cache2.getInvocationContext().getOptionOverrides().reset();
cache2.put(fqn, key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testPutKeyValueViaNodeAPI() throws Exception
{
Node node1 = cache1.getRoot().addChild(fqn);
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node1.put(key, "value");
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should not
assertNull("Should be null", cache2.get(fqn, key));
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().reset();
node1.put(key, "value");
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
Node node2 = cache2.getRoot().addChild(fqn);
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node2.put(key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
assertEquals("value", cache1.get(fqn, key));
cache2.getInvocationContext().getOptionOverrides().reset();
node2.put(key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testPutData() throws Exception
{
Map<String, String> map = new HashMap<String, String>();
map.put(key, "value");
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.put(fqn, map);
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should not
assertNull("Should be null", cache2.get(fqn, key));
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
cache1.put(fqn, map);
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
map.put(key, "value2");
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache2.put(fqn, map);
delay();
assertEquals("value2", cache2.get(fqn, key));
assertEquals("value", cache1.get(fqn, key));
cache2.getInvocationContext().getOptionOverrides().reset();
cache2.put(fqn, key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testPutDataViaNodeAPI() throws Exception
{
Map<String, String> map = new HashMap<String, String>();
map.put(key, "value");
Node node1 = cache1.getRoot().addChild(fqn);
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node1.putAll(map);
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should not
assertNull("Should be null", cache2.get(fqn, key));
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
node1.putAll(map);
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
Node node2 = cache2.getRoot().addChild(fqn);
map.put(key, "value2");
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node2.putAll(map);
delay();
assertEquals("value2", cache2.get(fqn, key));
assertEquals("value", cache1.get(fqn, key));
cache2.getInvocationContext().getOptionOverrides().reset();
node2.put(key, "value2");
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testRemoveNode() throws Exception
{
// put some stuff in the cache first
// make sure we cleanup thread local vars.
cache1.getInvocationContext().setOptionOverrides(null);
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.removeNode(fqn);
delay();
// should be removed in cache1
assertNull("should be null", cache1.get(fqn, key));
// Not in cache2
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// replace cache entries
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
cache1.removeNode(fqn);
delay();
// both should be null
assertNull("should be null", cache1.get(fqn, key));
assertNull("should be null", cache2.get(fqn, key));
}
public void testRemoveNodeViaNodeAPI() throws Exception
{
// put some stuff in the cache first
// make sure we cleanup thread local vars.
cache1.getInvocationContext().setOptionOverrides(null);
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.getRoot().removeChild(fqn);
delay();
// should be removed in cache1
assertNull("should be null", cache1.get(fqn, key));
// Not in cache2
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// replace cache entries
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
cache1.getRoot().removeChild(fqn);
delay();
// both should be null
assertNull("should be null", cache1.get(fqn, key));
assertNull("should be null", cache2.get(fqn, key));
}
public void testRemoveKey() throws Exception
{
// put some stuff in the cache first
cache1.getInvocationContext().setOptionOverrides(null);
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.remove(fqn, key);
delay();
// should be removed in cache1
assertNull("should be null", cache1.get(fqn, key));
// Not in cache2
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// replace cache entries
cache1.put(fqn, key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().reset();
cache1.remove(fqn, key);
delay();
// both should be null
assertNull("should be null", cache1.get(fqn, key));
assertNull("should be null", cache2.get(fqn, key));
}
public void testRemoveKeyViaNodeAPI() throws Exception
{
// put some stuff in the cache first
Node node1 = cache1.getRoot().addChild(fqn);
cache1.getInvocationContext().setOptionOverrides(null);
node1.put(key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node1.remove(key);
delay();
// should be removed in cache1
assertNull("should be null", cache1.get(fqn, key));
// Not in cache2
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// replace cache entries
node1.put(key, "value");
delay();
assertEquals("value", cache1.get(fqn, key));
if (isInvalidation)
{
assertNull("Should be null", cache2.get(fqn, key));
}
else
{
assertEquals("value", cache2.get(fqn, key));
}
// now try again with passing the default options
cache1.getInvocationContext().getOptionOverrides().reset();
node1.remove(key);
delay();
// both should be null
assertNull("should be null", cache1.get(fqn, key));
assertNull("should be null", cache2.get(fqn, key));
}
public void testTransactionalBehaviour() throws Exception
{
TransactionManager mgr = cache1.getTransactionManager();
mgr.begin();
cache1.getInvocationContext().getOptionOverrides().reset();
cache1.put(fqn, key, "value1");
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.put(fqn, key, "value2");
mgr.commit();
delay();
// cache1 should still have this
assertEquals("value2", cache1.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value1", cache2.get(fqn, key));
}
else
{
assertNull(cache2.get(fqn, key));
}
// now try again with passing the default options
mgr.begin();
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.put(fqn, key, "value3");
cache1.getInvocationContext().getOptionOverrides().reset();
cache1.put(fqn, key, "value");
mgr.commit();
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
mgr = cache2.getTransactionManager();
mgr.begin();
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
cache2.put(fqn, key, "value3");
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache2.put(fqn, key, "value2");
mgr.commit();
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value3", cache1.get(fqn, key));
}
else
{
assertNull(cache1.get(fqn, key));
}
mgr.begin();
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache2.put(fqn, key, "value2");
cache2.getInvocationContext().getOptionOverrides().reset();
cache2.put(fqn, key, "value2");
mgr.commit();
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testTransactionalBehaviourViaNodeAPI() throws Exception
{
Node node1 = cache1.getRoot().addChild(fqn);
TransactionManager mgr = cache1.getTransactionManager();
mgr.begin();
cache1.getInvocationContext().getOptionOverrides().reset();
node1.put(key, "value1");
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node1.put(key, "value2");
mgr.commit();
delay();
// cache1 should still have this
assertEquals("value2", cache1.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value1", cache2.get(fqn, key));
}
else
{
assertNull(cache2.get(fqn, key));
}
// now try again with passing the default options
mgr.begin();
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node1.put(key, "value3");
cache1.getInvocationContext().getOptionOverrides().reset();
node1.put(key, "value");
mgr.commit();
delay();
// cache1 should still have this
assertEquals("value", cache1.get(fqn, key));
// cache 2 should as well
if (!isInvalidation)
{
assertEquals("value", cache2.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache2.get(fqn, key));
}
// now cache2
Node node2 = cache2.getRoot().addChild(fqn);
mgr = cache2.getTransactionManager();
mgr.begin();
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
node2.put(key, "value3");
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node2.put(key, "value2");
mgr.commit();
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value3", cache1.get(fqn, key));
}
else
{
assertNull(cache1.get(fqn, key));
}
mgr.begin();
cache2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
node2.put(key, "value2");
cache2.getInvocationContext().getOptionOverrides().reset();
node2.put(key, "value2");
mgr.commit();
delay();
assertEquals("value2", cache2.get(fqn, key));
if (!isInvalidation)
{
assertEquals("value2", cache1.get(fqn, key));
}
else
{
assertNull("should be invalidated", cache1.get(fqn, key));
}
}
public void testAddChild() throws Exception
{
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.getRoot().addChild(fqn);
delay();
// cache1 should still have this
assertTrue(cache1.getRoot().hasChild(fqn));
// cache 2 should not
Node node2 = cache2.getRoot().getChild(fqn);
assertTrue("Should be null", node2 == null || (isInvalidation && !node2.isValid()));
// now try again with passing the default options
cache1.getRoot().removeChild(fqn);
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
cache1.getRoot().addChild(fqn);
delay();
// cache1 should still have this
assertTrue(cache1.getRoot().hasChild(fqn));
// cache 2 should as well
if (!isInvalidation)
{
assertTrue(cache2.getRoot().hasChild(fqn));
}
else
{
assertTrue("Should be null", node2 == null || !node2.isValid());
}
}
protected abstract void delay();
}