/core/src/test/java/org/jclouds/concurrent/config/ExecutorServiceModuleTest.java
Java | 258 lines | 142 code | 43 blank | 73 comment | 2 complexity | 32d7dc2178292112b827c715f4ba6732 MD5 | raw file
- /**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds licenses this file
- * to you 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 org.jclouds.concurrent.config;
- import static org.easymock.EasyMock.expect;
- import static org.easymock.classextension.EasyMock.createMock;
- import static org.easymock.classextension.EasyMock.replay;
- import static org.easymock.classextension.EasyMock.verify;
- import static org.testng.Assert.assertEquals;
- import java.io.IOException;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Future;
- import org.jclouds.Constants;
- import org.jclouds.lifecycle.Closer;
- import org.testng.annotations.Test;
- import com.google.common.base.Throwables;
- import com.google.common.collect.ImmutableList;
- import com.google.inject.Guice;
- import com.google.inject.Injector;
- import com.google.inject.Key;
- import com.google.inject.name.Names;
- /**
- *
- * @author Adrian Cole
- */
- @Test
- public class ExecutorServiceModuleTest {
- @Test
- public void testShutdownOnClose() throws IOException {
- Injector i = Guice.createInjector();
- Closer closer = i.getInstance(Closer.class);
- ExecutorService executor = createMock(ExecutorService.class);
- ExecutorServiceModule.shutdownOnClose(executor, closer);
- expect(executor.shutdownNow()).andReturn(ImmutableList.<Runnable> of()).atLeastOnce();
- replay(executor);
- closer.close();
- verify(executor);
- }
- @Test
- public void testShutdownOnCloseThroughModule() throws IOException {
- ExecutorServiceModule module = new ExecutorServiceModule() {
- @Override
- protected void configure() {
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
- super.configure();
- }
- };
-
- Injector i = Guice.createInjector(module);
- assertEquals(module.userExecutorFromConstructor, null);
- assertEquals(module.ioExecutorFromConstructor, null);
- Closer closer = i.getInstance(Closer.class);
- ExecutorService user = i
- .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
- ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
- .named(Constants.PROPERTY_IO_WORKER_THREADS)));
- assert !user.isShutdown();
- assert !io.isShutdown();
- closer.close();
- assert user.isShutdown();
- assert io.isShutdown();
- }
-
- @Test
- public void testDescribedFutureToString() throws Exception {
-
- ExecutorServiceModule module = new ExecutorServiceModule() {
- @Override
- protected void configure() {
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
- super.configure();
- }
- };
-
- Injector i = Guice.createInjector(module);
- Closer closer = i.getInstance(Closer.class);
-
- ExecutorService user = i
- .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
- ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
- .named(Constants.PROPERTY_IO_WORKER_THREADS)));
- ConfigurableRunner t1 = new ConfigurableRunner();
- t1.result = "okay";
-
- Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
- assert euc.toString().indexOf("ConfigurableRunner") >= 0;
- assert euc.get().equals("okay");
- Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
- assert eic.toString().indexOf("ConfigurableRunner") >= 0;
- assert eic.get().equals("okay");
-
- closer.close();
- }
- /*
- * The decoration makes sure that the stack trace looks like the following.
- * Note the last three included trace elements: this details where the task was submitted _from_
- * (technically it is a different stack frame, since it is across threads; but logically it is the same)
- *
- java.util.concurrent.ExecutionException: java.lang.IllegalStateException: foo
- at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
- at java.util.concurrent.FutureTask.get(FutureTask.java:83)
- at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.get(ExecutorServiceModule.java:232)
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest.checkFutureGetFailsWith(ExecutorServiceModuleTest.java:186)
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:171)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
- at org.testng.internal.Invoker.invokeMethod(Invoker.java:691)
- at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:883)
- at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1208)
- at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
- at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
- at org.testng.TestRunner.privateRun(TestRunner.java:753)
- at org.testng.TestRunner.run(TestRunner.java:613)
- at org.testng.SuiteRunner.runTest(SuiteRunner.java:335)
- at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:330)
- at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
- at org.testng.SuiteRunner.run(SuiteRunner.java:241)
- at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
- at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
- at org.testng.TestNG.runSuitesSequentially(TestNG.java:1169)
- at org.testng.TestNG.runSuitesLocally(TestNG.java:1094)
- at org.testng.TestNG.run(TestNG.java:1006)
- at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:107)
- at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:199)
- at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:170)
- Caused by: java.lang.IllegalStateException: foo
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.call(ExecutorServiceModuleTest.java:206)
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.run(ExecutorServiceModuleTest.java:203)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
- at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
- at java.util.concurrent.FutureTask.run(FutureTask.java:138)
- at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
- at java.lang.Thread.run(Thread.java:637)
- at org.jclouds.concurrent.config.ExecutorServiceModule$DescribingExecutorService.submit(ExecutorServiceModule.java:188)
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest.performSubmissionInSeparateMethod2(ExecutorServiceModuleTest.java:181)
- at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:170)
- ... 24 more
- *
- */
- @Test
- public void testDescribedFutureExceptionIncludesSubmissionTrace() throws Exception {
-
- ExecutorServiceModule module = new ExecutorServiceModule() {
- @Override
- protected void configure() {
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
- bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
- super.configure();
- }
- };
- Injector i = Guice.createInjector(module);
- Closer closer = i.getInstance(Closer.class);
-
- ExecutorService user = i
- .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
- ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
- .named(Constants.PROPERTY_IO_WORKER_THREADS)));
- ConfigurableRunner t1 = new ConfigurableRunner();
- t1.failMessage = "foo";
- t1.result = "shouldn't happen";
-
- Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
- checkFutureGetFailsWith(euc, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
-
- Future<Object> eur = performSubmissionInSeparateMethod2(user, t1);
- checkFutureGetFailsWith(eur, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
-
- Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
- checkFutureGetFailsWith(eic, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
-
- Future<Object> eir = performSubmissionInSeparateMethod2(io, t1);
- checkFutureGetFailsWith(eir, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
-
- closer.close();
- }
- static Future<Object> performSubmissionInSeparateMethod1(ExecutorService user, ConfigurableRunner t1) {
- return user.submit((Callable<Object>)t1);
- }
-
- static Future<Object> performSubmissionInSeparateMethod2(ExecutorService io, ConfigurableRunner t1) {
- return io.submit((Runnable)t1, (Object)"shouldn't happen");
- }
-
- static void checkFutureGetFailsWith(Future<Object> task, String ...requiredPhrases) throws Exception {
- try {
- task.get();
- assert false : "task should have failed";
- } catch (ExecutionException e) {
- String trace = Throwables.getStackTraceAsString(e);
- for (String requiredPhrase : requiredPhrases) {
- assert trace.indexOf(requiredPhrase) >= 0 : "stack trace should have contained '"+requiredPhrase+"'";
- }
- }
- }
- private static class ConfigurableRunner implements Runnable, Callable<Object> {
- private Object result;
- private String failMessage;
-
- @Override
- public void run() {
- call();
- }
- public Object call() {
- if (failMessage!=null) throw new IllegalStateException(failMessage);
- return result;
- }
- }
- }