1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.grinder.engine.process;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertNotSame;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertSame;
30 import static org.junit.Assert.assertTrue;
31 import static org.junit.Assert.fail;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
36
37 import java.util.concurrent.Callable;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.Executors;
40 import java.util.concurrent.Future;
41
42 import net.grinder.common.ThreadLifeCycleListener;
43 import net.grinder.communication.QueuedSender;
44 import net.grinder.engine.process.GrinderProcess.ThreadContexts;
45 import net.grinder.engine.process.GrinderProcess.ThreadSynchronisation;
46 import net.grinder.engine.process.GrinderProcess.Times;
47 import net.grinder.script.InvalidContextException;
48 import net.grinder.util.thread.Condition;
49
50 import org.junit.AfterClass;
51 import org.junit.Test;
52 import org.mockito.ArgumentCaptor;
53
54
55
56
57
58
59
60 public class TestGrinderProcess {
61 private static final ExecutorService s_executor =
62 Executors.newCachedThreadPool();
63
64 @AfterClass public static void shutdown() {
65 s_executor.shutdown();
66 }
67
68 @Test public void testThreadSynchronisationZeroThreads() throws Exception {
69 final Condition c = new Condition();
70
71 final ThreadSynchronisation ts =
72 new GrinderProcess.ThreadSynchronisation(c);
73
74 assertEquals(0, ts.getTotalNumberOfThreads());
75 assertEquals(0, ts.getNumberOfRunningThreads());
76 assertTrue(ts.isReadyToStart());
77 assertTrue(ts.isFinished());
78
79 ts.startThreads();
80 ts.awaitStart();
81 }
82
83 @Test public void testThreadSynchronisationNThreads() throws Exception {
84 final Condition c = new Condition();
85 final Thread[] threads = new Thread[100];
86
87 final ThreadSynchronisation ts =
88 new GrinderProcess.ThreadSynchronisation(c);
89
90 for (int i = 0; i < threads.length; ++i) {
91 threads[i] = new Thread(new MyRunnable(ts, i % 3 == 0));
92 }
93
94 assertEquals(100, ts.getTotalNumberOfThreads());
95 assertEquals(100, ts.getNumberOfRunningThreads());
96 assertFalse(ts.isReadyToStart());
97 assertFalse(ts.isFinished());
98
99 for (int i = 0; i < threads.length; ++i) {
100 threads[i].start();
101 }
102
103 ts.startThreads();
104
105 synchronized (c) {
106 while (!ts.isFinished()) {
107 c.waitNoInterrruptException();
108 }
109 }
110
111 assertTrue(ts.isFinished());
112 assertEquals(0, ts.getNumberOfRunningThreads());
113 assertEquals(100, ts.getTotalNumberOfThreads());
114 }
115
116 private static class MyRunnable implements Runnable {
117 private final ThreadSynchronisation m_ts;
118 private final boolean m_failBeforeStart;
119
120 public MyRunnable(ThreadSynchronisation ts, boolean failBeforeStart) {
121 m_ts = ts;
122 m_failBeforeStart = failBeforeStart;
123 ts.threadCreated();
124 }
125
126 public void run() {
127 shortSleep();
128
129 if (m_failBeforeStart) {
130 m_ts.threadFinished();
131 }
132 else {
133 m_ts.awaitStart();
134
135 shortSleep();
136
137 m_ts.threadFinished();
138 }
139 }
140
141 private void shortSleep() {
142 try {
143 Thread.sleep(10);
144 }
145 catch (InterruptedException e) {
146 }
147 }
148 }
149
150 @Test public void testTimes() {
151 final Times times = new Times();
152 assertNotNull(times.getTimeAuthority());
153
154 assertEquals(0, times.getExecutionStartTime());
155 final long t1 = System.currentTimeMillis();
156 times.setExecutionStartTime();
157 final long t2 = System.currentTimeMillis();
158
159
160 final long FUDGE = 10;
161
162 assertTrue(t1 - FUDGE <= times.getExecutionStartTime());
163 assertTrue(times.getExecutionStartTime() <= t2 + FUDGE);
164 final long elapsedTime = times.getElapsedTime();
165 assertTrue(elapsedTime <= (System.currentTimeMillis() - t1));
166 assertTrue(elapsedTime >= 0);
167 }
168
169 @Test public void testThreadContextsThreadContextLocator() throws Exception {
170 final ThreadContexts threadContexts = new ThreadContexts();
171 assertNull(threadContexts.get());
172
173 final ThreadContext threadContext1 = mock(ThreadContext.class);
174
175 threadContexts.threadStarted(threadContext1);
176 assertSame(threadContext1, threadContexts.get());
177
178 final Future<ThreadContext> future =
179 s_executor.submit(new Callable<ThreadContext>() {
180
181 public ThreadContext call() throws Exception {
182 return threadContexts.get();
183 }});
184
185 final ThreadContext otherContext = future.get();
186
187 assertNotSame(otherContext, threadContexts.get());
188 assertSame(threadContext1, threadContexts.get());
189 }
190
191 @Test public void testThreadContextsThreadCreated() throws Exception {
192 final ThreadContexts threadContexts = new ThreadContexts();
193
194 final ThreadContext threadContext = mock(ThreadContext.class);
195 when(threadContext.getThreadNumber()).thenReturn(99);
196
197 threadContexts.threadCreated(threadContext);
198
199 final ArgumentCaptor<ThreadLifeCycleListener> listenerCaptor=
200 ArgumentCaptor.forClass(ThreadLifeCycleListener.class);
201
202 verify(threadContext)
203 .registerThreadLifeCycleListener(listenerCaptor.capture());
204
205 listenerCaptor.getValue().endThread();
206
207
208 assertFalse(threadContexts.shutdown(99));
209 }
210
211 @Test public void testThreadContextsShutdown() throws Exception {
212 final ThreadContexts threadContexts = new ThreadContexts();
213 assertFalse(threadContexts.shutdown(2));
214
215 final ThreadContext threadContext = mock(ThreadContext.class);
216 when(threadContext.getThreadNumber()).thenReturn(2);
217
218 threadContexts.threadCreated(threadContext);
219
220 assertTrue(threadContexts.shutdown(2));
221 assertTrue(threadContexts.shutdown(2));
222
223 verify(threadContext, times(2)).shutdown();
224 }
225
226 @Test public void testThreadContextsShutdownAll() throws Exception {
227 final ThreadContexts threadContexts = new ThreadContexts();
228
229 final ThreadContext threadContext1 = mock(ThreadContext.class);
230 when(threadContext1.getThreadNumber()).thenReturn(1);
231 threadContexts.threadCreated(threadContext1);
232
233 final ThreadContext threadContext2 = mock(ThreadContext.class);
234 when(threadContext2.getThreadNumber()).thenReturn(2);
235 threadContexts.threadCreated(threadContext2);
236
237 threadContexts.shutdownAll();
238
239 verify(threadContext1).shutdown();
240 verify(threadContext2).shutdown();
241
242 final ThreadContext threadContext3 = mock(ThreadContext.class);
243 when(threadContext3.getThreadNumber()).thenReturn(2);
244 threadContexts.threadCreated(threadContext3);
245
246 verify(threadContext3).shutdown();
247 }
248
249 @Test public void testInvalidThreadStarter() throws Exception {
250 final ThreadStarter starter = new GrinderProcess.InvalidThreadStarter();
251
252 try {
253 starter.startThread(null);
254 fail("Expected InvalidContextException");
255 }
256 catch (InvalidContextException e) {
257 }
258 }
259
260 @Test public void testCoverNullQueuedSender() throws Exception {
261 final QueuedSender sender = new GrinderProcess.NullQueuedSender();
262
263 sender.send(null);
264 sender.send(null);
265 sender.flush();
266 sender.shutdown();
267
268 sender.send(null);
269 sender.send(null);
270 sender.flush();
271 sender.shutdown();
272 }
273 }