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"; } } }