package org.apache.niolex.lock; import static org.junit.Assert.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.apache.niolex.commons.bean.One; import org.apache.niolex.commons.concurrent.ThreadUtil; import org.apache.niolex.commons.util.Runner; import org.junit.Test; public class DistributedLockTest extends DistributedLock { @Test public void testLock() throws Exception { lock(); assertEquals(1, initLock); assertEquals(2, isLockReady); assertEquals(1, watchLock); assertEquals(0, release); lock(); assertEquals(2, initLock); assertEquals(4, isLockReady); assertEquals(2, watchLock); assertEquals(0, release); } @Test(expected=IllegalArgumentException.class) public void testLockException() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); exception = new IllegalArgumentException("test"); Future<Object> fu = Runner.run(threadVal, this, "lock"); int i = 5; while (i-- > 0) { ThreadUtil.sleep(20); threadVal.a.interrupt(); } latch.countDown(); assertEquals(1, initLock); assertTrue(1 < watchLock); try { fu.get(); } catch (ExecutionException e) { assertEquals(1, release); throw e.getCause(); } assertEquals(2, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test public void testLockInterruptibly() throws Exception { lockInterruptibly(); assertEquals(1, initLock); assertEquals(2, isLockReady); assertEquals(1, watchLock); assertEquals(0, release); lockInterruptibly(); assertEquals(2, initLock); assertEquals(4, isLockReady); assertEquals(2, watchLock); assertEquals(0, release); } @Test(expected=InterruptedException.class) public void testLockInterruptiblyInterrupt() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); exception = new IllegalArgumentException("test"); Future<Object> fu = Runner.run(threadVal, this, "lockInterruptibly"); int i = 5; while (i-- > 0) { ThreadUtil.sleep(20); threadVal.a.interrupt(); } assertEquals(1, initLock); assertEquals(1, isLockReady); assertEquals(1, watchLock); assertEquals(1, release); try { fu.get(); } catch (ExecutionException e) { assertEquals(1, release); throw e.getCause(); } assertEquals(2, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test(expected=IllegalArgumentException.class) public void testLockInterruptiblyException() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); exception = new IllegalArgumentException("test"); Future<Object> fu = Runner.run(threadVal, this, "lockInterruptibly"); ThreadUtil.sleep(100); latch.countDown(); assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(1, isLockReady); try { fu.get(); } catch (ExecutionException e) { assertEquals(1, release); throw e.getCause(); } assertEquals(2, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test public void testLockInterruptiblyOK() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); Future<Object> fu = Runner.run(threadVal, this, "lockInterruptibly"); ThreadUtil.sleep(100); latch.countDown(); assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(0, release); try { fu.get(); } catch (ExecutionException e) { throw e.getCause(); } assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test public void testTryLock() throws Exception { assertFalse(tryLock()); assertEquals(1, initLock); assertEquals(1, isLockReady); assertEquals(0, watchLock); assertEquals(1, release); assertTrue(tryLock()); assertEquals(2, initLock); assertEquals(2, isLockReady); assertEquals(0, watchLock); assertEquals(1, release); } @Test(expected=IllegalArgumentException.class) public void testTryLockException() throws Throwable { One<Thread> threadVal = One.create(null); exception2 = new IllegalArgumentException("test"); Future<Object> fu = Runner.run(threadVal, this, "tryLock"); ThreadUtil.sleep(100); assertEquals(1, initLock); assertEquals(0, watchLock); try { fu.get(); } catch (ExecutionException e) { assertEquals(1, release); assertEquals(0, isLockReady); assertEquals(1, initLock); assertEquals(0, watchLock); throw e.getCause(); } assertEquals(1000, release); } @Test public void testTryLockLongTimeUnit() throws Exception { assertTrue(tryLock(100, TimeUnit.MICROSECONDS)); assertEquals(1, initLock); assertEquals(2, isLockReady); assertEquals(1, watchLock); assertEquals(0, release); assertTrue(tryLock(100, TimeUnit.MICROSECONDS)); assertEquals(2, initLock); assertEquals(4, isLockReady); assertEquals(2, watchLock); assertEquals(0, release); } @Test public void testTryLockLongTimeUnitOKD() throws Exception { isLockReady = 1; assertTrue(tryLock(100, TimeUnit.MICROSECONDS)); assertEquals(1, initLock); assertEquals(2, isLockReady); assertEquals(0, watchLock); assertEquals(0, release); assertTrue(tryLock(100, TimeUnit.MICROSECONDS)); assertEquals(2, initLock); assertEquals(4, isLockReady); assertEquals(1, watchLock); assertEquals(0, release); } @Test(expected=InterruptedException.class) public void testTryLockLongTimeUnitInterrupt() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); Future<Object> fu = Runner.run(threadVal, this, "tryLock", 200, TimeUnit.MILLISECONDS); int i = 5; while (i-- > 0) { ThreadUtil.sleep(20); threadVal.a.interrupt(); } assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(1, release); try { fu.get(); } catch (ExecutionException e) { throw e.getCause(); } assertEquals(2, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test(expected=IllegalArgumentException.class) public void testTryLockLongTimeUnitException() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); exception = new IllegalArgumentException("test"); Future<Object> fu = Runner.run(threadVal, this, "tryLock", 200, TimeUnit.MILLISECONDS); ThreadUtil.sleep(100); latch.countDown(); assertEquals(1, initLock); assertEquals(1, watchLock); try { fu.get(); } catch (ExecutionException e) { assertEquals(1, release); throw e.getCause(); } assertEquals(2, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test public void testTryLockLongTimeUnitOK() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); Future<Object> fu = Runner.run(threadVal, this, "tryLock", 200, TimeUnit.MILLISECONDS); ThreadUtil.sleep(100); latch.countDown(); try { fu.get(); assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(0, release); } catch (ExecutionException e) { throw e.getCause(); } assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(0, release); } @Test public void testTryLockLongTimeUnitTimeout() throws Throwable { One<Thread> threadVal = One.create(null); latch = new CountDownLatch(1); Future<Boolean> fu = Runner.run(threadVal, this, "tryLock", 50, TimeUnit.MILLISECONDS); ThreadUtil.sleep(100); latch.countDown(); try { Boolean r = fu.get(); assertFalse(r); assertEquals(1, initLock); assertEquals(2, isLockReady); assertEquals(1, watchLock); } catch (ExecutionException e) { throw e.getCause(); } assertEquals(1, initLock); assertEquals(1, watchLock); assertEquals(1, release); } @Test(expected=UnsupportedOperationException.class) public void testNewCondition() throws Exception { newCondition(); } @Test public void testUnlock() throws Exception { unlock(); assertEquals(1, release); unlock(); assertEquals(2, release); } private int initLock = 0; private int isLockReady = 0; private int watchLock = 0; private int release = 0; private RuntimeException exception = null; private RuntimeException exception2 = null; private CountDownLatch latch = null; private boolean timeout2 = false; /** * This is the override of super method. * @see org.apache.niolex.lock.DistributedLock#initLock() */ @Override protected void initLock() { ++initLock; } /** * This is the override of super method. * @see org.apache.niolex.lock.DistributedLock#releaseLock() */ @Override protected void releaseLock() { ++release; } /** * This is the override of super method. * @see org.apache.niolex.lock.DistributedLock#isLockReady() */ @Override protected boolean isLockReady() { if (exception2 != null) throw exception2; if (++isLockReady % 2 == 0 && exception == null && !timeout2) { return true; } else { return false; } } /** * This is the override of super method. * @throws InterruptedException * @see org.apache.niolex.lock.DistributedLock#watchLock() */ @Override protected void watchLock() throws InterruptedException { ++watchLock; if (latch != null) latch.await(); if (exception != null) throw exception; } /** * This is the override of super method. * @see org.apache.niolex.lock.DistributedLock#watchLock(long, java.util.concurrent.TimeUnit) */ @Override protected boolean watchLock(long timeout, TimeUnit unit) throws InterruptedException { ++watchLock; if (latch != null) timeout2 = !latch.await(timeout, unit); if (exception != null) throw exception; if (watchLock % 2 == 0) { return true; } else { return false; } } /** * This is the override of super method. * @see org.apache.niolex.lock.DistributedLock#locked() */ @Override public boolean locked() { return false; } }