/*
*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.replicated;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.Assert;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCacheMBean;
import org.jboss.cache.misc.TestingUtil;
import javax.transaction.TransactionManager;
/**
* Unit test for replicated async TreeCache. Use locking and multiple threads to test
* concurrent access to the tree.
*
* @version $Revision: 2822 $
*/
public class AsyncReplTest extends TestCase {
TreeCache cache1, cache2;
String props=null;
public AsyncReplTest(String name) {
super(name);
}
public void setUp() throws Exception {
super.setUp();
log("creating cache1");
cache1=createCache("CacheGroup");
log("creating cache2");
cache2=createCache("CacheGroup");
}
private TreeCache createCache(String name) throws Exception {
TreeCache tree=new TreeCache();
PropertyConfigurator config=new PropertyConfigurator();
config.configure(tree, "META-INF/replAsync-service.xml"); // read in generic replAsync xml
tree.setClusterName(name);
// Call the hook that allows mux integration
configureMultiplexer(tree);
tree.createService();
tree.startService();
validateMultiplexer(tree);
return tree;
}
/**
* Provides a hook for multiplexer integration. This default implementation
* is a no-op; subclasses that test mux integration would override
* to integrate the given cache with a multiplexer.
*
* param cache a cache that has been configured but not yet created.
*/
protected void configureMultiplexer(TreeCacheMBean cache) throws Exception
{
// default does nothing
}
/**
* Provides a hook to check that the cache's channel came from the
* multiplexer, or not, as expected. This default impl asserts that
* the channel did not come from the multiplexer.
*
* @param cache a cache that has already been started
*/
protected void validateMultiplexer(TreeCacheMBean cache)
{
assertFalse("Cache is not using multiplexer", cache.isUsingMultiplexer());
}
public void tearDown() throws Exception {
super.tearDown();
if(cache1 != null) {
log("stopping cache1");
cache1.stopService();
}
if(cache2 != null) {
log("stopping cache2");
cache2.stopService();
}
}
public void testTxCompletion() throws Exception
{
// test a very simple replication.
Fqn fqn = Fqn.fromString("/a");
String key = "key";
cache1.put(fqn, key, "value1");
// allow for replication
TestingUtil.sleepThread((long)500);
Assert.assertEquals("value1", cache1.get(fqn, key));
Assert.assertEquals("value1", cache2.get(fqn, key));
TransactionManager mgr = cache1.getTransactionManager();
mgr.begin();
cache1.put(fqn, key, "value2");
Assert.assertEquals("value2", cache1.get(fqn, key));
Assert.assertEquals("value1", cache2.get(fqn, key));
mgr.commit();
TestingUtil.sleepThread((long)500);
Assert.assertEquals("value2", cache1.get(fqn, key));
Assert.assertEquals("value2", cache2.get(fqn, key));
mgr.begin();
cache1.put(fqn, key, "value3");
Assert.assertEquals("value3", cache1.get(fqn, key));
Assert.assertEquals("value2", cache2.get(fqn, key));
mgr.rollback();
TestingUtil.sleepThread((long)500);
Assert.assertEquals("value2", cache1.get(fqn, key));
Assert.assertEquals("value2", cache2.get(fqn, key));
if (cache1 != null)
{
cache1.stopService();
cache1 = null;
}
if (cache2 != null)
{
cache2.stopService();
cache2 = null;
}
}
public void testPutShouldNotReplicateToDifferentCluster() {
TreeCache cache3=null;
try {
cache3=createCache("DifferentGroup");
cache1.put("/a/b/c", "age", new Integer(38));
// because we use async repl, modfication may not yet have been propagated to cache2, so
// we have to wait a little
TestingUtil.sleepThread((long)1000);
assertNull("Should not have replicated", cache3.get("/a/b/c", "age"));
}
catch(Exception e) {
fail(e.toString());
}
finally {
if(cache3 != null)
cache3.stopService();
}
}
public void testStateTransfer() {
TreeCache cache4=null;
try {
cache1.put("a/b/c", "age", new Integer(38));
cache4=createCache("CacheGroup");
System.out.println("" + cache4.getMembers());
assertEquals(3, cache4.getMembers().size()); // cache1, cache2 and cache4
assertEquals("\"age\" should be 38", new Integer(38), cache4.get("/a/b/c", "age"));
}
catch(Exception e) {
fail(e.toString());
}
finally {
if(cache4 != null) {
System.out.println("cache4's view: " + cache4.getMembers());
cache4.stopService();
}
}
}
public void testAsyncReplDelay() {
Integer age;
try {
cache1.put("/a/b/c", "age", new Integer(38));
// value on cache2 may be 38 or not yet replicated
age=(Integer)cache2.get("/a/b/c", "age");
log("attr \"age\" of \"/a/b/c\" on cache2=" + age);
assertTrue("should be either null or 38", age == null || age.intValue() == 38);
}
catch(Exception e) {
fail(e.toString());
}
}
public void testAsyncReplTxDelay() {
Integer age;
try {
TransactionManager tm = cache1.getTransactionManager();
tm.begin();
cache1.put("/a/b/c", "age", new Integer(38));
tm.commit();
// value on cache2 may be 38 or not yet replicated
age=(Integer)cache2.get("/a/b/c", "age");
log("attr \"age\" of \"/a/b/c\" on cache2=" + age);
assertTrue("should be either null or 38", age == null || age.intValue() == 38);
}
catch(Exception e) {
fail(e.toString());
}
}
public void testSyncRepl() throws Exception {
Fqn fqn = Fqn.fromString("/JSESSIONID/1010.10.5:3000/1234567890/1");
Integer age;
cache1.setCacheMode(TreeCache.REPL_SYNC);
cache1.setSyncCommitPhase(true);
cache2.setCacheMode(TreeCache.REPL_SYNC);
cache2.setSyncCommitPhase(true);
try {
cache1.put(fqn, "age", new Integer(38));
// value on cache2 must be 38
age=(Integer)cache2.get(fqn, "age");
assertNotNull("\"age\" obtained from cache2 is null ", age);
assertTrue("\"age\" must be 38", age.intValue() == 38);
}
catch(Exception e) {
e.printStackTrace();
fail(e.toString());
}
}
public void testSyncReplSimple() throws Exception {
cache1.setCacheMode(TreeCache.REPL_SYNC);
cache1.setSyncCommitPhase(true);
cache2.setCacheMode(TreeCache.REPL_SYNC);
cache2.setSyncCommitPhase(true);
try {
cache1.put("/a", "x", "y");
assertEquals("y", cache2.get("/a", "x"));
}
catch(Exception e) {
fail(e.toString());
}
}
void log(String msg) {
System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
}
public static Test suite() {
return new TestSuite(AsyncReplTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
}