/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.cache.passivation;

import junit.framework.TestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jboss.cache.TreeCache;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.Fqn;
import org.jboss.cache.AbstractTreeCacheListener;
import org.jboss.cache.Node;
import org.jboss.cache.TreeCacheListener;
import org.jboss.cache.loader.DummyInMemoryCacheLoader;
import org.jboss.cache.loader.AbstractCacheLoaderTestBase;
import org.jboss.cache.eviction.*;
import org.jboss.cache.misc.TestingUtil;

/**
 *
 * @author Ben Wang
 * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
 * @version $Revision: 4089 $
 */
public class BasicPassivationTest extends AbstractCacheLoaderTestBase
{
   TreeCache cache_;
   int wakeupIntervalMillis_ = 0;
   final String ROOT_STR = "/test";
   Throwable t1_ex, t2_ex;
   final long DURATION = 10000;
   boolean isTrue;
   final String FQNSTR = "/org/jboss/3";
   int activationCount = 0;
   int passivationCount = 0;

   public BasicPassivationTest(String s)
   {
      super(s);
   }

   public void setUp() throws Exception
   {
      super.setUp();
      initCaches();
      wakeupIntervalMillis_ = cache_.getEvictionThreadWakeupIntervalSeconds() * 1000;
      log("wakeupInterval is " + wakeupIntervalMillis_);
      if (wakeupIntervalMillis_ < 0)
         fail("testEviction(): eviction thread wake up interval is illegal " + wakeupIntervalMillis_);

      t1_ex = t2_ex = null;
      isTrue = true;
   }

   void initCaches() throws Exception
   {
      cache_ = new TreeCache();
      PropertyConfigurator config = new PropertyConfigurator();
      config.configure(cache_, "META-INF/local-passivation-service.xml"); // read in generic local xml
      cache_.setCacheLoaderConfiguration(getSingleCacheLoaderConfig(true, "/", DummyInMemoryCacheLoader.class.getName(), null, false, true, false, false));
      cache_.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      TreeCacheListener listener = new TestCacheListener();
      cache_.addTreeCacheListener(listener);
      cache_.startService();
   }

   public void tearDown() throws Exception
   {
      super.tearDown();
      cache_.stopService();
   }

   public void testBasic()
   {
      activationCount = 0;
      passivationCount = 0;
      Fqn fqn = Fqn.fromString(FQNSTR);
      try
      {
         cache_.put(fqn, FQNSTR, FQNSTR);
      }
      catch (Exception e)
      {
         fail("Failed to insert data" + e);
         e.printStackTrace();
      }
      System.out.println(cache_.toString());
      TestingUtil.sleepThread(21000);
      System.out.println(cache_.toString());
      try
      {
         assertFalse(cache_.exists(FQNSTR, FQNSTR));
         String val = (String) cache_.get(FQNSTR, FQNSTR);
         assertNotNull("DataNode should not be empty ", val);
      }
      catch (Exception e)
      {
         e.printStackTrace();
         fail("Failed to get" + e);
      }

      assertEquals("activation count:", 1, activationCount);
      assertEquals("passivation count:", 1, passivationCount);
   }
   
   public void testDualPassivation() throws Exception
   {
      Fqn fqn = Fqn.fromString(FQNSTR);
      cache_.put(fqn, "key", "value");
      cache_.evict(fqn);
      cache_.evict(fqn);
      assertEquals("Proper value after 2 passivations", "value", cache_.get(fqn, "key"));
   }
   
   public void testIntermingledPassivation() throws Exception
   {
      Fqn fqn = Fqn.fromString(FQNSTR);
      cache_.put(fqn, "key1", "value");
      cache_.evict(fqn);
      cache_.put(fqn, "key2", "value");
      cache_.evict(fqn);
      assertEquals("Proper value after 2 passivations", "value", cache_.get(fqn, "key1"));
      
   }

   void log(String msg)
   {
      System.out.println("-- " + msg);
   }

   public static Test suite()
   {
      return new TestSuite(org.jboss.cache.passivation.BasicPassivationTest.class);
   }

   public static void main(String[] args)
   {
      junit.textui.TestRunner.run(org.jboss.cache.passivation.BasicPassivationTest.suite());
   }

   public class TestCacheListener extends AbstractTreeCacheListener
   {
      public void nodeActivate(Fqn fqn, boolean pre) {
         if(pre) return;  // we are not interested in postActivate event
         if(!fqn.isChildOrEquals(Fqn.fromString(FQNSTR))) return;  // don't care about fqn that doesn't belong to me.

         log("nodeActivate(): send postActivate event on fqn: " +fqn);
         activationCount++;
      }

      public void nodePassivate(Fqn fqn, boolean pre) {
         if(!pre) return;  // we are not interested in postPassivate event
         if(!fqn.isChildOrEquals(Fqn.fromString(FQNSTR))) return;  // don't care about fqn that doesn't belong to me.

         log("nodePassivate(): send prePassivate event on fqn: " +fqn);
         passivationCount++;
      }
   }
}
