package org.jboss.cache.eviction;

import junit.framework.TestCase;
import org.jboss.cache.CacheException;
import org.jboss.cache.DummyTransactionManagerLookup;
import org.jboss.cache.Fqn;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;
import org.jboss.cache.interceptors.EvictionInterceptor;
import org.jboss.cache.misc.TestingUtil;

import javax.transaction.TransactionManager;
import java.util.List;
import java.util.Iterator;

/**
 * Tests the eviction and the possible lack of locking nodes.
 * The configuration is with an aggressive eviction policy, 100 objects 2 seconds interval.
 * <p/>
 * It is possible that the number needs to be changed a little, depending on the machine speed.
 *
 * @author fhenning
 */
public class OptimisticEvictionTest extends TestCase
{

    //Maximum number of runs 2^20
    private static final int NUMBER_OF_RUNS = (1 << 20);
    //Initial number of nodes
    private static final int NUMBER_NODES = 256;

    private Fqn region = Fqn.fromString("testingRegion");
    private TransactionManager txManager;
    private TreeCache cache;

    protected void setUp() throws Exception
    {
        super.setUp();

        txManager = new DummyTransactionManagerLookup().getTransactionManager();
        cache = new TreeCache();
        PropertyConfigurator config = new PropertyConfigurator();
        config.configure(this.cache, "META-INF/optimistic-eviction.xml");
        cache.startService();
    }

    protected void tearDown() throws Exception
    {
        if (cache != null)
        {
            cache.stopService();
            cache = null;
        }
        super.tearDown();
    }

    public void testEvictionError() throws CacheException
    {
        //Initialize the cache via a map
        for (int i = 0; i < NUMBER_NODES; i++)
        {
            cache.put(new Fqn(region, new Integer(i)), new Integer(i), new Integer(i));
        }

        for (int i = 0; i < NUMBER_OF_RUNS; i++)
        {
            try
            {
                txManager.begin();
                cache.get(region, new Integer(i % NUMBER_NODES));
                txManager.commit();
            }
            catch (Exception e)
            {
                fail("Exception caught after run: " + i + ". Cause was " + e.getCause());
            }
        }
    }

    public void testEvictionOccurence() throws Exception
    {
        cache.put("/timeBased/test", "key", "value");
        assertTrue(cache.exists("/timeBased/test"));

        // wait for it to be evicted.
        TestingUtil.sleepThread(3000);
        assertTrue(!cache.exists("/timeBased/test"));
    }

    public void testInterceptorChain() throws Exception
    {
        List interceptors = cache.getInterceptors();
        System.out.println(interceptors);
        Iterator i = interceptors.iterator();
        boolean found = false;

        while (i.hasNext())
        {
            Object o = i.next();
            if (o instanceof EvictionInterceptor)
            {
                found = true;
            }
        }

        assertTrue("Eviction interceptor should be in interceptor chain.", found);
    }

}
