/*
* 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.apache.commons.logging.LogFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.GlobalTransaction;
import org.jboss.cache.misc.TestingUtil;
/** Testing of different locking semantics.
* @author Bela Ban
* @author Ben Wang
* @version $Revision: 1838 $
*/
public class IdentityLockTest extends TestCase
{
IdentityLock lock_;
Object other_ = new Object();
Log logger_=LogFactory.getLog(IdentityLockTest.class);
static Throwable thread_ex=null;
final Fqn FQN=Fqn.fromString("/dummyfqn");
public IdentityLockTest(String name)
{
super(name);
}
protected void setUp() throws Exception
{
super.setUp();
lock_ = new IdentityLock(null, FQN);
// try { Thread.TestingUtil.sleepThread(10000); } catch (Exception e) {
// }
}
protected void tearDown() throws Exception
{
super.tearDown();
lock_.releaseAll();
lock_ = null;
thread_ex=null;
}
protected void setLevelRW()
{
log("set lock level to RWUpgrade ...");
LockStrategyFactory.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
lock_ = new IdentityLock(null, FQN);
}
protected void setLevelSerial()
{
log("set lock level to SimpleLock ...");
LockStrategyFactory.setIsolationLevel(IsolationLevel.SERIALIZABLE);
lock_ = new IdentityLock(null, FQN);
}
protected GlobalTransaction getGlobalTransactionFromThread()
{
return GlobalTransaction.create(null);
}
public void testNullOwner_RWLock() throws InterruptedException {
setLevelRW();
nullOwner();
}
public void testNullOwner_SimpleLock() throws InterruptedException {
setLevelSerial();
nullOwner();
}
protected void nullOwner() throws InterruptedException {
log("testNullOwner ...");
try {
GlobalTransaction gtx = getGlobalTransactionFromThread();
lock_.acquireWriteLock(gtx, 50);
lock_.release(gtx);
lock_.acquireReadLock(gtx, 50);
lock_.release(gtx);
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e) {
fail(e.toString());
}
}
public void testNullOwner2_RWLock() throws InterruptedException {
setLevelRW();
nullOwner2();
}
public void testNullOwner2_SimpleLock() throws InterruptedException {
setLevelSerial();
nullOwner2();
}
protected void nullOwner2() throws InterruptedException {
log("testNullOwner2 ...");
try {
GlobalTransaction gtx = getGlobalTransactionFromThread();
lock_.acquireReadLock(gtx, 50);
lock_.acquireWriteLock(gtx, 50); // this should succeed
lock_.release(gtx);
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
}
public void testNullOwner3_RWLock() throws InterruptedException {
setLevelRW();
nullOwner3();
}
public void testNullOwner3_SimpleLock() throws InterruptedException {
setLevelSerial();
nullOwner3();
}
public void nullOwner3() throws InterruptedException {
log("testNullOwner3 ...");
try {
GlobalTransaction gtx = getGlobalTransactionFromThread();
lock_.acquireWriteLock(gtx, 50);
lock_.acquireReadLock(gtx, 50); // this should succeed
lock_.release(gtx);
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
}
public void testAcquireAndRelease_RWLock() throws InterruptedException {
setLevelRW();
acquireAndRelease();
}
public void testAcquireAndRelease_SimpleLock() throws InterruptedException {
setLevelSerial();
acquireAndRelease();
}
public void acquireAndRelease() throws InterruptedException {
log("testAcquireAndRelease ...");
try {
lock_.acquireReadLock(this, 50);
assertTrue("Is the lock owner", lock_.isOwner(this));
assertTrue(lock_.getReaderOwners().contains(this));
lock_.acquireReadLock(this, 50); // this should succeed
assertTrue("Is the lock owner", lock_.isOwner(this));
assertTrue(lock_.getReaderOwners().contains(this));
lock_.acquireWriteLock(this, 50); // this should succeed
assertTrue("Is the lock owner", lock_.isOwner(this));
assertTrue(!lock_.getReaderOwners().contains(this));
assertTrue(lock_.getWriterOwner().equals(this));
lock_.release(this);
assertTrue(!lock_.isOwner(this));
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
}
public void acquireAndRelease2_RWLock() throws InterruptedException {
setLevelRW();
log("testAcquireAndRelease2 ...");
try {
lock_.acquireReadLock(this, 10);
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
try {
lock_.acquireReadLock(other_, 10); // should succeed
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
try {
lock_.acquireWriteLock(other_, 50); // should fail
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
assertTrue(true);
}
lock_.release(this);
try {
lock_.acquireWriteLock(other_, 10); // should succeed
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
lock_.releaseAll();
}
public void acquireAndRelease2_SimpleLock() throws InterruptedException {
setLevelSerial();
log("testAcquireAndRelease2 ...");
try {
lock_.acquireReadLock(this, 10);
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
try {
lock_.acquireReadLock(other_, 10); // should fail
fail("Acquire read lock for other. Should fail.");
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
// Expected
assertTrue(true);
}
try {
lock_.acquireWriteLock(other_, 50); // should fail
fail("Acquire read lock for other. Should fail.");
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
assertTrue(true);
}
lock_.release(this);
try {
lock_.acquireWriteLock(other_, 10); // should succeed
} catch (LockingException e) {
fail(e.toString());
} catch (TimeoutException e2) {
fail(e2.toString());
}
lock_.releaseAll();
}
public void testThreadedAccess_RWLock() throws Throwable {
setLevelRW();
log("testThreadedAccess_RWLock ...");
final Object o1 = new Object();
final Object o2 = new Object();
System.out.println("");
// 1. o1 acquires the lock -- succeeds
Thread t1 = new Thread()
{
public void run()
{
try {
log("o1 acquiring lock");
lock_.acquireReadLock(o1, 50);
log("o1: OK");
} catch (Throwable e) {
log("o1: FAIL");
thread_ex=e;
}
}
};
// 2. o2 wants to acquire the lock -- this will fail and o2 will block for 2 secs
Thread t2 = new Thread()
{
public void run()
{
try {
log("o2 acquiring lock");
lock_.acquireWriteLock(o2, 2000);
log("o2: OK");
} catch (Throwable e) {
log("o2: FAIL");
thread_ex=e;
}
}
};
// 3. o1 acquires the lock a second time -- succeeds
Thread t3 = new Thread()
{
public void run()
{
try {
log("o1 acquiring lock");
lock_.acquireWriteLock(o1, 10);
log("o1: OK");
} catch (Throwable e) {
log("o1: FAIL");
thread_ex=e;
}
}
};
t1.start();
t2.start();
TestingUtil.sleepThread(1000);
// o1 must be the owner of the lock
assertTrue(lock_.isOwner(o1));
TestingUtil.sleepThread(100);
// o1 must still be the owner of the lock
assertTrue(lock_.isOwner(o1));
t3.start();
TestingUtil.sleepThread(100);
// o1 must still be the owner of the lock
assertTrue(lock_.isOwner(o1));
// 4. o1 releases the lock; now o2 will succeed in acquiring the lock
log("o1 releasing lock");
lock_.release(o1);
log("o1: OK");
TestingUtil.sleepThread(200);
//log("o2: " + o2.hashCode() + ", lock_.getOwner()=" + lock_.getOwner());
// assertTrue(lock_.isOwner(o2));
// lock_.release(o2);
t1.join(20000);
t2.join(20000);
t3.join(20000);
if(thread_ex != null)
throw thread_ex;
}
public void testThreadedAccess_SimpleLock() throws Throwable {
setLevelSerial();
log("testThreadedAccess_SimpleLock() ...");
final Object o1 = new Object();
final Object o2 = new Object();
System.out.println("");
// 1. o1 acquires the lock -- succeeds
Thread t1 = new Thread()
{
public void run()
{
try {
log("o1 acquiring lock");
lock_.acquireReadLock(o1, 50);
log("o1: OK");
} catch (Throwable e) {
log("o1: FAIL");
thread_ex=e;
}
}
};
// 2. o2 wants to acquire the lock -- this will fail and o2 will block for 2 secs
Thread t2 = new Thread()
{
public void run()
{
try {
log("o2 acquiring lock");
lock_.acquireWriteLock(o2, 2000);
log("o2: OK");
} catch (Throwable e) {
log("o2: FAIL");
thread_ex=e;
}
}
};
// 3. o1 acquires the lock a second time -- succeeds
Thread t3 = new Thread()
{
public void run()
{
try {
log("o1 acquiring lock");
lock_.acquireWriteLock(o1, 10);
log("o1: OK");
} catch (Throwable e) {
log("o1: FAIL");
thread_ex=e;
}
}
};
t1.start();
t2.start();
TestingUtil.sleepThread(1000);
// o1 must be the owner of the lock
assertTrue(lock_.isOwner(o1));
TestingUtil.sleepThread(100);
// o1 must still be the owner of the lock
assertTrue(lock_.isOwner(o1));
t3.start();
TestingUtil.sleepThread(100);
// o1 must still be the owner of the lock
assertTrue(lock_.isOwner(o1));
// 4. o1 releases the lock; now o2 will succeed in acquiring the lock
log("o1 releasing lock");
lock_.release(o1);
log("o1: OK");
TestingUtil.sleepThread(200);
//log("o2: " + o2.hashCode() + ", lock_.getOwner()=" + lock_.getOwner());
// assertTrue(lock_.isOwner(o2));
// lock_.release(o2);
t1.join(20000);
t2.join(20000);
t3.join(20000);
if(thread_ex != null)
throw thread_ex;
}
public void testReadAndReleaseAll()
{
setLevelRW();
log("testReadAndReleaseAll() ...");
final Object o1 = new Object();
final Object o2 = new Object();
System.out.println("");
// 1. o1 acquires the lock -- succeeds
try
{
log("o1: acquiring");
lock_.acquireReadLock(o1, 50);
log("o1: OK");
log("o2: acquiring");
lock_.acquireReadLock(o2, 50);
log("o2: OK");
}
catch (Throwable t)
{
log("read lock: FAIL");
fail(t.getMessage());
}
Thread t1 = new Thread()
{
public void run()
{
try {
log("calling releaseAll()");
lock_.releaseAll();
log("releaseAll(): OK");
} catch (Throwable e) {
log("releaseAll(): FAIL");
thread_ex=e;
}
}
};
try {
t1.setDaemon(true);
t1.start();
TestingUtil.sleepThread(1000);
assertFalse("Lock map cleared", lock_.isReadLocked());
}
finally {
// Manually release the locks so tearDown() will not fail
// if there is a problem with releaseAll()
lock_.release(o1);
lock_.release(o2);
}
}
public void testWriteAndReleaseAll()
{
setLevelSerial();
log("testWriteAndReleaseAll() ...");
final Object o1 = new Object();
System.out.println("");
// 1. o1 acquires the lock -- succeeds
try
{
log("o1: acquiring");
lock_.acquireWriteLock(o1, 50);
log("o1: OK");
}
catch (Throwable t)
{
log("write lock: FAIL");
fail(t.getMessage());
}
Thread t1 = new Thread()
{
public void run()
{
try {
log("calling releaseAll()");
lock_.releaseAll();
log("releaseAll(): OK");
} catch (Throwable e) {
log("releaseAll(): FAIL");
thread_ex=e;
}
}
};
try {
t1.setDaemon(true);
t1.start();
TestingUtil.sleepThread(1000);
assertFalse("Lock map cleared", lock_.isReadLocked());
}
finally {
// Manually release the lock so tearDown() will not fail
// if there is a problem with releaseAll()
lock_.release(o1);
}
}
void log(String msg)
{
// System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
logger_.info("-- [" + Thread.currentThread() + "]: " + msg);
}
public static Test suite()
{
TestSuite s = new TestSuite(IdentityLockTest.class);
return s;
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
}