/*
*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.lock;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.cache.transaction.DummyTransactionManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.UserTransaction;
import java.util.Properties;
import java.util.Set;
/**
* Verifies that there are no read locks held when a transaction ends.
*
* @author Bela Ban
* @version $Id: LockReleaseTest.java 3090 2006-12-05 15:27:52Z msurtani $
*/
public class LockReleaseTest extends TestCase {
TreeCache cache=null;
UserTransaction tx=null;
Log log;
Properties p=null;
String old_factory=null;
final String FACTORY="org.jboss.cache.transaction.DummyContextFactory";
final Fqn NODE1=Fqn.fromString("/test");
final Fqn NODE2=Fqn.fromString("/my/test");
final String KEY="key";
final String VAL1="val1";
final String VAL2="val2";
public LockReleaseTest(String name) {
super(name);
}
public void setUp() throws Exception {
super.setUp();
old_factory=System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
DummyTransactionManager.getInstance();
if(p == null) {
p=new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
}
tx=(UserTransaction)new InitialContext(p).lookup("UserTransaction");
}
public void tearDown() throws Exception {
super.tearDown();
if(cache != null)
cache.stopService();
// BW. kind of a hack to destroy jndi binding and thread local tx before next run.
DummyTransactionManager.destroy();
if(old_factory != null) {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory);
old_factory=null;
}
if(tx != null) {
try {
tx.rollback();
}
catch(Throwable t) {
}
tx=null;
}
}
TreeCache createCache(IsolationLevel level) throws Exception {
TreeCache c=new TreeCache("test", null, 10000);
c.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
c.setLockAcquisitionTimeout(500);
c.setIsolationLevel(level);
c.createService();
c.startService();
return c;
}
public void testReadWithReadUncommitted() throws Exception {
testReadLockRelease(IsolationLevel.READ_UNCOMMITTED);
}
public void testWriteWithReadUncommitted() throws Exception {
testWriteLockRelease(IsolationLevel.READ_UNCOMMITTED);
}
public void testReadWithReadCommitted() throws Exception {
testReadLockRelease(IsolationLevel.READ_COMMITTED);
}
public void testWriteWithReadCommitted() throws Exception {
testWriteLockRelease(IsolationLevel.READ_COMMITTED);
}
public void testReadWithRepeatableRead() throws Exception {
testReadLockRelease(IsolationLevel.REPEATABLE_READ);
}
public void testWriteWithRepeatableRead() throws Exception {
testWriteLockRelease(IsolationLevel.REPEATABLE_READ);
}
public void testReadWithSerialzable() throws Exception {
testReadLockRelease(IsolationLevel.SERIALIZABLE);
}
public void testWriteWithSerializable() throws Exception {
testWriteLockRelease(IsolationLevel.SERIALIZABLE);
}
public void testGetKeys() throws Exception {
cache=createCache(IsolationLevel.REPEATABLE_READ);
// add initial values outside of TX
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we ran outside of a TX, locks should have been released: ", 0, cache.getNumberOfLocksHeld());
Set keys=cache.getKeys(NODE1);
System.out.println("keys of " + NODE1 + " are " + keys);
assertEquals("getKeys() called outside the TX should have released all locks", 0, cache.getNumberOfLocksHeld());
tx.begin();
keys=cache.getKeys(NODE1);
assertEquals("we should hold 2 read locks now: ", 2, cache.getNumberOfLocksHeld());
keys=cache.getKeys(NODE2);
assertEquals("we should hold 4 read locks now: ", 4, cache.getNumberOfLocksHeld());
tx.commit();
assertEquals("we should have released all 4 read locks: ", 0, cache.getNumberOfLocksHeld());
}
public void testGetChildrenNames() throws Exception {
cache=createCache(IsolationLevel.REPEATABLE_READ);
// add initial values outside of TX
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we ran outside of a TX, locks should have been released: ", 0, cache.getNumberOfLocksHeld());
Set keys=cache.getChildrenNames(NODE2);
System.out.println("keys of " + NODE2 + " are " + keys);
assertEquals("getChildrenNames() called outside the TX should have released all locks", 0,
cache.getNumberOfLocksHeld());
tx.begin();
keys=cache.getChildrenNames(NODE1);
assertEquals("we should hold 2 read locks now: ", 2, cache.getNumberOfLocksHeld());
keys=cache.getChildrenNames(NODE2);
assertEquals("we should hold 4 read locks now: ", 4, cache.getNumberOfLocksHeld());
tx.commit();
assertEquals("we should have released all 4 read locks: ", 0, cache.getNumberOfLocksHeld());
}
public void testPrint() throws Exception {
cache=createCache(IsolationLevel.REPEATABLE_READ);
// add initial values outside of TX
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we ran outside of a TX, locks should have been released: ", 0, cache.getNumberOfLocksHeld());
cache.print(NODE1);
assertEquals("print() called outside the TX should have released all locks", 0, cache.getNumberOfLocksHeld());
tx.begin();
cache.print(NODE1);
assertEquals("we should hold 2 read locks now (for print()): ", 2, cache.getNumberOfLocksHeld());
cache.print(NODE2);
assertEquals("we should hold 4 read locks now (for print()): ", 4, cache.getNumberOfLocksHeld());
tx.commit();
assertEquals("we should have released all 4 read locks: ", 0, cache.getNumberOfLocksHeld());
}
void testReadLockRelease(IsolationLevel level) throws Exception {
cache=createCache(level);
// add initial values outside of TX
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we ran outside of a TX, locks should have been released: ", 0, cache.getNumberOfLocksHeld());
tx.begin();
assertEquals(VAL1, cache.get(NODE1, KEY));
assertEquals(VAL1, cache.get(NODE2, KEY));
assertEquals("we should hold 4 read locks now: ", 4, cache.getNumberOfLocksHeld());
tx.commit();
assertEquals("we should have released all 4 read locks: ", 0, cache.getNumberOfLocksHeld());
}
void testWriteLockRelease(IsolationLevel level) throws Exception {
cache=createCache(level);
// add initial values outside of TX
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we ran outside of a TX, locks should have been released: ", 0, cache.getNumberOfLocksHeld());
tx.begin();
cache.put(NODE1, KEY, VAL1);
cache.put(NODE2, KEY, VAL1);
assertEquals("we should hold 4 write locks now: ", 4, cache.getNumberOfLocksHeld());
tx.commit();
assertEquals("we should have released all 4 write locks: ", 0, cache.getNumberOfLocksHeld());
}
void log(String msg) {
log.info("-- [" + Thread.currentThread() + "]: " + msg);
}
public static Test suite() throws Exception {
return new TestSuite(LockReleaseTest.class);
}
public static void main(String[] args) throws Exception {
junit.textui.TestRunner.run(suite());
}
}