1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.constructs.nonstop;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ThreadFactory;
23 import java.util.concurrent.atomic.AtomicInteger;
24
25 import junit.framework.Assert;
26 import junit.framework.TestCase;
27 import net.sf.ehcache.constructs.nonstop.ThreadDump.ThreadInformation;
28
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class ExecutorServiceTest extends TestCase {
33
34 private static final String TEST_EXECUTOR_THREAD_NAME_PREFIX = "Test Executor thread";
35 private NonstopExecutorServiceImpl service;
36 private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceTest.class);
37
38 @Override
39 protected void setUp() throws Exception {
40 int initialThreadsCount = countExecutorThreads();
41 LOG.info("Initial thread count: " + initialThreadsCount);
42 Assert.assertEquals(0, initialThreadsCount);
43 service = new NonstopExecutorServiceImpl(new ThreadFactory() {
44 private final AtomicInteger count = new AtomicInteger();
45
46 public Thread newThread(Runnable r) {
47 Thread thread = new Thread(r, TEST_EXECUTOR_THREAD_NAME_PREFIX + "-" + count.incrementAndGet() + " [for '"
48 + Thread.currentThread().getName() + "']");
49 thread.setDaemon(true);
50 return thread;
51 }
52 });
53 }
54
55 @Override
56 protected void tearDown() throws Exception {
57 service.shutdown();
58 Thread.sleep(2000);
59 int threads = countExecutorThreads();
60 LOG.info("After shutting down service, thread count: " + threads);
61 Assert.assertEquals(0, threads);
62 LOG.info("Test complete successfully");
63 }
64
65 public void testOnlyOneExecutorThreadCreated() throws Exception {
66 int initialThreadsCount = countExecutorThreads();
67 int numOps = 100;
68 for (int i = 0; i < numOps; i++) {
69 service.execute(new NoopCallable(), 5000);
70 }
71
72 int actualThreadCount = countExecutorThreads() - initialThreadsCount;
73 assertEquals("ActualThreadCount: " + actualThreadCount + " Expected to be 1", 1, actualThreadCount);
74 }
75
76 public void testOneExecutorThreadCreatedPerAppThread() throws Exception {
77 int initialThreadsCount = countExecutorThreads();
78
79 List<Thread> requestThreads = new ArrayList<Thread>();
80 int extraRequests = 20;
81 for (int i = 0; i < extraRequests; i++) {
82 Thread thread = new Thread(new Runnable() {
83 public void run() {
84 try {
85 service.execute(new NoopCallable(), 5000);
86 } catch (Exception e) {
87 fail("Executing noopCallable should not fail");
88 }
89 }
90 }, "RequestThread-" + i);
91 requestThreads.add(thread);
92 thread.start();
93 }
94 for (Thread t : requestThreads) {
95 t.join();
96 }
97 Assert.assertEquals(extraRequests, countExecutorThreads() - initialThreadsCount);
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 private int countExecutorThreads() {
118 List<ThreadInformation> threadDump = ThreadDump.getThreadDump();
119 int rv = 0;
120 List<ThreadInformation> threads = new ArrayList();
121 for (ThreadInformation info : threadDump) {
122 if (info.getThreadName().contains(TEST_EXECUTOR_THREAD_NAME_PREFIX)) {
123
124
125 threads.add(info);
126 rv++;
127 }
128 }
129 LOG.info("Counting number of executor threads created till now: " + rv);
130 String string = "{";
131 for (ThreadInformation info : threads) {
132 string += info.getThreadName() + " [id=" + info.getThreadId() + "], ";
133 }
134 string += "}";
135 LOG.info("Thread name/ids: " + string);
136 return rv;
137 }
138
139 private static class NoopCallable implements Callable<Void> {
140
141 public Void call() throws Exception {
142
143 return null;
144 }
145
146 }
147
148 }