Author: manik.surtani(a)jboss.com
Date: 2007-09-14 11:50:44 -0400 (Fri, 14 Sep 2007)
New Revision: 4461
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
Log:
Added tests for a series of bugs, including JBCACHE-923, JBCACHE-1164, JBCACHE-1165,
JBCACHE-1166, JBCACHE-1168, JBCACHE-1183.
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java 2007-09-14
15:50:44 UTC (rev 4461)
@@ -0,0 +1,107 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.IsolationLevel;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ConcurrentPutRemoveTest extends TestCase
+{
+
+ private TransactionManager tm;
+
+ public ConcurrentPutRemoveTest(String s)
+ {
+ super(s);
+ }
+
+ private TreeCache cache;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setCacheMode(TreeCache.LOCAL);
+ cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ cache.setTransactionManagerLookup(new DummyTransactionManagerLookup());
+ cache.setLockAcquisitionTimeout(10000);
+ cache.create();
+ cache.start();
+ tm = cache.getTransactionManager();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ cache.stop();
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception
+ {
+ List threads = new ArrayList();
+ for (int x = 0; x < 2; x++)
+ {
+ SeparateThread t = new SeparateThread(x);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ SeparateThread separateThread = (SeparateThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ throw separateThread.getException();
+ }
+ }
+
+ }
+
+ private class SeparateThread extends Thread
+ {
+ Exception e = null;
+
+ private int num = 0;
+
+ public SeparateThread(int num)
+ {
+ this.num = num;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("Thread:" + num);
+ try
+ {
+ for (int x = 0; x < 1000; x++)
+ {
+ tm.begin();
+ System.out.println("R" + Thread.currentThread().getName());
+ //inside transaction
+ cache.remove("/a");
+ System.out.println("AR" + Thread.currentThread().getName());
+ tm.commit();
+ //outside transaction
+ System.out.println("P" + Thread.currentThread().getName());
+ cache.put("/a/b/c/d", "text" + x, "b");
+ System.out.println("AP" + Thread.currentThread().getName());
+ }
+ }
+ catch (Exception e)
+ {
+ this.e = e;
+ }
+ }
+ }
+
+}
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java 2007-09-14
15:50:44 UTC (rev 4461)
@@ -0,0 +1,175 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.IsolationLevel;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+public class LockNotReleasedTest extends TestCase
+{
+ Random rand = new Random(System.currentTimeMillis());
+
+ private TransactionManager tm;
+
+ private TreeCache cache;
+
+ private void startTest() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setCacheMode(TreeCache.LOCAL);
+ cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+
cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.setLockAcquisitionTimeout(1000);
+ cache.create();
+ cache.start();
+ tm = cache.getTransactionManager();
+ }
+
+ public void tearDown() throws Exception
+ {
+ cache.stop();
+ cache.destroy();
+ }
+
+
+ public int getNumberOfLocksHeld()
+ {
+ return numLocks((Node) cache.getRoot());
+ }
+
+ private int numLocks(Node n)
+ {
+ int num = 0;
+ Map children;
+
+ if (n.getLock().isLocked())
+ {
+ num++;
+ System.out.println("Node [" + n.getFqn() + "] is locked");
+ }
+ if ((children = n.getChildren(true)) != null)
+ {
+ for (Iterator i = children.values().iterator(); i.hasNext();)
+ {
+ num += numLocks((Node) i.next());
+ }
+ }
+ return num;
+ }
+
+ public void testTransactionStorm() throws Exception
+ {
+ startTest();
+ List threads = new ArrayList();
+// System.out.println(cache.getNumberOfLocksHeld());
+ assertEquals(0, getNumberOfLocksHeld());
+ while (true)
+ {
+ for (int x = 0; x < 2; x++)
+ {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ WorkThread separateThread = (WorkThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ //separateThread.getException().getMessage();
+ }
+ }
+ int locksNum = getNumberOfLocksHeld();
+// System.out.println("Locks="+locksNum);
+ // checkpoint
+ if (cache.getNumberOfLocksHeld() > 0)
+ {
+ System.out.println("ERROR, locks=" + locksNum);
+ doDomethingOnCache(1);
+ }
+ assertEquals(0, locksNum);
+ }
+
+ }
+
+ private class WorkThread extends Thread
+ {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove)
+ {
+ this.remove = remove;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ try
+ {
+ for (int x = 0; x < 100; x++)
+ {
+ tm.begin();
+ try
+ {
+ doDomethingOnCache(x);
+ }
+ finally
+ {
+ if (x % 3 == 0)
+ {
+ tm.commit();
+ }
+ else
+ {
+ tm.rollback();
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+// System.out.println(e.getMessage());
+ this.e = e;
+ }
+ }
+
+ }
+
+ private void doDomethingOnCache(int x) throws CacheException, InterruptedException
+ {
+ cache.put(Fqn.fromString("/a/b/c/a"), "text1" + x,
"");
+ cache.remove(Fqn.fromString("/q/b/c/d"));
+ cache.put(Fqn.fromString("/a/b/c/b"), "text2" + x,
"");
+ cache.remove(Fqn.fromString("/q/b/c/c"));
+ cache.put(Fqn.fromString("/a/b/c/c"), "text3" + x,
"");
+ cache.remove(Fqn.fromString("/q/b/c/b"));
+ cache.put(Fqn.fromString("/a/b/c/d"), "text4" + x,
"");
+ cache.remove(Fqn.fromString("/q/b/c/a"));
+ cache.put(Fqn.fromString("/q/b/c/a"), "text5" + x,
"");
+ cache.remove(Fqn.fromString("/a/b/c/d"));
+ cache.put(Fqn.fromString("/q/b/c/b"), "text6" + x,
"");
+ cache.remove(Fqn.fromString("/a/b/c/c"));
+ cache.put(Fqn.fromString("/q/b/c/c"), "text7" + x,
"");
+ cache.remove(Fqn.fromString("/a/b/c/b"));
+ cache.put(Fqn.fromString("/q/b/c/d"), "text8" + x,
"");
+ cache.remove(Fqn.fromString("/a/b/c/a"));
+ }
+
+}
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java 2007-09-14
15:50:44 UTC (rev 4461)
@@ -0,0 +1,107 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.transaction.DummyTransactionManager;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Test behaviour of concurent put/remove
+ *
+ * @author jhalat
+ */
+public class LockUpgradeTest extends TestCase
+{
+
+ private TransactionManager tm;
+
+ public LockUpgradeTest(String s)
+ {
+ super(s);
+ }
+
+ private TreeCache cache;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+
cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = DummyTransactionManager.getInstance();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ cache.stop();
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception
+ {
+ List threads = new ArrayList();
+ for (int x = 0; x < 2; x++)
+ {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ WorkThread separateThread = (WorkThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ throw separateThread.getException();
+ }
+ }
+ }
+
+ private class WorkThread extends Thread
+ {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove)
+ {
+ this.remove = remove;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ try
+ {
+ for (int x = 0; x < 1000; x++)
+ {
+ tm.begin();
+ if (remove)
+ {
+ cache.remove("/a/b/c/d");
+ cache.remove("/a");
+ }
+ else
+ {
+ cache.put("/a/b/c/d", "key", "text" +
x);
+ }
+ tm.commit();
+ Thread.sleep(1);
+ }
+ }
+ catch (Exception e)
+ {
+ this.e = e;
+ }
+ }
+ }
+}
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java 2007-09-14
15:50:44 UTC (rev 4461)
@@ -0,0 +1,89 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+import org.jboss.cache.TreeCache;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * Test behaviour of async rollback timeouted transaction
+ *
+ * @author <a href="mailto:jhalat@infovide.pl">Jacek Halat</a>
+ */
+public class AsyncRollbackTxLockTest extends TestCase
+{
+ private TreeCache cache;
+ private TransactionManager tm;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+
+
cache.setTransactionManagerLookupClass("org.jboss.cache.transaction.AsyncRollbackTransactionManagerLookup");
+ cache.startService();
+ tm = cache.getTransactionManager();
+ tm.setTransactionTimeout(2);
+ }
+
+ protected void tearDown()
+ {
+ try
+ {
+ if (tm != null && tm.getTransaction() != null)
+ {
+ try
+ {
+ tm.rollback();
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ }
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ if (cache != null) cache.stopService();
+ cache = null;
+ tm = null;
+ }
+
+
+ public void testTxTimeoutAndRemovePutAfter() throws Exception
+ {
+ Thread.currentThread().setName("Thread-0");
+ System.out.println("Main Thread:" + Thread.currentThread());
+ assertEquals(0, cache.getNumberOfLocksHeld());
+ tm.setTransactionTimeout(1);//short transaction timeout
+ cache.put("/a/b/c/d", "k", "v");
+ tm.begin();
+ Transaction transaction = tm.getTransaction();
+ transaction.registerSynchronization(new Synchronization()
+ {
+
+ public void afterCompletion(int arg0)
+ {
+ System.out.println("Synchronization Thread:" +
Thread.currentThread());
+ }
+
+ public void beforeCompletion()
+ {
+ }
+
+ });
+ assertNotNull(tm.getTransaction());
+ Thread.sleep(500);//transaction should be rolledback in another thread
+ cache.put("/a", "k", "v");
+ tm.rollback();
+ assertNull(tm.getTransaction());
+ assertEquals(0, cache.getNumberOfLocksHeld());
+ cache.put("/a", "k", "v");
+ }
+
+}
+
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java 2007-09-14
15:50:44 UTC (rev 4461)
@@ -0,0 +1,95 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * To test JBCACHE-923
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ */
+public class SimultaneousRollbackAndPutTest extends TestCase
+{
+ private TreeCache cache;
+ private TransactionManager tm;
+ private Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b");
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+
cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = cache.getTransactionManager();
+ cache.put(A, "k", "v");
+ }
+
+ protected void tearDown()
+ {
+ cache.stop();
+ }
+
+ public void testStaleLocks() throws Exception
+ {
+ // repeat this test several times.
+ for (int i = 0; i < 1000; i++)
+ {
+ System.out.println("In loop " + i);
+ doTest();
+ cache.remove(B);
+ cache.removeData(A);
+ cache.put(A, "k", "v");
+ }
+
+ }
+
+
+ private void doTest() throws Exception
+ {
+ // scenario:
+ // Thread starts tx in cache. E.g., create and put into B
+ tm.begin();
+ final Transaction t = tm.getTransaction();
+ final List exceptions = new ArrayList();
+
+ cache.put(B, "k", "v");
+
+ // now the container should attempt to rollback the tx in a separate thread.
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ t.rollback();
+ }
+ catch (Exception e)
+ {
+ exceptions.add(e);
+ }
+ }
+ }.start();
+
+ // now try and put stuff in the main thread again
+ cache.put(A, "k2", "v2");
+ try
+ {
+ tm.commit();
+ }
+ catch (RollbackException expected)
+ {
+ // this is expected.
+ }
+
+ assertEquals("No stale locks should be around", 0,
cache.getNumberOfLocksHeld());
+
+ if (exceptions.size() > 0) throw ((Exception) exceptions.get(0));
+ }
+}