/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.loader;

import org.jboss.cache.CacheException;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.XmlConfigurationParser;
import org.jboss.cache.xml.XmlHelper;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Element;

/**
 * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
 */
@Test(groups = {"functional"})
public class CacheLoaderPurgingTest extends AbstractCacheLoaderTestBase
{
   private CacheSPI<Object, Object> cache;
   private String key = "key", value = "value";
   private Fqn fqn = Fqn.fromString("/a/b/c");

   @AfterMethod(alwaysRun = true)
   public void tearDown() throws CacheException
   {
      if (cache != null)
      {
         cache.removeNode(Fqn.ROOT);
         cache.stop();
         cache = null;
      }
   }

   public void testSingleLoaderNoPurge() throws Exception
   {
      cache = (CacheSPI<Object, Object>) new DefaultCacheFactory().createCache(false);
      Configuration c = cache.getConfiguration();

      c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", DummySharedInMemoryCacheLoader.class.getName(), "", false, false, false));
      cache.start();

      cache.put(fqn, key, value);

      CacheLoader loader = cache.getCacheLoaderManager().getCacheLoader();

      assertEquals(value, cache.get(fqn, key));
      assertEquals(value, loader.get(fqn).get(key));

      cache.evict(fqn);
      cache.stop();
      assertEquals(value, loader.get(fqn).get(key));

      cache.start();
      assertEquals(value, cache.get(fqn, key));
      assertEquals(value, loader.get(fqn).get(key));
   }

   public void testSingleLoaderPurge() throws Exception
   {
      cache = (CacheSPI<Object, Object>) new DefaultCacheFactory<Object, Object>().createCache(false);
      Configuration c = cache.getConfiguration();
      c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", DummySharedInMemoryCacheLoader.class.getName(), "", false, false, false, true));
      cache.start();

      cache.put(fqn, key, value);

      CacheLoader loader = cache.getCacheLoaderManager().getCacheLoader();

      assertEquals(value, cache.get(fqn, key));
      assertEquals(value, loader.get(fqn).get(key));

      cache.evict(fqn);
      cache.stop();
      assertEquals(value, loader.get(fqn).get(key));

      cache.start();

      assertTrue(cache.getCacheLoaderManager().getCacheLoaderConfig().getFirstCacheLoaderConfig().isPurgeOnStartup());

      assertNull(cache.getNode(fqn));
      assertNull(loader.get(fqn));
   }

   public void testTwoLoadersPurge() throws Exception
   {
      cache = (CacheSPI<Object, Object>) new DefaultCacheFactory().createCache(false);

      String xml = "<config>\n" +
            "<passivation>false</passivation>\n" +
            "<preload></preload>\n" +
            "<cacheloader>\n" +
            "<class>" + DummySharedInMemoryCacheLoader.class.getName() + "</class>\n" +
            "<properties>" +
            " bin=bin1\n" +
            "</properties>\n" +
            "<async>false</async>\n" +
            "<fetchPersistentState>true</fetchPersistentState>\n" +
            "<purgeOnStartup>" + true + "</purgeOnStartup>\n" +
            "</cacheloader>\n" +
            "<cacheloader>\n" +
            "<class>" + DummySharedInMemoryCacheLoader.class.getName() + "</class>\n" +
            "<properties>" +
            " bin=bin2\n" +
            "</properties>\n" +
            "<async>false</async>\n" +
            "<fetchPersistentState>false</fetchPersistentState>\n" +
            "<purgeOnStartup>" + false + "</purgeOnStartup>\n" +
            "</cacheloader>\n" +
            "</config>";

      Configuration c = cache.getConfiguration();
      Element element = XmlHelper.stringToElement(xml);
      c.setCacheLoaderConfig(XmlConfigurationParser.parseCacheLoaderConfig(element));
      cache.start();

      cache.put(fqn, key, value);

      CacheLoader loader[] = ((ChainingCacheLoader) cache.getCacheLoaderManager().getCacheLoader()).getCacheLoaders().toArray(new CacheLoader[]{});

      assertEquals(value, cache.get(fqn, key));
      assertEquals(value, loader[0].get(fqn).get(key));
      assertEquals(value, loader[1].get(fqn).get(key));

      cache.evict(fqn);
      cache.stop();
      assertEquals(value, loader[0].get(fqn).get(key));
      assertEquals(value, loader[1].get(fqn).get(key));

      cache.start();
      assertTrue(!cache.exists(fqn));
      assertNull(loader[0].get(fqn));
      assertNotNull(loader[1].get(fqn));
      assertEquals(value, cache.get(fqn, key));
   }

}
