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

package org.jboss.cache.eviction;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jboss.cache.Fqn;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;

import java.io.File;

/**
 * Tests cache behavior in the presence of concurrent passivation.
 *
 * @author Brian Stansberry
 * @version $Revision: 2796 $
 */
public class ConcurrentEvictionTest extends TestCase
{
   private TreeCache cache_;
   private int wakeupIntervalMillis_ = 0;

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

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

   }

   void initCaches() throws Exception
   {
      removeStaleFiles();
      cache_ = new TreeCache();
      PropertyConfigurator config = new PropertyConfigurator();
      config.configure(cache_, "META-INF/local-eviction-cacheloader-service.xml"); // read in generic local xml
      cache_.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      cache_.startService();
   }

   public void tearDown() throws Exception
   {
      super.tearDown();
      removeStaleFiles();
      cache_.stop();
      cache_ = null;
   }

   private void removeStaleFiles()
   {
      File file = new File("/tmp/JBossCacheFileCacheLoader");
      if (file.exists())
      {
         System.out.println("Deleting file " + file);
         //file.deleteOnExit();
         //System.out.println(file.delete());
         recursivedelete(file);
      }
   }

   private void recursivedelete(File f)
   {
      if (f.isDirectory())
      {
         File[] files = f.listFiles();
         for (int i = 0; i < files.length; i++)
         {
            recursivedelete(files[i]);
         }
      }
      //System.out.println("File " + f.toURI() + " deleted = " + f.delete());
      f.delete();
   }

   public void testConcurrentEviction() throws Exception
   {
      Fqn base = Fqn.fromString("/org/jboss/test/data/concurrent/eviction");

      // Create a bunch of nodes; more than the /org/jboss/test/data
      // region's maxNodes so we know eviction will kick in
      for (int i = 0; i < 1000; i++)
      {
         cache_.put(new Fqn(base, new Integer(i / 100)), new Integer(i), "value");
      }

      // Loop for long enough to have 5 runs of the eviction thread
      long loopDone = System.currentTimeMillis() + (5 * wakeupIntervalMillis_);
      while (System.currentTimeMillis() < loopDone)
      {
         // If any get returns null, that's a failure
         for (int i = 0; i < 1000; i++)
         {
            Fqn fqn = new Fqn(base, new Integer(i / 100));
            Integer key = new Integer(i);
            assertNotNull("found value under Fqn " + fqn + " and key " + key,
                    cache_.get(fqn, key));
         }
      }
   }

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