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

package org.jboss.cache.api.mvcc;

import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.UnitTestCacheFactory;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.UnitTestConfigurationFactory;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.transaction.DummyTransactionManagerLookup;
import org.jboss.cache.util.TestingUtil;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import javax.transaction.TransactionManager;

@Test(groups = { "functional" }, testName = "api.mvcc.PutRemoveTest")
public class PutRemoveTest
{
   private CacheSPI<String, String> cache;
   private TransactionManager tm;

   @BeforeMethod(alwaysRun = true)
   public void setUp() throws Exception
   {
      UnitTestCacheFactory<String, String> factory = new UnitTestCacheFactory<String, String>();
      Configuration conf = UnitTestConfigurationFactory.createConfiguration(Configuration.CacheMode.LOCAL, true);
      conf.setIsolationLevel(IsolationLevel.READ_COMMITTED);
      conf.setLockParentForChildInsertRemove(true);
      conf.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
      cache = (CacheSPI<String, String>) factory.createCache(conf, true, getClass());
      tm = cache.getTransactionManager();
   }

   @AfterMethod(alwaysRun = true)
   public void tearDown() throws Exception
   {
      TestingUtil.killCaches(cache);
   }

   public void testPutRemove() throws Exception
   {
      Fqn fqn = Fqn.fromElements("test", "a", "b");

      for (int i = 0; i < 5; i++)
      {
         System.out.println("i == " + i + " [1]");
         tm.begin();
         check(fqn);
         tm.commit();

         System.out.println("i == " + i + " [2]");
         tm.begin();
         // the exception is in remove() on the SECOND pass!
         if (remove(fqn))
         {
            check(fqn);
         }
         tm.commit();
      }
   }

   private void check(Fqn fqn)
   {
      if (cache.get(fqn.getAncestor(1), "a") == null)
      {
         cache.put(fqn.getAncestor(1), "key-a", "value-a");
         cache.put(fqn, "test-key-a", "value-a");
      }
   }

   private boolean remove(Fqn fqn)
   {
      return cache.removeNode(fqn.getAncestor(1));
   }
}
