package org.jboss.cache.aop.loader;

import junit.framework.Test;
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;

import javax.transaction.Transaction;

/**
 * Commons tests for all CacheLoaders. Aop version.
 *
 * @author bwang
 * @version $Id: CacheLoaderTestsBase.java,v 1.9 2006/04/09 12:33:49 bwang Exp $
 */
abstract public class CacheLoaderTestsBase extends AbstractCacheLoaderTestBase {
   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 testEviction() 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 testPojoEviction() 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);
      // This will use both original the new pojo to get.
      assertEquals(test.getName(), val.getName());
      assertTrue(cache.exists("/first/second/third"));
      assertTrue(cache.exists("/first/second"));
      assertTrue(cache.exists("/first"));
   }

   public void testPojoRemove() 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);
   }

   /**
    * This test illustrates the problem in JBCACHE-477. That is transactional remove under
    * cacheloader using pessimistic locking.
    */
   public void testTxCollectionRemove() throws Exception {
      /*
      Person joe = new Person();
      joe.setName("Joe");
      joe.setAge(10);
      Person ben = new Person();
      ben.setName("Ben");
      ben.setAge(10);

      ArrayList list =new ArrayList();
      list.add(joe);
      list.add(ben);

      cache.putObject("/list", list);   // stored in cache loader
      list = (ArrayList)cache.getObject("/list");

      DummyTransactionManager mgr=DummyTransactionManager.getInstance();
      try {
         mgr.begin();
         tx=mgr.getTransaction();
         list.remove(joe);
      } catch (Exception ex)
      {
        fail("This is currently a known problem (JBCACHE-477) that we need to fix.");
      } finally
      {
         tx.commit();
      }
      */
      // do nothing: override the test which fails.
      // see JBCACHE-477
   }

   public void testCollection() throws Exception
   {
      /*
      Map map = new HashMap();
      map.put("1", "1");
      map.put("2", "2");

      cache.putObject("/test/map", map);
      map = (Map)cache.getObject("/test/map");
      map.put("3", "3");
      assertEquals("Map size ", 3, map.size());

      cache.evict(Fqn.fromString("/test/map"));
      addDelay();
      map = (Map)cache.getObject("/test/map");
      assertEquals("Map 1", "1", map.get("1"));
      assertEquals("Map 2", "2", map.get("2"));
//      assertEquals("Map 3", "3", map.get("3"));
      assertEquals("Known Failure - see JBCACHE-479 - Map size is not correct now. This is a known bug because of cacheloader does not load children that should be fixed in 1.3. ", 3, map.size());
      */

      // do nothing; override the test which fails.
      // See JBCACHE-479

   }

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

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

}
