View Javadoc

1   // Copyright (C) 2008 - 2012 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.console;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.mockito.Matchers.eq;
26  import static org.mockito.Matchers.isA;
27  import static org.mockito.Mockito.mock;
28  import static org.mockito.Mockito.verify;
29  import static org.mockito.Mockito.verifyNoMoreInteractions;
30  import static org.mockito.Mockito.when;
31  
32  import java.io.File;
33  import java.net.InetAddress;
34  import java.net.ServerSocket;
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.HashMap;
38  import java.util.Timer;
39  import java.util.concurrent.Callable;
40  import java.util.concurrent.ExecutionException;
41  import java.util.concurrent.ExecutorService;
42  import java.util.concurrent.Executors;
43  import java.util.concurrent.Future;
44  import java.util.concurrent.TimeUnit;
45  
46  import net.grinder.communication.Message;
47  import net.grinder.communication.MessageDispatchRegistry;
48  import net.grinder.communication.MessageDispatchRegistry.Handler;
49  import net.grinder.console.client.ConsoleConnection;
50  import net.grinder.console.client.ConsoleConnectionFactory;
51  import net.grinder.console.common.Resources;
52  import net.grinder.console.common.StubResources;
53  import net.grinder.console.communication.ConsoleCommunication;
54  import net.grinder.console.communication.server.DispatchClientCommands;
55  import net.grinder.console.model.ConsoleProperties;
56  import net.grinder.console.model.SampleModel;
57  import net.grinder.console.model.SampleModelViews;
58  import net.grinder.messages.console.RegisterExpressionViewMessage;
59  import net.grinder.messages.console.RegisterTestsMessage;
60  import net.grinder.messages.console.ReportStatisticsMessage;
61  import net.grinder.statistics.ExpressionView;
62  import net.grinder.statistics.StatisticsServicesImplementation;
63  import net.grinder.statistics.TestStatisticsMap;
64  import net.grinder.testutility.AbstractJUnit4FileTestCase;
65  
66  import org.junit.After;
67  import org.junit.Before;
68  import org.junit.Test;
69  import org.mockito.ArgumentCaptor;
70  import org.mockito.Captor;
71  import org.mockito.Mock;
72  import org.mockito.MockitoAnnotations;
73  import org.slf4j.Logger;
74  
75  
76  /**
77   * Unit tests for {@link ConsoleFoundation}.
78   *
79   * @author Philip Aston
80   */
81  public class TestConsoleFoundation extends AbstractJUnit4FileTestCase {
82  
83    @Mock private MessageDispatchRegistry m_messageDispatchRegistry;
84    @Mock private ConsoleCommunication m_consoleCommunication;
85    @Mock private Logger m_logger;
86  
87    @Captor private ArgumentCaptor<Handler<Message>> m_handlerCaptor;
88  
89    private final ExecutorService m_executor = Executors.newCachedThreadPool();
90  
91    @Before public void setUp() {
92      MockitoAnnotations.initMocks(this);
93  
94      when(m_consoleCommunication.getMessageDispatchRegistry())
95        .thenReturn(m_messageDispatchRegistry);
96    }
97  
98    @After public void tearDown() {
99      m_executor.shutdownNow();
100   }
101 
102   private final Resources m_resources =
103     new StubResources<Object>(new HashMap<String, Object>() {{
104     }});
105 
106   @Test public void testConstruction() throws Exception {
107 
108     final ConsoleFoundation consoleFoundation =
109         new ConsoleFoundation(m_resources, m_logger, true);
110 
111     verify(m_logger).info(isA(String.class)); // Text UI version.
112     verifyNoMoreInteractions(m_logger);
113     consoleFoundation.shutdown();
114   }
115 
116   @Test public void testSimpleRun() throws Exception {
117 
118     final Timer timer = new Timer(true);
119 
120     final ConsoleProperties consoleProperties =
121       new ConsoleProperties(m_resources, new File(getDirectory(), "props"));
122 
123     // Figure out free local ports.
124 
125     final ServerSocket serverSocket =
126       new ServerSocket(0, 50, InetAddress.getLocalHost());
127     final String hostName = serverSocket.getInetAddress().getHostName();
128     final int port = serverSocket.getLocalPort();
129 
130     final ServerSocket serverSocket2 =
131         new ServerSocket(0, 50, InetAddress.getLocalHost());
132     final int port2 = serverSocket2.getLocalPort();
133 
134     serverSocket.close();
135     serverSocket2.close();
136 
137     consoleProperties.setConsoleHost(hostName);
138     consoleProperties.setConsolePort(port);
139     consoleProperties.setHttpHost(hostName);
140     consoleProperties.setHttpPort(port2);
141 
142     final ConsoleFoundation foundation =
143       new ConsoleFoundation(m_resources,
144                             m_logger,
145                             false,
146                             timer,
147                             consoleProperties);
148 
149     verify(m_logger).info(isA(String.class)); // Text UI version.
150     verifyNoMoreInteractions(m_logger);
151 
152     final Future<?> runTask = m_executor.submit(new Runnable() {
153       public void run() { foundation.run(); }
154     });
155 
156     connectToConsole(hostName, port);
157 
158     foundation.shutdown();
159 
160     runTask.get(1, TimeUnit.SECONDS);
161 
162     verifyNoMoreInteractions(m_logger);
163   }
164 
165   private void connectToConsole(final String hostName, final int port)
166       throws Exception {
167 
168     final ConsoleConnectionFactory ccf = new ConsoleConnectionFactory();
169 
170     final Callable<Void> connect = new Callable<Void>() {
171         public Void call() throws Exception {
172           final ConsoleConnection client = ccf.connect(hostName, port);
173           assertEquals(0, client.getNumberOfAgents());
174           client.close();
175           return null;
176         }
177       };
178 
179     final int retries = 3;
180 
181     for (int i = 0; i < retries; ++i) {
182       final Future<Void> task = m_executor.submit(connect);
183 
184       try {
185         task.get(1, TimeUnit.SECONDS);
186       }
187       catch (ExecutionException e) {
188         if (i == retries - 1) {
189           throw e;
190         }
191 
192         Thread.sleep(50);
193       }
194     }
195   }
196 
197   @Test public void testWireMessageDispatch() throws Exception {
198 
199     final SampleModel sampleModel = mock(SampleModel.class);
200 
201     final SampleModelViews sampleModelViews = mock(SampleModelViews.class);
202 
203     final DispatchClientCommands dispatchClientCommands =
204       new DispatchClientCommands(null, null, null);
205 
206     new ConsoleFoundation.WireMessageDispatch(m_consoleCommunication,
207                                               sampleModel,
208                                               sampleModelViews,
209                                               dispatchClientCommands);
210 
211     verify(m_messageDispatchRegistry).set(eq(RegisterTestsMessage.class),
212                                           m_handlerCaptor.capture());
213 
214     final Collection<net.grinder.common.Test> tests = Collections.emptySet();
215     m_handlerCaptor.getValue().handle(new RegisterTestsMessage(tests));
216 
217     verify(sampleModel).registerTests(tests);
218 
219     verify(m_messageDispatchRegistry).set(eq(ReportStatisticsMessage.class),
220                                           m_handlerCaptor.capture());
221 
222     final TestStatisticsMap delta = new TestStatisticsMap();
223     m_handlerCaptor.getValue().handle(new ReportStatisticsMessage(delta));
224 
225     verify(sampleModel).addTestReport(delta);
226 
227     verify(m_messageDispatchRegistry).set(
228       eq(RegisterExpressionViewMessage.class), m_handlerCaptor.capture());
229 
230     final ExpressionView expressionView =
231       StatisticsServicesImplementation.getInstance()
232       .getStatisticExpressionFactory().createExpressionView(
233         "blah", "userLong0", false);
234     m_handlerCaptor.getValue().handle(
235       new RegisterExpressionViewMessage(expressionView));
236 
237     verify(sampleModelViews).registerStatisticExpression(expressionView);
238 
239     verifyNoMoreInteractions(sampleModel,
240                              sampleModelViews);
241   }
242 }