/*
 *
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.test.cache.test.replicated;


import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;

/**
 * Unit test for replicated async TreeCache. Use locking and multiple threads to test
 * concurrent access to the tree.
 *
 * @version $Revision: 1.12 $
 */
public class AsyncUnitTestCase extends TestCase {
   TreeCache cache1, cache2;
   String props=null;

   public AsyncUnitTestCase(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);
      tree.createService();
      tree.startService();
      return tree;
   }

   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 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
         sleep(2000);
         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");
         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 testSyncRepl() throws Exception {
      Integer age;
      cache1.setCacheMode(TreeCache.REPL_SYNC);
      cache2.setCacheMode(TreeCache.REPL_SYNC);

      try {
         cache1.put("/a/b/c", "age", new Integer(38));

         // value on cache2 must be 38
         age=(Integer)cache2.get("/a/b/c", "age");
         log("attr \"age\" of \"/a/b/c\" on cache2=" + age);
         assertNotNull("\"age\" obtained from cache2 is null ", age);
         assertTrue("\"age\" must be 38", age.intValue() == 38);
      }
      catch(Exception e) {
         fail(e.toString());
      }
   }


   private void sleep(long timeout) {
      try {
         Thread.sleep(timeout);
      }
      catch(Throwable t) {
         ;
      }
   }

   void log(String msg) {
      System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
   }


   public static Test suite() {
      return new TestSuite(AsyncUnitTestCase.class);
   }

   public static void main(String[] args) {
      junit.textui.TestRunner.run(suite());
   }
}