package org.jboss.cache.lock;
import org.jboss.cache.util.TestingUtil;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Tests ReentrantWriterPreferenceReadWriteLock
*
* @author Bela Ban
* @version $Id: ReentrantWriterPreferenceReadWriteLockTest.java 6905 2008-10-13 09:35:27Z dpospisi@redhat.com $
*/
@Test(groups = {"functional"}, sequential = true)
public class ReentrantWriterPreferenceReadWriteLockTest
{
ReentrantReadWriteLock lock;
Lock rl, wl;
Exception thread_ex = null;
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception
{
// lock=new ReentrantWriterPreferenceReadWriteLock();
lock = new ReentrantReadWriteLock();
rl = lock.readLock();
wl = lock.writeLock();
thread_ex = null;
}
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
lock = null;
if (thread_ex != null)
throw thread_ex;
}
public void testMultipleReadLockAcquisitions() throws InterruptedException
{
rl.lock();
rl.lock();
}
public void testInterruptedLockAcquisition()
{
Thread.currentThread().interrupt();
try
{
rl.lockInterruptibly();
fail("thread should be in interrupted status");
}
catch (InterruptedException e)
{
}
finally
{
try
{
rl.unlock();
fail("unlock() should throw an IllegalStateException");
}
catch (IllegalMonitorStateException illegalStateEx)
{
assertTrue(true);
}
}
}
public void testMultipleWriteLockAcquisitions() throws InterruptedException
{
wl.lock();
wl.lock();
}
public void testMultipleReadLockReleases() throws InterruptedException
{
rl.lock();
rl.unlock();
try
{
rl.unlock();
fail("we should not get here, cannot lock RL once but unlock twice");
}
catch (IllegalMonitorStateException illegalState)
{
// this is as expected
}
}
public void testMultipleWriteLockReleases() throws InterruptedException
{
wl.lock();
wl.unlock();
try
{
wl.unlock();
fail("expected");
}
catch (IllegalMonitorStateException e)
{
}
}
public void testAcquireWriteLockAfterReadLock() throws InterruptedException
{
rl.lock();
rl.unlock();
wl.lock();
}
public void testAcquiringReadLockedLockWithRead() throws InterruptedException
{
new Thread()
{
public void run()
{
try
{
rl.lockInterruptibly();
}
catch (InterruptedException e)
{
}
}
}.start();
TestingUtil.sleepThread(500);
// now we have a RL by another thread
boolean flag = rl.tryLock(3000, TimeUnit.MILLISECONDS);
assertTrue(flag);
flag = wl.tryLock(3000, TimeUnit.MILLISECONDS);
assertFalse(flag);
}
public void testAcquiringReadLockedLock() throws InterruptedException
{
new Thread()
{
public void run()
{
try
{
rl.lockInterruptibly();
}
catch (InterruptedException e)
{
}
}
}.start();
TestingUtil.sleepThread(500);
// now we have a RL by another thread
boolean flag = wl.tryLock(3000, TimeUnit.MILLISECONDS);
assertFalse(flag);
}
public void testWriteThenReadByDifferentTx() throws InterruptedException
{
Writer writer = new Writer("Writer");
Reader reader = new Reader("Reader");
writer.start();
TestingUtil.sleepThread(500);
reader.start();
TestingUtil.sleepThread(1000);
synchronized (writer)
{
log("terminating Writer");
writer.notify();
}
TestingUtil.sleepThread(500);
synchronized (reader)
{
reader.notify();
}
writer.join();
reader.join();
}
public void testReadThenWriteByDifferentTx() throws InterruptedException
{
Writer writer = new Writer("Writer");
Reader reader = new Reader("Reader");
reader.start();
TestingUtil.sleepThread(500);
writer.start();
TestingUtil.sleepThread(1000);
synchronized (reader)
{
log("terminating Reader");
reader.notify();
}
TestingUtil.sleepThread(500);
synchronized (writer)
{
writer.notify();
}
writer.join();
reader.join();
}
private static void log(String msg)
{
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread() +
" [" + Thread.currentThread().getName() + "]: " + msg);
}
class Reader extends Thread
{
public Reader(String name)
{
super(name);
}
public void run()
{
try
{
log("acquiring RL");
rl.lock();
log("acquired RL");
synchronized (this)
{
this.wait();
}
log("releasing RL");
rl.unlock();
log("released RL");
}
catch (InterruptedException e)
{
}
}
}
class Writer extends Thread
{
public Writer(String name)
{
super(name);
}
public void run()
{
try
{
log("acquiring WL");
wl.lock();
log("acquired WL");
synchronized (this)
{
this.wait();
}
log("releasing WL");
wl.unlock();
log("released WL");
}
catch (InterruptedException e)
{
}
}
}
class Upgrader extends Thread
{
boolean upgradeSuccessful = false;
public Upgrader(String name)
{
super(name);
}
public boolean wasUpgradeSuccessful()
{
return upgradeSuccessful;
}
public void run()
{
try
{
log("acquiring RL");
rl.lock();
log("acquired RL");
synchronized (this)
{
this.wait();
}
log("attempting to lock WL");
// rl.unlock();
wl.lock();
upgradeSuccessful = true;
log("acquired WL");
log("releasing WL/RL");
wl.unlock();
log("released WL/RL");
}
catch (InterruptedException e)
{
}
}
}
}