package org.dcache.util;
import org.junit.Before;
import org.junit.Test;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
public class AtomicCounterTest
{
private AtomicCounter counter;
private CountDownLatch latch;
@Before
public void setup()
{
latch = new CountDownLatch(1);
counter = new AtomicCounter() {
@Override
void inLock()
{
latch.countDown();
}
};
}
@Test
public void startsAtZero()
{
assertEquals(0, counter.get());
}
@Test
public void incrementByOne()
{
counter.increment();
assertEquals(1, counter.get());
}
@Test
public void incrementIsThreadSafe()
throws InterruptedException
{
final int THREADS = 5;
final int ITERATIONS = 100000;
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < THREADS; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
counter.increment();
}
}
});
}
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
assertEquals(THREADS * ITERATIONS, counter.get());
}
@Test
public void awaitReturnsImmediately()
throws InterruptedException
{
assertTrue(counter.awaitChangeUntil(1, new Date(System.currentTimeMillis() + 2000)));
}
@Test
public void awaitTimesOutInFuture()
throws InterruptedException
{
assertFalse(counter.awaitChangeUntil(0, new Date(System.currentTimeMillis() + 100)));
}
@Test
public void awaitTimesOutImmediately()
throws InterruptedException
{
assertFalse(counter.awaitChangeUntil(0, new Date(System.currentTimeMillis() - 100)));
}
@Test(expected=InterruptedException.class)
public void awaitIsInterruptible()
throws InterruptedException
{
Thread.currentThread().interrupt();
counter.awaitChangeUntil(0, new Date(System.currentTimeMillis() + 200));
}
@Test
public void incrementWakensAwait()
throws InterruptedException
{
ExecutorService executor = Executors.newCachedThreadPool();
try {
executor.execute(new Runnable() {
@Override
public void run() {
try {
latch.await();
counter.increment();
} catch (InterruptedException e) {
fail("Test was interrupted");
}
}
});
assertTrue(counter.awaitChangeUntil(0, new Date(System.currentTimeMillis() + 200)));
} finally {
executor.shutdownNow();
}
}
}