package org.infinispan.executors;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertSame;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.infinispan.test.AbstractInfinispanTest;
import org.infinispan.util.concurrent.WithinThreadExecutor;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
/**
* Basic tests for {@link SemaphoreCompletionService}
*
* @author Dan Berindei
*/
@Test(groups = "functional", testName = "executors.SemaphoreCompletionServiceTest")
public class SemaphoreCompletionServiceTest extends AbstractInfinispanTest {
private final ExecutorService executor2Threads = Executors.newFixedThreadPool(2, getTestThreadFactory("Test"));
@AfterClass(alwaysRun = true)
public void stopExecutors() {
executor2Threads.shutdownNow();
}
public void testConcurrency1WithinThread() throws Exception {
SemaphoreCompletionService<String> completionService = new SemaphoreCompletionService<>(new WithinThreadExecutor(), 1);
Future<String> future1 = completionService.submit(new DummyTask());
Future<String> future2 = completionService.poll();
assertSame(future1, future2);
assertNotNull(future2);
assertEquals("bla", future2.get());
}
public void testConcurrencyLimit() throws Exception {
SemaphoreCompletionService<String> completionService = new SemaphoreCompletionService<>(executor2Threads, 1);
CountDownLatch latch = new CountDownLatch(1);
Future<String> blockingFuture = completionService.submit(new BlockingTask(latch));
Future<String> dummyFuture = completionService.submit(new DummyTask());
assertNull(completionService.poll(1, SECONDS));
assertFalse(dummyFuture.isDone());
latch.countDown();
assertEquals("bla", blockingFuture.get(10, SECONDS));
assertEquals("bla", dummyFuture.get(10, SECONDS));
}
public void testBackgroundTasks() throws Exception {
SemaphoreCompletionService<String> completionService = new SemaphoreCompletionService<>(executor2Threads, 1);
CountDownLatch latch = new CountDownLatch(1);
Future<String> backgroundInitFuture = completionService.submit(new BackgroundInitTask(completionService));
assertEquals("bla", backgroundInitFuture.get(1, SECONDS));
Future<String> dummyFuture = completionService.submit(new DummyTask());
assertSame(backgroundInitFuture, completionService.poll(1, SECONDS));
assertFalse(dummyFuture.isDone());
Future<String> backgroundEndFuture = completionService.backgroundTaskFinished(new BlockingTask(latch));
assertNull(completionService.poll(1, SECONDS));
assertFalse(dummyFuture.isDone());
latch.countDown();
assertEquals("bla", backgroundEndFuture.get(10, SECONDS));
assertEquals("bla", dummyFuture.get(10, SECONDS));
}
private static class DummyTask implements Callable<String> {
@Override
public String call() throws Exception {
return "bla";
}
}
private static class BlockingTask implements Callable<String> {
private final CountDownLatch latch;
private BlockingTask(CountDownLatch latch) {
this.latch = latch;
}
@Override
public String call() throws Exception {
latch.await(30, SECONDS);
return "bla";
}
}
private static class BackgroundInitTask implements Callable<String> {
private final SemaphoreCompletionService<String> completionService;
private BackgroundInitTask(SemaphoreCompletionService<String> completionService) {
this.completionService = completionService;
}
@Override
public String call() throws Exception {
completionService.continueTaskInBackground();
return "bla";
}
}
}