From c6255fa9b539543ae2f4a0e07f92bf7bf167609f Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 9 Dec 2015 14:13:09 +0300 Subject: [PATCH] RedissonReadWriteLockTest added. #206 --- .../redisson/RedissonReadWriteLockTest.java | 449 ++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100644 src/test/java/org/redisson/RedissonReadWriteLockTest.java diff --git a/src/test/java/org/redisson/RedissonReadWriteLockTest.java b/src/test/java/org/redisson/RedissonReadWriteLockTest.java new file mode 100644 index 000000000..8683708a1 --- /dev/null +++ b/src/test/java/org/redisson/RedissonReadWriteLockTest.java @@ -0,0 +1,449 @@ +package org.redisson; + +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.Assert; +import org.junit.Test; +import org.redisson.core.RLock; +import org.redisson.core.RReadWriteLock; + +public class RedissonReadWriteLockTest extends BaseConcurrentTest { + + @Test + public void testWriteLock() throws InterruptedException { + final RReadWriteLock lock = redisson.getReadWriteLock("lock"); + + final RLock writeLock = lock.writeLock(); + writeLock.lock(); + + Assert.assertTrue(lock.writeLock().tryLock()); + + Thread t = new Thread() { + public void run() { + Assert.assertFalse(writeLock.isHeldByCurrentThread()); + Assert.assertTrue(writeLock.isLocked()); + Assert.assertFalse(lock.readLock().tryLock()); + Assert.assertFalse(redisson.getReadWriteLock("lock").readLock().tryLock()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + Assert.assertTrue(lock.readLock().tryLock()); + Assert.assertTrue(redisson.getReadWriteLock("lock").readLock().tryLock()); + }; + }; + + t.start(); + t.join(50); + + writeLock.unlock(); + Assert.assertFalse(lock.readLock().tryLock()); + Assert.assertTrue(writeLock.isHeldByCurrentThread()); + writeLock.unlock(); + Thread.sleep(1000); + + Assert.assertFalse(lock.writeLock().tryLock()); + Assert.assertFalse(lock.writeLock().isLocked()); + Assert.assertFalse(lock.writeLock().isHeldByCurrentThread()); + lock.delete(); + } + + @Test + public void testMultiRead() throws InterruptedException { + final RReadWriteLock lock = redisson.getReadWriteLock("lock"); + Assert.assertFalse(lock.delete()); + + final RLock readLock1 = lock.readLock(); + readLock1.lock(); + + Assert.assertFalse(lock.writeLock().tryLock()); + + final AtomicReference readLock2 = new AtomicReference(); + Thread t = new Thread() { + public void run() { + RLock r = lock.readLock(); + Assert.assertFalse(readLock1.isHeldByCurrentThread()); + Assert.assertTrue(readLock1.isLocked()); + r.lock(); + readLock2.set(r); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + r.unlock(); + }; + }; + + t.start(); + t.join(50); + + Assert.assertTrue(readLock2.get().isLocked()); + + readLock1.unlock(); + Assert.assertFalse(lock.writeLock().tryLock()); + Assert.assertFalse(readLock1.isHeldByCurrentThread()); + Thread.sleep(1000); + + Assert.assertFalse(readLock2.get().isLocked()); + Assert.assertTrue(lock.writeLock().tryLock()); + Assert.assertTrue(lock.writeLock().isLocked()); + Assert.assertTrue(lock.writeLock().isHeldByCurrentThread()); + lock.writeLock().unlock(); + + Assert.assertFalse(lock.writeLock().isLocked()); + Assert.assertFalse(lock.writeLock().isHeldByCurrentThread()); + Assert.assertTrue(lock.writeLock().tryLock()); + lock.delete(); + } + + @Test + public void testDelete() { + RReadWriteLock lock = redisson.getReadWriteLock("lock"); + Assert.assertFalse(lock.delete()); + + lock.readLock().lock(); + Assert.assertTrue(lock.delete()); + } + + @Test + public void testForceUnlock() { + RReadWriteLock lock = redisson.getReadWriteLock("lock"); + RLock readLock = lock.readLock(); + readLock.lock(); + Assert.assertTrue(readLock.isLocked()); + readLock.forceUnlock(); + Assert.assertFalse(readLock.isLocked()); + + lock = redisson.getReadWriteLock("lock"); + Assert.assertFalse(lock.readLock().isLocked()); + } + + @Test + public void testExpireRead() throws InterruptedException { + RReadWriteLock lock = redisson.getReadWriteLock("lock"); + lock.readLock().lock(2, TimeUnit.SECONDS); + + final long startTime = System.currentTimeMillis(); + Thread t = new Thread() { + public void run() { + RReadWriteLock lock1 = redisson.getReadWriteLock("lock"); + lock1.readLock().lock(); + long spendTime = System.currentTimeMillis() - startTime; + Assert.assertTrue(spendTime < 2050); + lock1.readLock().unlock(); + }; + }; + + t.start(); + t.join(); + + lock.readLock().unlock(); + } + + @Test + public void testExpireWrite() throws InterruptedException { + RReadWriteLock lock = redisson.getReadWriteLock("lock"); + lock.writeLock().lock(2, TimeUnit.SECONDS); + + final long startTime = System.currentTimeMillis(); + Thread t = new Thread() { + public void run() { + RReadWriteLock lock1 = redisson.getReadWriteLock("lock"); + lock1.writeLock().lock(); + long spendTime = System.currentTimeMillis() - startTime; + Assert.assertTrue(spendTime < 2050); + lock1.writeLock().unlock(); + }; + }; + + t.start(); + t.join(); + + lock.writeLock().unlock(); + } + + + @Test + public void testAutoExpire() throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + testSingleInstanceConcurrency(1, new RedissonRunnable() { + @Override + public void run(RedissonClient redisson) { + RReadWriteLock lock1 = redisson.getReadWriteLock("lock"); + lock1.writeLock().lock(); + latch.countDown(); + } + }); + + Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); + RReadWriteLock lock1 = redisson.getReadWriteLock("lock"); + Thread.sleep(TimeUnit.SECONDS.toMillis(RedissonLock.LOCK_EXPIRATION_INTERVAL_SECONDS + 1)); + Assert.assertFalse("Transient lock expired automatically", lock1.writeLock().isLocked()); + } + + @Test + public void testHoldCount() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + testHoldCount(rwlock.readLock()); + testHoldCount(rwlock.writeLock()); + } + + private void testHoldCount(RLock lock) { + Assert.assertEquals(0, lock.getHoldCount()); + lock.lock(); + Assert.assertEquals(1, lock.getHoldCount()); + lock.unlock(); + Assert.assertEquals(0, lock.getHoldCount()); + + lock.lock(); + lock.lock(); + Assert.assertEquals(2, lock.getHoldCount()); + lock.unlock(); + Assert.assertEquals(1, lock.getHoldCount()); + lock.unlock(); + Assert.assertEquals(0, lock.getHoldCount()); + } + + @Test + public void testIsHeldByCurrentThreadOtherThread() throws InterruptedException { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + lock.lock(); + + Thread t = new Thread() { + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + + Assert.assertFalse(lock.isHeldByCurrentThread()); + }; + }; + + t.start(); + t.join(); + + lock.unlock(); + + Thread t2 = new Thread() { + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + + Assert.assertFalse(lock.isHeldByCurrentThread()); + }; + }; + + t2.start(); + t2.join(); + } + + @Test + public void testIsHeldByCurrentThread() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + Assert.assertFalse(lock.isHeldByCurrentThread()); + lock.lock(); + Assert.assertTrue(lock.isHeldByCurrentThread()); + lock.unlock(); + Assert.assertFalse(lock.isHeldByCurrentThread()); + } + + @Test + public void testIsLockedOtherThread() throws InterruptedException { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + lock.lock(); + + Thread t = new Thread() { + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + Assert.assertTrue(lock.isLocked()); + }; + }; + + t.start(); + t.join(); + + lock.unlock(); + + Thread t2 = new Thread() { + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + Assert.assertFalse(lock.isLocked()); + }; + }; + + t2.start(); + t2.join(); + } + + @Test + public void testIsLocked() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + Assert.assertFalse(lock.isLocked()); + lock.lock(); + Assert.assertTrue(lock.isLocked()); + lock.unlock(); + Assert.assertFalse(lock.isLocked()); + } + + @Test(expected = IllegalMonitorStateException.class) + public void testUnlockFail() throws InterruptedException { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + Thread t = new Thread() { + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + rwlock.readLock().lock(); + }; + }; + + t.start(); + t.join(); + + RLock lock = rwlock.readLock(); + lock.unlock(); + } + + @Test + public void testLockUnlock() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + lock.lock(); + lock.unlock(); + + lock.lock(); + lock.unlock(); + } + + @Test + public void testReentrancy() throws InterruptedException { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock"); + RLock lock = rwlock.readLock(); + + Assert.assertTrue(lock.tryLock()); + Assert.assertTrue(lock.tryLock()); + lock.unlock(); + // next row for test renew expiration tisk. + //Thread.currentThread().sleep(TimeUnit.SECONDS.toMillis(RedissonLock.LOCK_EXPIRATION_INTERVAL_SECONDS*2)); + Thread thread1 = new Thread() { + @Override + public void run() { + RReadWriteLock rwlock = redisson.getReadWriteLock("lock1"); + RLock lock = rwlock.readLock(); + Assert.assertTrue(lock.tryLock()); + } + }; + thread1.start(); + thread1.join(); + lock.unlock(); + } + + + @Test + public void testConcurrency_SingleInstance() throws InterruptedException { + final AtomicInteger lockedCounter = new AtomicInteger(); + + final Random r = new SecureRandom(); + int iterations = 15; + testSingleInstanceConcurrency(iterations, new RedissonRunnable() { + @Override + public void run(RedissonClient redisson) { + RReadWriteLock rwlock = redisson.getReadWriteLock("testConcurrency_SingleInstance"); + RLock lock; + if (r.nextBoolean()) { + lock = rwlock.writeLock(); + } else { + lock = rwlock.readLock(); + } + + lock.lock(); + lockedCounter.incrementAndGet(); + lock.unlock(); + } + }); + + Assert.assertEquals(iterations, lockedCounter.get()); + } + + @Test + public void testConcurrencyLoop_MultiInstance() throws InterruptedException { + final int iterations = 100; + final AtomicInteger lockedCounter = new AtomicInteger(); + + final Random r = new SecureRandom(); + testMultiInstanceConcurrency(16, new RedissonRunnable() { + @Override + public void run(RedissonClient redisson) { + for (int i = 0; i < iterations; i++) { + boolean useWriteLock = r.nextBoolean(); + RReadWriteLock rwlock = redisson.getReadWriteLock("testConcurrency_MultiInstance1"); + RLock lock; + if (useWriteLock) { + lock = rwlock.writeLock(); + } else { + lock = rwlock.readLock(); + } + lock.lock(); + + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + lockedCounter.incrementAndGet(); + + rwlock = redisson.getReadWriteLock("testConcurrency_MultiInstance1"); + if (useWriteLock) { + lock = rwlock.writeLock(); + } else { + lock = rwlock.readLock(); + } + lock.unlock(); + } + } + }); + + Assert.assertEquals(16 * iterations, lockedCounter.get()); + } + + @Test + public void testConcurrency_MultiInstance() throws InterruptedException { + int iterations = 100; + final AtomicInteger lockedCounter = new AtomicInteger(); + + final Random r = new SecureRandom(); + testMultiInstanceConcurrency(iterations, new RedissonRunnable() { + @Override + public void run(RedissonClient redisson) { + RReadWriteLock rwlock = redisson.getReadWriteLock("testConcurrency_MultiInstance2"); + RLock lock; + if (r.nextBoolean()) { + lock = rwlock.writeLock(); + } else { + lock = rwlock.readLock(); + } + + lock.lock(); + lockedCounter.incrementAndGet(); + lock.unlock(); + } + }); + + Assert.assertEquals(iterations, lockedCounter.get()); + } + +}