package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assume;
import org.junit.Test;
import org.redisson.api.RSemaphore;
public class RedissonSemaphoreTest extends BaseConcurrentTest {
@Test
public void testAcquireWithoutSetPermits() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.release();
s.release();
s.acquire(2);
}
@Test
public void testTrySetPermits() {
RSemaphore s = redisson.getSemaphore("test");
assertThat(s.trySetPermits(10)).isTrue();
assertThat(s.availablePermits()).isEqualTo(10);
assertThat(s.trySetPermits(15)).isFalse();
assertThat(s.availablePermits()).isEqualTo(10);
}
@Test
public void testReducePermits() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(10);
s.acquire(10);
s.reducePermits(5);
assertThat(s.availablePermits()).isEqualTo(-5);
s.release(10);
assertThat(s.availablePermits()).isEqualTo(5);
s.acquire(5);
assertThat(s.availablePermits()).isEqualTo(0);
}
@Test
public void testBlockingAcquire() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(1);
s.acquire();
Thread t = new Thread() {
@Override
public void run() {
RSemaphore s = redisson.getSemaphore("test");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.release();
}
};
t.start();
assertThat(s.availablePermits()).isEqualTo(0);
s.acquire();
assertThat(s.tryAcquire()).isFalse();
assertThat(s.availablePermits()).isEqualTo(0);
}
@Test
public void testBlockingNAcquire() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(5);
s.acquire(3);
Thread t = new Thread() {
@Override
public void run() {
RSemaphore s = redisson.getSemaphore("test");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.release();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.release();
}
};
assertThat(s.availablePermits()).isEqualTo(2);
t.start();
s.acquire(4);
assertThat(s.availablePermits()).isEqualTo(0);
}
@Test
public void testTryNAcquire() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(5);
assertThat(s.tryAcquire(3)).isTrue();
Thread t = new Thread() {
@Override
public void run() {
RSemaphore s = redisson.getSemaphore("test");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.release();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.release();
}
};
assertThat(s.tryAcquire(4)).isFalse();
t.start();
t.join(1);
long startTime = System.currentTimeMillis();
assertThat(s.tryAcquire(4, 2, TimeUnit.SECONDS)).isTrue();
assertThat(System.currentTimeMillis() - startTime).isBetween(900L, 1020L);
assertThat(s.availablePermits()).isEqualTo(0);
}
@Test
public void testReleaseWithoutPermits() {
RSemaphore s = redisson.getSemaphore("test");
s.release();
assertThat(s.availablePermits()).isEqualTo(1);
}
@Test
public void testDrainPermits() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(10);
s.acquire(3);
assertThat(s.drainPermits()).isEqualTo(7);
assertThat(s.availablePermits()).isEqualTo(0);
}
@Test
public void testReleaseAcquire() throws InterruptedException {
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(10);
s.acquire();
assertThat(s.availablePermits()).isEqualTo(9);
s.release();
assertThat(s.availablePermits()).isEqualTo(10);
s.acquire(5);
assertThat(s.availablePermits()).isEqualTo(5);
s.release(5);
assertThat(s.availablePermits()).isEqualTo(10);
}
@Test
public void testConcurrency_SingleInstance() throws InterruptedException {
final AtomicInteger lockedCounter = new AtomicInteger();
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(1);
int iterations = 15;
testSingleInstanceConcurrency(iterations, r -> {
RSemaphore s1 = r.getSemaphore("test");
try {
s1.acquire();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int value = lockedCounter.get();
lockedCounter.set(value + 1);
s1.release();
});
assertThat(lockedCounter.get()).isEqualTo(iterations);
}
@Test
public void testConcurrencyLoop_MultiInstance() throws InterruptedException {
final int iterations = 100;
final AtomicInteger lockedCounter = new AtomicInteger();
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(1);
testMultiInstanceConcurrency(16, r -> {
for (int i = 0; i < iterations; i++) {
try {
r.getSemaphore("test").acquire();
}catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
int value = lockedCounter.get();
lockedCounter.set(value + 1);
r.getSemaphore("test").release();
}
});
assertThat(lockedCounter.get()).isEqualTo(16 * iterations);
}
@Test
public void testConcurrency_MultiInstance_1_permits() throws InterruptedException {
int iterations = 30;
final AtomicInteger lockedCounter = new AtomicInteger();
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(1);
testMultiInstanceConcurrency(iterations, r -> {
RSemaphore s1 = r.getSemaphore("test");
try {
s1.acquire();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int value = lockedCounter.get();
lockedCounter.set(value + 1);
s1.release();
});
assertThat(lockedCounter.get()).isEqualTo(iterations);
}
@Test
public void testConcurrency_MultiInstance_10_permits() throws InterruptedException {
Assume.assumeFalse(RedissonRuntimeEnvironment.isTravis);
int iterations = 100;
final AtomicInteger lockedCounter = new AtomicInteger();
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(10);
final AtomicInteger checkPermits = new AtomicInteger(s.availablePermits());
final CyclicBarrier barrier = new CyclicBarrier(s.availablePermits());
testMultiInstanceConcurrencySequentiallyLaunched(iterations, r -> {
RSemaphore s1 = r.getSemaphore("test");
try {
s1.acquire();
barrier.await();
if (checkPermits.decrementAndGet() > 0) {
assertThat(s1.availablePermits()).isEqualTo(0);
assertThat(s1.tryAcquire()).isFalse();
} else {
Thread.sleep(50);
}
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int value = lockedCounter.get();
lockedCounter.set(value + 1);
s1.release();
});
System.out.println(lockedCounter.get());
assertThat(lockedCounter.get()).isLessThan(iterations);
}
}