View Javadoc

1   // Copyright (C) 2008 - 2011 Philip Aston
2   // All rights reserved.
3   //
4   // This file is part of The Grinder software distribution. Refer to
5   // the file LICENSE which is part of The Grinder distribution for
6   // licensing details. The Grinder distribution is available on the
7   // Internet at http://grinder.sourceforge.net/
8   //
9   // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
13  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17  // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
18  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
20  // OF THE POSSIBILITY OF SUCH DAMAGE.
21  
22  package net.grinder.engine.process;
23  
24  import static org.mockito.Mockito.doThrow;
25  import static org.mockito.Mockito.never;
26  import static org.mockito.Mockito.times;
27  import static org.mockito.Mockito.verify;
28  import static org.mockito.Mockito.verifyNoMoreInteractions;
29  import static org.mockito.Mockito.when;
30  import net.grinder.common.GrinderProperties;
31  import net.grinder.engine.common.EngineException;
32  import net.grinder.scriptengine.ScriptEngineService.WorkerRunnable;
33  import net.grinder.scriptengine.ScriptExecutionException;
34  import net.grinder.testutility.AbstractJUnit4FileTestCase;
35  import net.grinder.util.Sleeper;
36  
37  import org.junit.Before;
38  import org.junit.Test;
39  import org.mockito.Mock;
40  import org.mockito.MockitoAnnotations;
41  import org.slf4j.Logger;
42  
43  
44  /**
45   * Unit tests for {@link GrinderThread}.
46   *
47   * @author Philip Aston
48   */
49  public class TestGrinderThread extends AbstractJUnit4FileTestCase {
50  
51    @Mock private Logger m_logger;
52    @Mock private ThreadContext m_threadContext;
53    @Mock private WorkerThreadSynchronisation m_workerThreadSynchronisation;
54    @Mock private ProcessLifeCycleListener m_processLifeCycleListener;
55    @Mock private Sleeper m_sleeper;
56    @Mock private WorkerRunnableFactory m_workerRunnableFactory;
57    @Mock private WorkerRunnable m_workerRunnable;
58  
59    private final GrinderProperties m_properties = new GrinderProperties();
60  
61  
62    @Before public void setUp() throws Exception {
63      MockitoAnnotations.initMocks(this);
64  
65      when(m_workerRunnableFactory.create()).thenReturn(m_workerRunnable);
66    }
67  
68    @Test public void testConstruction() throws Exception {
69  
70      new GrinderThread(m_logger,
71                        m_threadContext,
72                        m_workerThreadSynchronisation,
73                        m_processLifeCycleListener,
74                        m_properties,
75                        m_sleeper,
76                        m_workerRunnableFactory);
77  
78      verify(m_workerThreadSynchronisation).threadCreated();
79  
80      verify(m_processLifeCycleListener).threadCreated(m_threadContext);
81  
82      verifyNoMoreInteractions(m_processLifeCycleListener, m_threadContext);
83    }
84  
85    @Test public void testRun() throws Exception {
86  
87      final GrinderThread grinderThread =
88        new GrinderThread(m_logger,
89                          m_threadContext,
90                          m_workerThreadSynchronisation,
91                          m_processLifeCycleListener,
92                          m_properties,
93                          m_sleeper,
94                          m_workerRunnableFactory);
95  
96      verify(m_processLifeCycleListener).threadCreated(m_threadContext);
97  
98      grinderThread.run();
99  
100     verify(m_processLifeCycleListener).threadStarted(m_threadContext);
101 
102     verify(m_threadContext).fireBeginThreadEvent();
103     verify(m_threadContext).fireBeginRunEvent();
104     verify(m_threadContext).fireEndRunEvent();
105     verify(m_threadContext).fireBeginShutdownEvent();
106     verify(m_threadContext).fireEndThreadEvent();
107 
108     verify(m_workerRunnable).run();
109     verify(m_workerRunnable).shutdown();
110 
111     verify(m_workerThreadSynchronisation).threadCreated();
112     verify(m_workerThreadSynchronisation).awaitStart();
113     verify(m_workerThreadSynchronisation).threadFinished();
114 
115     verify(m_sleeper).sleepFlat(0);
116     verifyNoMoreInteractions(m_sleeper);
117   }
118 
119   @Test public void testMultipleRuns() throws Exception {
120 
121     final GrinderThread grinderThread =
122       new GrinderThread(m_logger,
123                         m_threadContext,
124                         m_workerThreadSynchronisation,
125                         m_processLifeCycleListener,
126                         m_properties,
127                         m_sleeper,
128                         m_workerRunnableFactory);
129 
130     m_properties.setInt("grinder.runs", 2);
131     m_properties.setLong("grinder.initialSleepTime", 100);
132 
133     grinderThread.run();
134 
135     verify(m_threadContext).fireBeginThreadEvent();
136     verify(m_threadContext, times(2)).fireBeginRunEvent();
137     verify(m_threadContext, times(2)).fireEndRunEvent();
138     verify(m_threadContext).fireBeginShutdownEvent();
139     verify(m_threadContext).fireEndThreadEvent();
140 
141     verify(m_workerRunnable, times(2)).run();
142     verify(m_workerRunnable).shutdown();
143 
144     verify(m_workerThreadSynchronisation).threadCreated();
145     verify(m_workerThreadSynchronisation).awaitStart();
146     verify(m_workerThreadSynchronisation).threadFinished();
147 
148     verify(m_sleeper).sleepFlat(100);
149     verifyNoMoreInteractions(m_sleeper);
150   }
151 
152   @Test public void testRunForeverShutdownException() throws Exception {
153 
154     final GrinderThread grinderThread =
155       new GrinderThread(m_logger,
156                         m_threadContext,
157                         m_workerThreadSynchronisation,
158                         m_processLifeCycleListener,
159                         m_properties,
160                         m_sleeper,
161                         m_workerRunnableFactory);
162 
163     m_properties.setInt("grinder.runs", 0);
164 
165     doThrow(new MyScriptEngineException(new ShutdownException("bye")))
166       .when(m_workerRunnable).run();
167 
168     grinderThread.run();
169 
170     verify(m_threadContext).fireBeginThreadEvent();
171     verify(m_threadContext).fireBeginRunEvent();
172     verify(m_threadContext, never()).fireEndRunEvent();
173     verify(m_threadContext).fireBeginShutdownEvent();
174     verify(m_threadContext).fireEndThreadEvent();
175 
176     verify(m_workerRunnable).run();
177     verify(m_workerRunnable).shutdown();
178 
179     verify(m_workerThreadSynchronisation).threadCreated();
180     verify(m_workerThreadSynchronisation).awaitStart();
181     verify(m_workerThreadSynchronisation).threadFinished();
182 
183     verify(m_sleeper).sleepFlat(0);
184     verifyNoMoreInteractions(m_sleeper);
185 
186     // TODO verify(m_threadLogger).output("shut down");
187   }
188 
189   @Test public void testRunScriptException() throws Exception {
190 
191     final GrinderThread grinderThread =
192       new GrinderThread(m_logger,
193                         m_threadContext,
194                         m_workerThreadSynchronisation,
195                         m_processLifeCycleListener,
196                         m_properties,
197                         m_sleeper,
198                         m_workerRunnableFactory);
199 
200     doThrow(new MyScriptEngineException("whatever"))
201       .when(m_workerRunnable).run();
202     doThrow(new MyScriptEngineException("whatever"))
203       .when(m_workerRunnable).shutdown();
204 
205     grinderThread.run();
206 
207     verify(m_threadContext).fireBeginThreadEvent();
208     verify(m_threadContext).fireBeginRunEvent();
209     verify(m_threadContext).fireEndRunEvent();
210     verify(m_threadContext).fireBeginShutdownEvent();
211     verify(m_threadContext).fireEndThreadEvent();
212 
213     verify(m_workerThreadSynchronisation).threadCreated();
214     verify(m_workerThreadSynchronisation).awaitStart();
215     verify(m_workerThreadSynchronisation).threadFinished();
216 
217     // TODO verify(m_threadLogger).error(and(contains("Aborted run"),
218     //                                 contains("short message")));
219   }
220 
221   @Test public void testRunScriptEngineException() throws Exception {
222 
223     final GrinderThread grinderThread =
224       new GrinderThread(m_logger,
225                         m_threadContext,
226                         m_workerThreadSynchronisation,
227                         m_processLifeCycleListener,
228                         m_properties,
229                         m_sleeper,
230                         m_workerRunnableFactory);
231 
232     when(m_workerRunnableFactory.create())
233       .thenThrow(new MyScriptEngineException("blah"));
234 
235     grinderThread.run();
236 
237     verify(m_threadContext).fireBeginThreadEvent();
238 
239     verify(m_workerThreadSynchronisation).threadCreated();
240     verify(m_workerThreadSynchronisation).threadFinished();
241     verifyNoMoreInteractions(m_workerThreadSynchronisation);
242 
243     // TODO verify(m_threadLogger).error(contains("Aborting thread: short message"));
244   }
245 
246   @Test public void testRunSomeOtherException() throws Exception {
247 
248     final GrinderThread grinderThread =
249       new GrinderThread(m_logger,
250                         m_threadContext,
251                         m_workerThreadSynchronisation,
252                         m_processLifeCycleListener,
253                         m_properties,
254                         m_sleeper,
255                         m_workerRunnableFactory);
256 
257     when(m_workerRunnableFactory.create())
258       .thenThrow(new EngineException("blah"));
259 
260     grinderThread.run();
261 
262     verify(m_threadContext).fireBeginThreadEvent();
263 
264     verify(m_workerThreadSynchronisation).threadCreated();
265     verify(m_workerThreadSynchronisation).threadFinished();
266     verifyNoMoreInteractions(m_workerThreadSynchronisation);
267 
268     // TODO verify(m_threadLogger).error(and(contains("Aborting thread:"),
269     //                                 contains("blah")));
270   }
271 
272   private static final class MyScriptEngineException
273     extends ScriptExecutionException {
274     public MyScriptEngineException(Throwable t) {
275       super("whoops", t);
276     }
277 
278     public MyScriptEngineException(String message) {
279       super(message);
280     }
281 
282     public String getShortMessage() {
283       return "short message";
284     }
285   }
286 }