package org.infinispan.executors;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.infinispan.test.AbstractInfinispanTest;
import org.infinispan.test.TestingUtil;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
@Test(groups = "functional", testName = "executors.ExecutorAllCompletionServiceTest")
public class ExecutorAllCompletionServiceTest extends AbstractInfinispanTest {
private ExecutorService lastExecutorService;
@AfterClass(alwaysRun = true)
public void stopExecutors() {
if (lastExecutorService != null) {
lastExecutorService.shutdownNow();
}
}
public void testWaitForAll() {
ExecutorAllCompletionService service = createService(1);
long before = System.currentTimeMillis();
service.submit(new WaitRunnable(500), null);
service.submit(new WaitRunnable(500), null);
service.waitUntilAllCompleted();
long after = System.currentTimeMillis();
assertTrue(after - before >= 1000);
assertTrue(service.isAllCompleted());
assertFalse(service.isExceptionThrown());
}
public void testExceptions() {
ExecutorAllCompletionService service = createService(1);
service.submit(new WaitRunnable(1), null);
service.submit(new ExceptionRunnable("second"), null);
service.submit(new WaitRunnable(1), null);
service.submit(new ExceptionRunnable("third"), null);
service.waitUntilAllCompleted();
assertTrue(service.isAllCompleted());
assertTrue(service.isExceptionThrown());
assertEquals("second", findCause(service.getFirstException()).getMessage());
}
public void testParallelWait() throws InterruptedException {
final ExecutorAllCompletionService service = createService(2);
for (int i = 0; i < 300; ++i) {
service.submit(new WaitRunnable(10), null);
}
List<Thread> threads = new ArrayList<>(10);
for (int i = 0; i < 10; ++i) {
Thread t = new Thread(() -> {
service.waitUntilAllCompleted();
assertTrue(service.isAllCompleted());
assertFalse(service.isExceptionThrown());
});
threads.add(t);
t.start();
}
for (Thread t : threads) {
t.join();
}
assertTrue(service.isAllCompleted());
assertFalse(service.isExceptionThrown());
}
public void testParallelException() throws InterruptedException {
final ExecutorAllCompletionService service = createService(2);
for (int i = 0; i < 150; ++i) {
service.submit(new WaitRunnable(10), null);
}
service.submit(new ExceptionRunnable("foobar"), null);
for (int i = 0; i < 150; ++i) {
service.submit(new WaitRunnable(10), null);
}
List<Thread> threads = new ArrayList<>(10);
for (int i = 0; i < 10; ++i) {
Thread t = new Thread(() -> {
service.waitUntilAllCompleted();
assertTrue(service.isAllCompleted());
assertTrue(service.isExceptionThrown());
});
threads.add(t);
t.start();
}
for (Thread t : threads) {
t.join();
}
assertTrue(service.isAllCompleted());
assertTrue(service.isExceptionThrown());
}
private Throwable findCause(ExecutionException e) {
Throwable t = e;
while (t.getCause() != null) t = t.getCause();
return t;
}
private ExecutorAllCompletionService createService(int maxThreads) {
if (lastExecutorService != null) {
lastExecutorService.shutdownNow();
}
lastExecutorService = Executors.newFixedThreadPool(maxThreads, getTestThreadFactory("Worker"));
return new ExecutorAllCompletionService(lastExecutorService);
}
private class WaitRunnable implements Runnable {
private long period;
private WaitRunnable(long period) {
this.period = period;
}
@Override
public void run() {
TestingUtil.sleepThread(period);
}
}
private class ExceptionRunnable implements Runnable {
private final String message;
public ExceptionRunnable(String message) {
this.message = message;
}
@Override
public void run() {
throw new RuntimeException(message);
}
}
}