/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.core; import com.hazelcast.impl.GroupProperties; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; import static org.junit.Assert.*; /** * Testing suite for ExecutorService * * @author Marco Ferrante, DISI - University of Genoa * @oztalip */ @RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class) public class ExecutorServiceTest { public static int COUNT = 1000; @BeforeClass @AfterClass public static void init() throws Exception { System.setProperty(GroupProperties.PROP_WAIT_SECONDS_BEFORE_JOIN, "1"); System.setProperty(GroupProperties.PROP_VERSION_CHECK_ENABLED, "false"); Hazelcast.shutdownAll(); } @After public void cleanup() throws Exception { Hazelcast.shutdownAll(); } /** * Get a service instance. */ @Test public void testGetExecutorService() { ExecutorService executor = Hazelcast.getExecutorService(); assertNotNull(executor); } public static class BasicTestTask implements Callable<String>, Serializable { public static String RESULT = "Task completed"; public String call() throws Exception { return RESULT; } } public static class CancellationAwareTask implements Callable<Boolean>, Serializable { long sleepTime = 10000; public CancellationAwareTask(long sleepTime) { this.sleepTime = sleepTime; } public Boolean call() throws InterruptedException { Thread.sleep(sleepTime); return Boolean.TRUE; } } public static class NestedExecutorTask implements Callable<String>, Serializable { public String call() throws Exception { Future future = Hazelcast.getExecutorService().submit(new BasicTestTask()); return (String) future.get(); } } public static class MemberCheck implements Callable<Member>, Serializable { public Member call() throws Exception { return Hazelcast.getCluster().getLocalMember(); } } @Test public void testIssue292() throws Exception { final BlockingQueue qResponse = new ArrayBlockingQueue(1); Hazelcast.getDefaultInstance();//instance creation Thread thread = new Thread(new Runnable() { public void run() { try { DistributedTask<Member> dtask = new DistributedTask<Member>(new MemberCheck()); Hazelcast.getExecutorService().submit(dtask);//instance usage Member member = dtask.get(); qResponse.offer(member); } catch (Throwable e) { qResponse.offer(e); } } }); thread.start(); Object response = qResponse.poll(10, TimeUnit.SECONDS); assertNotNull(response); assertTrue(response instanceof Member); } /** * Submit a null task must raise a NullPointerException */ @Test public void submitNullTask() throws Exception { ExecutorService executor = Hazelcast.getExecutorService(); try { Callable c = null; Future future = executor.submit(c); fail(); } catch (NullPointerException npe) { // It's ok } } /** * Run a basic task */ @Test public void testBasicTask() throws Exception { Callable<String> task = new BasicTestTask(); ExecutorService executor = Hazelcast.getExecutorService(); Future future = executor.submit(task); assertEquals(future.get(), BasicTestTask.RESULT); } @Test public void testCancellationAwareTask() { CancellationAwareTask task = new CancellationAwareTask(10000); ExecutorService executor = Hazelcast.getExecutorService(); Future future = executor.submit(task); try { future.get(2, TimeUnit.SECONDS); } catch (TimeoutException expected) { } catch (Exception e) { fail("No other Exception!!"); } assertFalse(future.isDone()); assertTrue(future.cancel(true)); assertTrue(future.isCancelled()); try { future.get(); fail("Should not complete the task successfully"); } catch (CancellationException e) { // expected } catch (Exception e) { fail("Unexpected exception " + e.getMessage()); } } /** * Test the method isDone() */ @Test public void isDoneMethod() throws Exception { Callable<String> task = new BasicTestTask(); ExecutorService executor = Hazelcast.getExecutorService(); Future future = executor.submit(task); if (future.isDone()) { assertTrue(future.isDone()); } assertEquals(future.get(), BasicTestTask.RESULT); assertTrue(future.isDone()); } /** * Test for the issue 129. * Repeatedly runs tasks and check for isDone() status after * get(). */ @Test public void isDoneMethod2() throws Exception { ExecutorService executor = Hazelcast.getExecutorService(); for (int i = 0; i < COUNT; i++) { Callable<String> task1 = new BasicTestTask(); Callable<String> task2 = new BasicTestTask(); Future future1 = executor.submit(task1); Future future2 = executor.submit(task2); assertEquals(future2.get(), BasicTestTask.RESULT); assertTrue(future2.isDone()); assertEquals(future1.get(), BasicTestTask.RESULT); assertTrue(future1.isDone()); } } /** * Test the Execution Callback */ @Test public void testExecutionCallback() throws Exception { Callable<String> task = new BasicTestTask(); ExecutorService executor = Hazelcast.getExecutorService(); DistributedTask dtask = new DistributedTask(task); final CountDownLatch latch = new CountDownLatch(1); dtask.setExecutionCallback(new ExecutionCallback() { public void done(Future future) { assertTrue(future.isDone()); try { assertEquals(future.get(), BasicTestTask.RESULT); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } } }); Future future = executor.submit(dtask); assertTrue(latch.await(2, TimeUnit.SECONDS)); assertTrue(future.isDone()); assertEquals(future.get(), BasicTestTask.RESULT); assertTrue(future.isDone()); } /** * Execute a task that is executing * something else inside. Nested Execution. */ @Test(timeout = 10000) public void testNestedExecution() throws Exception { Callable<String> task = new NestedExecutorTask(); ExecutorService executor = Hazelcast.getExecutorService(); Future future = executor.submit(task); future.get(); } /** * Test multiple Future.get() invocation */ @Test public void isTwoGetFromFuture() throws Exception { Callable<String> task = new BasicTestTask(); ExecutorService executor = Hazelcast.getExecutorService(); Future<String> future = executor.submit(task); String s1 = future.get(); assertEquals(s1, BasicTestTask.RESULT); assertTrue(future.isDone()); String s2 = future.get(); assertEquals(s2, BasicTestTask.RESULT); assertTrue(future.isDone()); String s3 = future.get(); assertEquals(s3, BasicTestTask.RESULT); assertTrue(future.isDone()); String s4 = future.get(); assertEquals(s4, BasicTestTask.RESULT); assertTrue(future.isDone()); } /** * invokeAll tests */ @Test public void testInvokeAll() throws Exception { Callable<String> task = new BasicTestTask(); ExecutorService executor = Hazelcast.getExecutorService(); assertFalse(executor.isShutdown()); // Only one task ArrayList<Callable<String>> tasks = new ArrayList<Callable<String>>(); tasks.add(new BasicTestTask()); List<Future<String>> futures = executor.invokeAll(tasks); assertEquals(futures.size(), 1); assertEquals(futures.get(0).get(), BasicTestTask.RESULT); // More tasks tasks.clear(); for (int i = 0; i < COUNT; i++) { tasks.add(new BasicTestTask()); } futures = executor.invokeAll(tasks); assertEquals(futures.size(), COUNT); for (int i = 0; i < COUNT; i++) { assertEquals(futures.get(i).get(), BasicTestTask.RESULT); } } /** * Shutdown-related method behaviour when the cluster is running */ @Test public void testShutdownBehaviour() throws Exception { ExecutorService executor = Hazelcast.getExecutorService(); // Fresh instance, is not shutting down assertFalse(executor.isShutdown()); assertFalse(executor.isTerminated()); executor.shutdown(); assertTrue(executor.isShutdown()); assertTrue(executor.isTerminated()); // shutdownNow() should return an empty list and be ignored List<Runnable> pending = executor.shutdownNow(); assertTrue(pending.isEmpty()); assertTrue(executor.isShutdown()); assertTrue(executor.isTerminated()); // awaitTermination() should return immediately false try { boolean terminated = executor.awaitTermination(60L, TimeUnit.SECONDS); assertFalse(terminated); } catch (InterruptedException ie) { fail("InterruptedException"); } assertTrue(executor.isShutdown()); assertTrue(executor.isTerminated()); } /** * Shutting down the cluster should act as the ExecutorService shutdown */ @Test public void testClusterShutdown() throws Exception { ExecutorService executor = Hazelcast.getExecutorService(); Hazelcast.shutdown(); Thread.sleep(2000); assertNotNull(executor); assertTrue(executor.isShutdown()); assertTrue(executor.isTerminated()); // New tasks must be rejected Callable<String> task = new BasicTestTask(); try { Future future = executor.submit(task); fail("Should not be here!"); } catch (RejectedExecutionException ree) { ; // It's ok } // Reanimate Hazelcast Hazelcast.restart(); executor = Hazelcast.getExecutorService(); assertFalse(executor.isShutdown()); assertFalse(executor.isTerminated()); Future future = executor.submit(task); } }