package org.jboss.cache.eviction;

import org.jboss.cache.Cache;
import org.jboss.cache.CacheFactory;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.EvictionConfig;
import org.jboss.cache.config.EvictionRegionConfig;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;
import static org.testng.AssertJUnit.*;

@Test(groups = {"functional"}, testName = "eviction.LongTransactionEvictionsTest")
public class LongTransactionEvictionsTest
{
   public void testFIFOAlgoWithLongTx() throws Exception
   {
      // Create the cache
      CacheFactory<String, Object> factory = new DefaultCacheFactory<String, Object>();
      final Cache<String, Object> cache = factory.createCache(false);

      // Configure the Eviction
      EvictionConfig evictionConfig = new EvictionConfig();
      cache.getConfiguration().setEvictionConfig(evictionConfig);

      // Set the LRUAlgorithm as eviction algorithm
      int maxNodes = 1;
      long timeout = 4000;
      FIFOAlgorithmConfig fifo = new FIFOAlgorithmConfig(maxNodes);
      fifo.setMinTimeToLive(timeout);
      EvictionRegionConfig erConfig = new EvictionRegionConfig(Fqn.ROOT, fifo);
      evictionConfig.setDefaultEvictionRegionConfig(erConfig);

      // Set the wakeup interval
      long wakeupInterval = 1000;
      evictionConfig.setWakeupInterval(wakeupInterval);

      cache.getConfiguration().setInvocationBatchingEnabled(true);

      // Start the cache
      cache.start();
      cache.startBatch();
      cache.put(Fqn.fromElements("a"), "a", "value");
      // Add a pause before committing
      long pause = wakeupInterval + 1000;
      Thread.sleep(pause);

      cache.endBatch(true);
      AssertJUnit.assertEquals(1, ((CacheSPI<String, Object>)cache).getNumberOfNodes());
      cache.startBatch();
      cache.put(Fqn.fromElements("b"), "b", "value");

      // Add a pause before committing
      pause = wakeupInterval + 1000;
      assertEquals(1, ((CacheSPI<String, Object>)cache).getNumberOfNodes());
      Thread.sleep(pause);

      cache.endBatch(true);
      assertEquals(2, ((CacheSPI<String, Object>)cache).getNumberOfNodes());

      Thread.sleep(timeout + pause);

      // We expect to have 1 entry into the cache there
      assertEquals(1, ((CacheSPI<String, Object>)cache).getNumberOfNodes());
   }

   public void testLRUAlgoWithLongTx() throws Exception
   {
      // Create the cache
      CacheFactory<String, Object> factory = new DefaultCacheFactory<String, Object>();
      final Cache<String, Object> cache = factory.createCache(false);

      // Configure the Eviction
      EvictionConfig evictionConfig = new EvictionConfig();
      cache.getConfiguration().setEvictionConfig(evictionConfig);

      // Set the LRUAlgorithm as eviction algorithm
      int maxNodes = 5;
      long timeout = 4000;
      LRUAlgorithmConfig lru = new LRUAlgorithmConfig(1000, timeout, maxNodes);
      EvictionRegionConfig erConfig = new EvictionRegionConfig(Fqn.ROOT, lru);
      evictionConfig.setDefaultEvictionRegionConfig(erConfig);

      // Set the wakeup interval
      long wakeupInterval = 1000;
      evictionConfig.setWakeupInterval(wakeupInterval);

      cache.getConfiguration().setInvocationBatchingEnabled(true);

      // Start the cache
      cache.start();

      cache.startBatch();
      Fqn<String> fqn = Fqn.fromElements("key");
      cache.put(fqn, "key", "value");

      // Add a pause before committing
      long pause = wakeupInterval + 1000;
      Thread.sleep(pause);

      cache.endBatch(true);

      Thread.sleep(timeout + pause);

      // We expect to have an empty cache there
      assertEquals(0, ((CacheSPI<String, Object>)cache).getNumberOfNodes());
   }

   public void testExpAlgoWithLongTx() throws Exception
   {
      // Create the cache
      CacheFactory<String, Object> factory = new DefaultCacheFactory<String, Object>();
      final Cache<String, Object> cache = factory.createCache(false);

      // Configure the Eviction
      EvictionConfig evictionConfig = new EvictionConfig();
      cache.getConfiguration().setEvictionConfig(evictionConfig);

      // Set the ExpirationAlgorithm as eviction algorithm
      int maxNodes = 5;
      ExpirationAlgorithmConfig ea = new ExpirationAlgorithmConfig();
      ea.setMaxNodes(maxNodes);
      EvictionRegionConfig erConfig = new EvictionRegionConfig(Fqn.ROOT, ea);
      evictionConfig.setDefaultEvictionRegionConfig(erConfig);

      // Set the wakeup interval
      long wakeupInterval = 1000;
      evictionConfig.setWakeupInterval(wakeupInterval);

      cache.getConfiguration().setInvocationBatchingEnabled(true);

      // Start the cache
      cache.start();

      cache.startBatch();
      long timeout = 4000;
      Fqn<String> fqn = Fqn.fromElements("key");
      Long future = new Long(System.currentTimeMillis() + timeout);
      cache.put(fqn, ExpirationAlgorithmConfig.EXPIRATION_KEY, future);

      // Add a pause before committing
      long pause = wakeupInterval + 1000;
      Thread.sleep(pause);

      cache.endBatch(true);

      Thread.sleep(timeout + pause);

      // We expect to have an empty cache there
      assertEquals(0, ((CacheSPI<String, Object>)cache).getNumberOfNodes());
   }
}