package org.jboss.cache.eviction;

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

import org.jboss.cache.Fqn;
import org.jboss.cache.Region;
import org.jboss.cache.RegionManager;
import org.jboss.cache.config.EvictionConfig;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
 * @author Ben Wang, Feb 11, 2004
 * @author Daniel Huang (dhuang@jboss.org)
 */
@Test(groups = {"functional"})
public class RegionTest
{
   RegionManager regionManager_;
   EvictionAlgorithm algorithm;

   @BeforeMethod(alwaysRun = true)
   public void setUp() throws Exception
   {
      algorithm = new LRUAlgorithm();
      regionManager_ = new RegionManager();
      regionManager_.getRegion("/a/b", true).setEvictionPolicy(new DummyEvictionConfiguration());
   }

   public void testAddedQueue()
   {
      Fqn fqn1 = Fqn.fromString("/a/b/c");
      Fqn fqn2 = Fqn.fromString("/a/b/d");
      Fqn fqn3 = Fqn.fromString("/a/b/e");

      Region region = regionManager_.getRegion("/a/b", true);
      region.putNodeEvent(new EvictedEventNode(fqn1, NodeEventType.ADD_NODE_EVENT));
      region.putNodeEvent(new EvictedEventNode(fqn2, NodeEventType.ADD_NODE_EVENT));
      region.putNodeEvent(new EvictedEventNode(fqn3, NodeEventType.ADD_NODE_EVENT));

      assertEquals("AddedNode queue size ", 3, region.nodeEventQueueSize());
      EvictedEventNode node = region.takeLastEventNode();
      Fqn fqn = node.getFqn();
      assertEquals("DataNode retrieved should be FILO ", fqn, fqn1);
      assertEquals("AddedNode queue size ", 2, region.nodeEventQueueSize());
      fqn = region.takeLastEventNode().getFqn();
      fqn = region.takeLastEventNode().getFqn();
      node = region.takeLastEventNode();
      assertNull("DataNode should be null", node);
   }

   public void testEventQueue()
   {
      Fqn fqn1 = Fqn.fromString("/a/b/c");
      Fqn fqn2 = Fqn.fromString("/a/b/d");
      Fqn fqn3 = Fqn.fromString("/a/b/e");

      Region region = regionManager_.getRegion("/a/b", true);
      region.putNodeEvent(new EvictedEventNode(fqn1, NodeEventType.REMOVE_NODE_EVENT));
      region.putNodeEvent(new EvictedEventNode(fqn2, NodeEventType.ADD_NODE_EVENT));
      region.putNodeEvent(new EvictedEventNode(fqn3, NodeEventType.VISIT_NODE_EVENT));

      assertEquals("RemovedNode queue size ", 3, region.nodeEventQueueSize());
      NodeEventType event = region.takeLastEventNode().getEventType();
      assertEquals("DataNode retrieved should be: ", NodeEventType.REMOVE_NODE_EVENT, event);
      region.takeLastEventNode();
      region.takeLastEventNode();
      EvictedEventNode node = region.takeLastEventNode();
      assertNull("DataNode should be null", node);
   }

   public void testMassivePutOnQueue()
   {
      Fqn fqn2 = Fqn.fromString("/a/b/d");

      Region region = regionManager_.getRegion("/a/b", true);
      // This should succeed, alhtough it will produce warning over the threshold.
      for (int i = 0; i < EvictionConfig.EVENT_QUEUE_SIZE_DEFAULT - 1; i++)
      {
         region.putNodeEvent(new EvictedEventNode(fqn2, NodeEventType.ADD_NODE_EVENT));
      }

   }

   void log(String msg)
   {
      System.out.println("-- " + msg);
   }

}
