package org.jboss.cache.transaction;

import org.jboss.cache.CacheFactory;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.lock.IsolationLevel;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;

/**
 * Tests whether modifications within callbacks (TreeCacheListener) are handled correctly
 *
 * @author Bela Ban
 * @version $Id: IsolationLevelNoneTest.java 4880 2007-12-19 15:14:43Z manik.surtani@jboss.com $
 */
@Test(groups = {"functional", "transaction"})
public class IsolationLevelNoneTest
{
   CacheSPI<String, String> cache = null;
   final Fqn FQN = Fqn.fromString("/a/b/c");
   final String KEY = "key";
   final String VALUE = "value";
   TransactionManager tm;

   @AfterMethod(alwaysRun = true)
   public void tearDown() throws Exception
   {
      if (cache != null)
      {
         cache.stop();
         cache.destroy();
         cache = null;
      }
   }

   public void testWithoutTransactions() throws Exception
   {
      CacheFactory<String, String> instance = new DefaultCacheFactory();
      cache = (CacheSPI<String, String>) instance.createCache(false);
      cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
      cache.getConfiguration().setIsolationLevel(IsolationLevel.NONE);
      cache.start();
      cache.put(FQN, KEY, VALUE);
      cache.put(FQN + "/d", KEY, VALUE);
      Node node = cache.peek(FQN, false, false);
      assertTrue(node != null && node.getKeys().contains(KEY));
      assertEquals(VALUE, cache.get(FQN, KEY));
      assertEquals(0, cache.getNumberOfLocksHeld());
   }

   public void testWithTransactions() throws Exception
   {
      CacheFactory<String, String> instance = new DefaultCacheFactory();
      cache = (CacheSPI<String, String>) instance.createCache(false);
      cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
      cache.getConfiguration().setIsolationLevel(IsolationLevel.NONE);
      cache.getConfiguration().setTransactionManagerLookupClass(TransactionSetup.getManagerLookup());
      cache.start();
      tm = startTransaction();
      cache.put(FQN, KEY, VALUE);
      cache.put(FQN + "/d", KEY, VALUE);
      Node node = cache.peek(FQN, false, false);
      assertTrue(node != null && node.getKeys().contains(KEY));
      assertEquals(VALUE, cache.get(FQN, KEY));
      assertEquals(0, cache.getNumberOfLocksHeld());
      tm.commit();
   }

   public void testWithTransactionsRepeatableRead() throws Exception
   {
      CacheFactory<String, String> instance = new DefaultCacheFactory();
      cache = (CacheSPI<String, String>) instance.createCache(false);
      cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
      cache.getConfiguration().setIsolationLevel(IsolationLevel.REPEATABLE_READ);
      cache.getConfiguration().setTransactionManagerLookupClass(TransactionSetup.getManagerLookup());
      cache.start();
      tm = startTransaction();
      cache.put(FQN, KEY, VALUE);
      cache.put(FQN + "/d", KEY, VALUE);
      Node node = cache.peek(FQN, false, false);
      assertTrue(node != null && node.getKeys().contains(KEY));
      assertEquals(VALUE, cache.get(FQN, KEY));
      assertEquals(5, cache.getNumberOfLocksHeld());
      tm.commit();
   }

   private TransactionManager startTransaction() throws SystemException, NotSupportedException
   {
      TransactionManager mgr = cache.getTransactionManager();
      mgr.begin();
      return mgr;
   }
}
