package org.jboss.cache.aop;

import javax.transaction.Transaction;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import org.jboss.cache.aop.test.Person;
import org.jboss.cache.loader.CacheLoader;

/**
 * Commons tests for all CacheLoaders. Aop version.
 *
 * @author bwang
 * @version $Id: CacheLoaderTestsBase.java,v 1.4 2006/04/09 12:33:49 bwang Exp $
 */
abstract public class CacheLoaderTestsBase extends TestCase {
   PojoCache cache;
   CacheLoader loader = null;
   Transaction tx = null;
   static final Fqn FQN = new Fqn("key");

   protected void setUp() throws Exception {
      super.setUp();
      cache = new PojoCache();
      cache.setCacheMode("local");
      configureCache();
      cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      cache.createService();
      cache.startService();
      loader = cache.getCacheLoader();
   }

   abstract protected void configureCache() throws Exception;

   protected void tearDown() throws Exception {
      super.tearDown();
      if (tx != null) {
         try {
            tx.commit();
         } catch (Throwable e) {
            e.printStackTrace();
         }
      }
      cache.remove("/");
      loader.remove(Fqn.fromString("/"));
      cache.stopService();
      cache.destroyService();
   }

   protected void addDelay() {
      ; // returns immediately in this case.  Subclasses may override where a delay is needed.
   }

   public void testEvictionWithCacheLoader() throws Exception {
      cache.putObject("/first/second/third", "val1");   // stored in cache loader
      cache.evict(Fqn.fromString("/first/second/third"));  // removes node, because there are no children
      addDelay();
      assertFalse(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
      String val = (String) cache.getObject("/first/second/third"); // should be loaded from cache loader
      assertEquals("val1", val);
      assertTrue(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
   }


   public void testPojoEvictionWithCacheLoader() throws Exception {
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache.putObject("/first/second/third", test);   // stored in cache loader
      cache.evict(Fqn.fromString("/first/second/third"));  // removes node, because there are no children
      addDelay();
      assertFalse(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
      Person val = (Person) cache.getObject("/first/second/third"); // should be loaded from cache loader
      assertNotNull(val);
      assertEquals(test.getName(), val.getName());
      assertTrue(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
   }

   public void testPojoRemoveWithCacheLoader() throws Exception {
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache.putObject("/first/second/third", test);   // stored in cache loader
      cache.remove(Fqn.fromString("/first/second/third"));  // removes node, because there are no children
      addDelay();
      assertFalse(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
      Person val = (Person) cache.getObject("/first/second/third"); // should be loaded from cache loader
      assertNull(val);
   }

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

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

}
