package org.infinispan.distexec; import static org.infinispan.test.Exceptions.expectException; import java.io.Serializable; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.infinispan.Cache; import org.infinispan.distribution.BaseDistFunctionalTest; import org.infinispan.marshall.core.ExternalPojo; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.testng.AssertJUnit; import org.testng.annotations.Test; /** * Tests org.infinispan.distexec.DistributedExecutorService * * @author Vladimir Blagojevic * @author Anna Manukyan */ @Test(groups = "functional", testName = "distexec.DistributedExecutionCompletionTest") public class DistributedExecutionCompletionTest extends BaseDistFunctionalTest<Object, String> { private static Log log = LogFactory.getLog(DistributedExecutionCompletionTest.class); public DistributedExecutionCompletionTest() { } @Override protected void createCacheManagers() throws Throwable { super.createCacheManagers(); } public void testBasicInvocation() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); try { DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); decs.submit(new SimpleCallable()); CompletableFuture<Integer> future = decs.take(); Integer r = future.get(); AssertJUnit.assertEquals(1, r.intValue()); } finally { des.shutdownNow(); } } public void testBasicDistributedCallableWitkKeys() throws Exception { c1.put("key1", "Manik"); c1.put("key2", "Mircea"); c1.put("key3", "Galder"); c1.put("key4", "Sanne"); DistributedExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Boolean> decs = new DistributedExecutionCompletionService<>(des); try { decs.submit(new SimpleDistributedCallable(true), "key1", "key2"); Future<Boolean> future = decs.take(); Boolean r = future.get(); assert r; } finally { des.shutdownNow(); } } public void testDistributedCallableEverywhereWithKeys() throws Exception { c1.put("key1", "Manik"); c1.put("key2", "Mircea"); c1.put("key3", "Galder"); c1.put("key4", "Sanne"); DefaultExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Boolean> decs = new DistributedExecutionCompletionService<>(des); try { decs.submitEverywhere(new SimpleDistributedCallable(true), "key1", "key2"); Future<Boolean> f; int counter = 0; while ((f = decs.poll(1,TimeUnit.SECONDS)) != null) { assert f.get(); counter++; } AssertJUnit.assertTrue("Counter greater than 0", counter > 0); } finally { des.shutdownNow(); } } public void testDistributedCallableEverywhere() throws Exception { DefaultExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Boolean> decs = new DistributedExecutionCompletionService<>(des); try { decs.submitEverywhere(new SimpleDistributedCallable(false)); Future<Boolean> f; int counter = 0; while ((f = decs.poll(1,TimeUnit.SECONDS)) != null) { assert f.get(); counter++; } AssertJUnit.assertTrue("Counter greater than 0", counter > 0); } finally { des.shutdownNow(); } } public void testBasicInvocationWithNullExecutor() throws Exception { DistributedExecutorService des = null; expectException(NullPointerException.class, () -> new DistributedExecutionCompletionService(des)); } public void testBasicInvocationWithNullTask() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); try { DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); expectException(NullPointerException.class, () -> decs.submit(null)); } finally { des.shutdownNow(); } } public void testBasicInvocationWithBlockingQueue() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); try { BlockingQueue<CompletableFuture<Integer>> queue = new ArrayBlockingQueue<>(10); DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des, queue); decs.submit(new SimpleCallable()); CompletableFuture<Integer> future = decs.take(); Integer r = future.get(); AssertJUnit.assertEquals((Integer) 1, r); } finally { des.shutdownNow(); } } public void testBasicInvocationWithRunnable() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); try { DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); Integer result = 5; decs.submit(new SimpleRunnable(), result); CompletableFuture<Integer> future = decs.take(); Integer r = future.get(); AssertJUnit.assertEquals(result, r); } finally { des.shutdownNow(); } } public void testBasicInvocationWithNullRunnable() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); try { DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); Integer result = 5; expectException(NullPointerException.class, () -> decs.submit(null, result)); } finally { des.shutdownNow(); } } public void testBasicPollInvocationWithSleepingCallable() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); try { decs.submit(new SimpleCallable(true, 5000)); CompletableFuture<Integer> callable = decs.poll(); AssertJUnit.assertNull(callable); } finally { des.shutdownNow(); } } public void testBasicTakeInvocationWithSleepingCallable() throws Exception { long sleepTime = 2000; DistributedExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); try { long start = System.currentTimeMillis(); decs.submit(new SimpleCallable(true, sleepTime)); CompletableFuture<Integer> future = decs.take(); long end = System.currentTimeMillis(); AssertJUnit.assertTrue("take() returned too soon", (end - start) >= sleepTime); AssertJUnit.assertTrue("take() returned, but future is not done yet", future.isDone()); AssertJUnit.assertEquals((Integer) 1, future.get()); } finally { des.shutdownNow(); } } public void testBasicPollInvocation() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); try { decs.submit(new SimpleCallable()); CompletableFuture<Integer> callable = decs.poll(1000, TimeUnit.MILLISECONDS); AssertJUnit.assertEquals((Integer) 1, callable.get()); } finally { des.shutdownNow(); } } public void testBasicPollInvocationWithTimeout() throws Exception { DistributedExecutorService des = new DefaultExecutorService(c1); DistributedExecutionCompletionService<Integer> decs = new DistributedExecutionCompletionService<>(des); try { decs.submit(new SimpleCallable(true,5000)); CompletableFuture<Integer> callable = decs.poll(10, TimeUnit.MILLISECONDS); AssertJUnit.assertNull(callable); } finally { des.shutdownNow(); } } static class SimpleDistributedCallable implements DistributedCallable<String, String, Boolean>, Serializable, ExternalPojo { /** The serialVersionUID */ private static final long serialVersionUID = 623845442163221832L; private boolean invokedProperly = false; private final boolean hasKeys; public SimpleDistributedCallable(boolean hasKeys) { this.hasKeys = hasKeys; } @Override public Boolean call() throws Exception { return invokedProperly; } @Override public void setEnvironment(Cache<String, String> cache, Set<String> inputKeys) { boolean keysProperlySet = hasKeys ? inputKeys != null && !inputKeys.isEmpty() : inputKeys != null && inputKeys.isEmpty(); invokedProperly = cache != null && keysProperlySet; } public boolean validlyInvoked() { return invokedProperly; } } static class SimpleCallable implements Callable<Integer>, Serializable, ExternalPojo { /** The serialVersionUID */ private static final long serialVersionUID = -8589149500259272402L; private boolean shouldSleep = false; private long sleepTime; public SimpleCallable() { } public SimpleCallable(boolean shouldSleep, long sleepTime) { this.shouldSleep = shouldSleep; this.sleepTime = sleepTime; } @Override public Integer call() throws Exception { if(shouldSleep) { Thread.sleep(sleepTime); } return 1; } } static class SimpleRunnable implements Runnable, Serializable { @Override public void run() { log.trace("This is a runnable!"); } } }