PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/test/java/org/jclouds/concurrent/config/ExecutorServiceModuleTest.java

https://github.com/ddurnev/jclouds
Java | 258 lines | 142 code | 43 blank | 73 comment | 2 complexity | 32d7dc2178292112b827c715f4ba6732 MD5 | raw file
  1. /**
  2. * Licensed to jclouds, Inc. (jclouds) under one or more
  3. * contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. jclouds licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.jclouds.concurrent.config;
  20. import static org.easymock.EasyMock.expect;
  21. import static org.easymock.classextension.EasyMock.createMock;
  22. import static org.easymock.classextension.EasyMock.replay;
  23. import static org.easymock.classextension.EasyMock.verify;
  24. import static org.testng.Assert.assertEquals;
  25. import java.io.IOException;
  26. import java.util.concurrent.Callable;
  27. import java.util.concurrent.ExecutionException;
  28. import java.util.concurrent.ExecutorService;
  29. import java.util.concurrent.Future;
  30. import org.jclouds.Constants;
  31. import org.jclouds.lifecycle.Closer;
  32. import org.testng.annotations.Test;
  33. import com.google.common.base.Throwables;
  34. import com.google.common.collect.ImmutableList;
  35. import com.google.inject.Guice;
  36. import com.google.inject.Injector;
  37. import com.google.inject.Key;
  38. import com.google.inject.name.Names;
  39. /**
  40. *
  41. * @author Adrian Cole
  42. */
  43. @Test
  44. public class ExecutorServiceModuleTest {
  45. @Test
  46. public void testShutdownOnClose() throws IOException {
  47. Injector i = Guice.createInjector();
  48. Closer closer = i.getInstance(Closer.class);
  49. ExecutorService executor = createMock(ExecutorService.class);
  50. ExecutorServiceModule.shutdownOnClose(executor, closer);
  51. expect(executor.shutdownNow()).andReturn(ImmutableList.<Runnable> of()).atLeastOnce();
  52. replay(executor);
  53. closer.close();
  54. verify(executor);
  55. }
  56. @Test
  57. public void testShutdownOnCloseThroughModule() throws IOException {
  58. ExecutorServiceModule module = new ExecutorServiceModule() {
  59. @Override
  60. protected void configure() {
  61. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
  62. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
  63. super.configure();
  64. }
  65. };
  66. Injector i = Guice.createInjector(module);
  67. assertEquals(module.userExecutorFromConstructor, null);
  68. assertEquals(module.ioExecutorFromConstructor, null);
  69. Closer closer = i.getInstance(Closer.class);
  70. ExecutorService user = i
  71. .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
  72. ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
  73. .named(Constants.PROPERTY_IO_WORKER_THREADS)));
  74. assert !user.isShutdown();
  75. assert !io.isShutdown();
  76. closer.close();
  77. assert user.isShutdown();
  78. assert io.isShutdown();
  79. }
  80. @Test
  81. public void testDescribedFutureToString() throws Exception {
  82. ExecutorServiceModule module = new ExecutorServiceModule() {
  83. @Override
  84. protected void configure() {
  85. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
  86. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
  87. super.configure();
  88. }
  89. };
  90. Injector i = Guice.createInjector(module);
  91. Closer closer = i.getInstance(Closer.class);
  92. ExecutorService user = i
  93. .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
  94. ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
  95. .named(Constants.PROPERTY_IO_WORKER_THREADS)));
  96. ConfigurableRunner t1 = new ConfigurableRunner();
  97. t1.result = "okay";
  98. Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
  99. assert euc.toString().indexOf("ConfigurableRunner") >= 0;
  100. assert euc.get().equals("okay");
  101. Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
  102. assert eic.toString().indexOf("ConfigurableRunner") >= 0;
  103. assert eic.get().equals("okay");
  104. closer.close();
  105. }
  106. /*
  107. * The decoration makes sure that the stack trace looks like the following.
  108. * Note the last three included trace elements: this details where the task was submitted _from_
  109. * (technically it is a different stack frame, since it is across threads; but logically it is the same)
  110. *
  111. java.util.concurrent.ExecutionException: java.lang.IllegalStateException: foo
  112. at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
  113. at java.util.concurrent.FutureTask.get(FutureTask.java:83)
  114. at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.get(ExecutorServiceModule.java:232)
  115. at org.jclouds.concurrent.config.ExecutorServiceModuleTest.checkFutureGetFailsWith(ExecutorServiceModuleTest.java:186)
  116. at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:171)
  117. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  118. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  119. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  120. at java.lang.reflect.Method.invoke(Method.java:597)
  121. at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
  122. at org.testng.internal.Invoker.invokeMethod(Invoker.java:691)
  123. at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:883)
  124. at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1208)
  125. at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
  126. at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
  127. at org.testng.TestRunner.privateRun(TestRunner.java:753)
  128. at org.testng.TestRunner.run(TestRunner.java:613)
  129. at org.testng.SuiteRunner.runTest(SuiteRunner.java:335)
  130. at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:330)
  131. at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
  132. at org.testng.SuiteRunner.run(SuiteRunner.java:241)
  133. at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
  134. at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
  135. at org.testng.TestNG.runSuitesSequentially(TestNG.java:1169)
  136. at org.testng.TestNG.runSuitesLocally(TestNG.java:1094)
  137. at org.testng.TestNG.run(TestNG.java:1006)
  138. at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:107)
  139. at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:199)
  140. at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:170)
  141. Caused by: java.lang.IllegalStateException: foo
  142. at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.call(ExecutorServiceModuleTest.java:206)
  143. at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.run(ExecutorServiceModuleTest.java:203)
  144. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
  145. at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
  146. at java.util.concurrent.FutureTask.run(FutureTask.java:138)
  147. at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
  148. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
  149. at java.lang.Thread.run(Thread.java:637)
  150. at org.jclouds.concurrent.config.ExecutorServiceModule$DescribingExecutorService.submit(ExecutorServiceModule.java:188)
  151. at org.jclouds.concurrent.config.ExecutorServiceModuleTest.performSubmissionInSeparateMethod2(ExecutorServiceModuleTest.java:181)
  152. at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:170)
  153. ... 24 more
  154. *
  155. */
  156. @Test
  157. public void testDescribedFutureExceptionIncludesSubmissionTrace() throws Exception {
  158. ExecutorServiceModule module = new ExecutorServiceModule() {
  159. @Override
  160. protected void configure() {
  161. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
  162. bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
  163. super.configure();
  164. }
  165. };
  166. Injector i = Guice.createInjector(module);
  167. Closer closer = i.getInstance(Closer.class);
  168. ExecutorService user = i
  169. .getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
  170. ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
  171. .named(Constants.PROPERTY_IO_WORKER_THREADS)));
  172. ConfigurableRunner t1 = new ConfigurableRunner();
  173. t1.failMessage = "foo";
  174. t1.result = "shouldn't happen";
  175. Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
  176. checkFutureGetFailsWith(euc, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
  177. Future<Object> eur = performSubmissionInSeparateMethod2(user, t1);
  178. checkFutureGetFailsWith(eur, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
  179. Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
  180. checkFutureGetFailsWith(eic, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
  181. Future<Object> eir = performSubmissionInSeparateMethod2(io, t1);
  182. checkFutureGetFailsWith(eir, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
  183. closer.close();
  184. }
  185. static Future<Object> performSubmissionInSeparateMethod1(ExecutorService user, ConfigurableRunner t1) {
  186. return user.submit((Callable<Object>)t1);
  187. }
  188. static Future<Object> performSubmissionInSeparateMethod2(ExecutorService io, ConfigurableRunner t1) {
  189. return io.submit((Runnable)t1, (Object)"shouldn't happen");
  190. }
  191. static void checkFutureGetFailsWith(Future<Object> task, String ...requiredPhrases) throws Exception {
  192. try {
  193. task.get();
  194. assert false : "task should have failed";
  195. } catch (ExecutionException e) {
  196. String trace = Throwables.getStackTraceAsString(e);
  197. for (String requiredPhrase : requiredPhrases) {
  198. assert trace.indexOf(requiredPhrase) >= 0 : "stack trace should have contained '"+requiredPhrase+"'";
  199. }
  200. }
  201. }
  202. private static class ConfigurableRunner implements Runnable, Callable<Object> {
  203. private Object result;
  204. private String failMessage;
  205. @Override
  206. public void run() {
  207. call();
  208. }
  209. public Object call() {
  210. if (failMessage!=null) throw new IllegalStateException(failMessage);
  211. return result;
  212. }
  213. }
  214. }