/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.eviction;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;

import java.util.Iterator;

import org.jboss.cache.Fqn;
import org.jboss.cache.Region;
import org.jboss.cache.RegionManager;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
 * Unit tests for FIFOAlgorithm.
 *
 * @author Daniel Huang (dhuang@jboss.org)
 * @version $Revision: 4444 $
 */
@Test(groups = {"functional"})
public class FIFOAlgorithmTest
{

   RegionManager regionManager;
   FIFOAlgorithm algo;

   @BeforeMethod(alwaysRun = true)
   public void setUp() throws Exception
   {
      algo = new FIFOAlgorithm();
      FIFOConfiguration config = new FIFOConfiguration();
      // We have to setCache maxNodes!!
      config.setMaxNodes(0);
      regionManager = new RegionManager();
      config.setEvictionPolicyClass(DummyEvictionPolicy.class.getName());
      regionManager.getRegion("/a/b", true).setEvictionPolicy(config);
   }

   public void testMaxNodes1() throws Exception
   {
      Region region = regionManager.getRegion("/a/b", true);
      FIFOConfiguration config = (FIFOConfiguration) region.getEvictionPolicyConfig();
      config.setMaxNodes(5);

      for (int i = 0; i < 8; i++)
      {
         Fqn fqn = Fqn.fromString("/a/b/" + Integer.toString(i));
         region.putNodeEvent(new EvictedEventNode(fqn, NodeEventType.ADD_NODE_EVENT));
      }

      algo.process(region);
      FIFOQueue queue = (FIFOQueue) algo.evictionQueue;
      assertEquals(5, algo.getEvictionQueue().getNumberOfNodes());

      // now verify the order.
      Iterator it = queue.iterate();
      int index = 3;
      while (it.hasNext())
      {
         NodeEntry ne = (NodeEntry) it.next();
         String fqn = ne.getFqn().toString();
         assertTrue(fqn.endsWith("/" + Integer.toString(index)));
         index++;
      }

      // now verify the same order still exists after visiting the nodes.
      for (int i = 3; i < 8; i++)
      {
         Fqn fqn = Fqn.fromString("/a/b/" + Integer.toString(i));
         region.putNodeEvent(new EvictedEventNode(fqn, NodeEventType.VISIT_NODE_EVENT));
      }
      for (int i = 3; i < 5; i++)
      {
         Fqn fqn = Fqn.fromString("/a/b/" + Integer.toString(i));
         region.putNodeEvent(new EvictedEventNode(fqn, NodeEventType.VISIT_NODE_EVENT));
      }

      algo.process(region);

      assertEquals(5, algo.getEvictionQueue().getNumberOfNodes());

      it = queue.iterate();
      index = 3;
      while (it.hasNext())
      {
         NodeEntry ne = (NodeEntry) it.next();
         String fqn = ne.getFqn().toString();
         assertTrue(fqn.endsWith("/" + Integer.toString(index)));
         index++;
      }
   }

   public void testMaxNodes2() throws Exception
   {
      Region region = regionManager.getRegion("/a/b", true);
      FIFOConfiguration config = (FIFOConfiguration) region.getEvictionPolicyConfig();
      config.setMaxNodes(50000);

      for (int i = 0; i < 50000; i++)
      {
         Fqn fqn = Fqn.fromString("/a/b/" + Integer.toString(i));
         region.putNodeEvent(new EvictedEventNode(fqn, NodeEventType.ADD_NODE_EVENT));
      }

      algo.process(region);
      FIFOQueue queue = (FIFOQueue) algo.evictionQueue;
      assertEquals(50000, algo.getEvictionQueue().getNumberOfNodes());

      Iterator it = queue.iterate();
      int index = 0;
      while (it.hasNext())
      {
         NodeEntry ne = (NodeEntry) it.next();
         assertTrue(ne.getFqn().toString().endsWith("/" + Integer.toString(index)));
         index++;
      }

      for (int i = 50000; i < 60000; i++)
      {
         Fqn fqn = Fqn.fromString("/a/b/" + Integer.toString(i));
         region.putNodeEvent(new EvictedEventNode(fqn, NodeEventType.ADD_NODE_EVENT));
      }

      algo.process(region);

      it = queue.iterate();
      index = 10000;
      while (it.hasNext())
      {
         NodeEntry ne = (NodeEntry) it.next();
         assertTrue(ne.getFqn().toString().endsWith("/" + Integer.toString(index)));
         index++;
      }
   }
}
