1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact tma@netspace.net.au.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2003-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: AbstractTestRunner.java,v 1.7 2004/01/31 13:44:24 tanderson Exp $
44 */
45 package org.exolab.jmscts.core;
46
47 import java.io.FileReader;
48 import java.io.File;
49 import java.util.Enumeration;
50 import java.util.Iterator;
51
52 import junit.extensions.TestSetup;
53 import junit.framework.Test;
54 import junit.framework.TestResult;
55 import junit.framework.TestSuite;
56
57 import org.apache.commons.cli.CommandLine;
58 import org.apache.commons.cli.CommandLineParser;
59 import org.apache.commons.cli.GnuParser;
60 import org.apache.commons.cli.Options;
61 import org.apache.log4j.Category;
62 import org.apache.log4j.xml.DOMConfigurator;
63
64 import org.exolab.core.service.ServiceException;
65 import org.exolab.core.service.ServiceGroup;
66 import org.exolab.core.util.RmiRegistryService;
67
68 import org.exolab.jmscts.core.filter.Filter;
69 import org.exolab.jmscts.core.service.SnapshotService;
70 import org.exolab.jmscts.core.service.TestTerminatorService;
71 import org.exolab.jmscts.provider.Configuration;
72 import org.exolab.jmscts.provider.ProviderLoader;
73
74
75 /***
76 * This class enables test cases to be run against different JMS providers
77 * <p>
78 * The provider configuration file path is passed at construction. This
79 * contains a list of providers to run the tests against.
80 * <p>
81 * <h3>Parameters</h3>
82 * <table border="1" cellpadding="2" cellspacing="0">
83 * <tr>
84 * <td valign="top"><b>Argument</b></td>
85 * <td valign="top"><b>Description</b></td>
86 * <td align="center" valign="top"><b>Required</b></td>
87 * </tr>
88 * <tr>
89 * <td valign="top">config</td>
90 * <td valign="top">the provider configuration file path</td>
91 * <td valign="top" align="center">No</td>
92 * </tr>
93 * <tr>
94 * <td valign="top">output</td>
95 * <td valign="top">the report output directory</td>
96 * <td valign="top" align="center">No</td>
97 * </tr>
98 * <tr>
99 * <td valign="top">filter</td>
100 * <td valign="top">the test filter configuration file path</td>
101 * <td valign="top" align="center">No</td>
102 * </tr>
103 * <tr>
104 * <td valign="top">port</td>
105 * <td valign="top">the registry port</td>
106 * <td valign="top" align="center">No</td>
107 * </tr>
108 * </table>
109 *
110 * @version $Revision: 1.7 $ $Date: 2004/01/31 13:44:24 $
111 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
112 */
113 public abstract class AbstractTestRunner extends TestSetup {
114
115 /***
116 * The default registry port
117 */
118 public static final String DEFAULT_PORT = "4000";
119
120 /***
121 * The configuration file path argument
122 */
123 private static final String CONFIG = "config";
124
125 /***
126 * The test case filter path argument
127 */
128 private static final String FILTER = "filter";
129
130 /***
131 * The coverage report output directory
132 */
133 private static final String OUTPUT = "output";
134
135 /***
136 * The registry port argument
137 */
138 private static final String PORT = "port";
139
140 /***
141 * The log4j configuration filename
142 */
143 private static final String LOG4J = "log4j.xml";
144
145 /***
146 * The configuration for each provider
147 */
148 private Configuration _config = null;
149
150 /***
151 * The report output directory
152 */
153 private String _output = null;
154
155 /***
156 * The test case filter
157 */
158 private Filter _filter = null;
159
160 /***
161 * The command line arguments
162 */
163 private final String[] _args;
164
165 /***
166 * The test result
167 */
168 private TestResult _result = null;
169
170 /***
171 * The current provider being tested against
172 */
173 private ProviderLoader _provider = null;
174
175 /***
176 * The registry port
177 */
178 private int _port;
179
180 /***
181 * The services
182 */
183 private ServiceGroup _services = new ServiceGroup();
184
185 /***
186 * The logger
187 */
188 private static final Category log =
189 Category.getInstance(AbstractTestRunner.class.getName());
190
191
192 /***
193 * Construct an instance using the class of the test case, and the list
194 * of arguments to configure the test suite
195 *
196 * @param test a class implementing the {@link ConnectionFactoryTestCase}
197 * interface
198 * @param args command line arguments
199 */
200 public AbstractTestRunner(Class test, String[] args) {
201 super(new TestSuite(test));
202 if (args == null) {
203 throw new IllegalArgumentException("Argument 'args' is null");
204 }
205 _args = args;
206
207 // configure the logger
208 DOMConfigurator.configure(getHome() + "/config/" + LOG4J);
209 }
210
211 /***
212 * Construct an instance with the test to run, and the list of arguments
213 * to configure the test suite
214 *
215 * @param test the test to run
216 * @param args command line arguments
217 */
218 public AbstractTestRunner(Test test, String[] args) {
219 super(test);
220 if (args == null) {
221 throw new IllegalArgumentException("Argument args is null");
222 }
223 _args = args;
224
225 // configure the logger
226 DOMConfigurator.configure(getHome() + "/config/" + LOG4J);
227 }
228
229 /***
230 * Generate a report
231 *
232 * @param path the path to write the report to
233 * @throws Exception for any error
234 */
235 public abstract void report(String path) throws Exception;
236
237 /***
238 * Snapshot the current state of the test
239 *
240 * @param path the path to write the report to
241 * @throws Exception for any error
242 */
243 public void snapshot(String path) throws Exception {
244 report(path);
245 }
246
247 /***
248 * Generate a report and stop the test
249 */
250 public void stop() {
251 if (_result != null) {
252 _result.stop();
253 }
254 try {
255 report(_output);
256 } catch (Exception exception) {
257 log.error("Failed to produce report", exception);
258 }
259 }
260
261 /***
262 * Generate a report, and abort the test
263 */
264 public void abort() {
265 try {
266 report(_output);
267 } catch (Exception exception) {
268 log.error("Failed to produce report", exception);
269 }
270 System.exit(1);
271 }
272
273 /***
274 * Creates a test context
275 *
276 * @return a new test context
277 */
278 public abstract TestContext createContext();
279
280 /***
281 * Runs the test case against each provider
282 *
283 * @param result the instance to collect results in
284 */
285 public void basicRun(TestResult result) {
286 TestFilter filter = (_filter != null) ? new TestFilter(_filter) : null;
287 _result = result;
288
289 Iterator iterator = _config.getProviders().iterator();
290 while (iterator.hasNext() && !result.shouldStop()) {
291 _provider = (ProviderLoader) iterator.next();
292
293 TestSuite suite = new TestSuite();
294 mergeSuites(suite, getTest());
295
296 TestContext context = createContext();
297
298 // run the tests against the provider configuration
299 ProviderTestRunner runner = new ProviderTestRunner(suite);
300 runner.setContext(context);
301 runner.setFilter(filter);
302 runner.setProvider(_provider);
303 runner.run(result);
304
305 // generate a results report
306 try {
307 report(_output);
308 } catch (Exception exception) {
309 log.error(exception, exception);
310 }
311 }
312 }
313
314 /***
315 * Returns the registry port
316 *
317 * @return the registry port
318 */
319 public int getPort() {
320 return _port;
321 }
322
323 /***
324 * Reads the provider configuration
325 *
326 * @throws Exception if the configuration cannot be initialised
327 */
328 protected void setUp() throws Exception {
329 // parse the command line
330 Options options = new Options();
331 options.addOption(CONFIG, true, "the provider configuration path");
332 options.addOption(OUTPUT, true, "the output path");
333 options.addOption(FILTER, true, "the test case filter path");
334 options.addOption(PORT, true, "registry port");
335
336 CommandLineParser parser = new GnuParser();
337 CommandLine commands = parser.parse(options, _args);
338
339 String config = commands.getOptionValue(
340 CONFIG, getHome() + "/config/providers.xml");
341
342 _output = (String) commands.getOptionValue(
343 OUTPUT, getHome() + "/report");
344 File dir = new File(_output);
345 if (!dir.isDirectory()) {
346 throw new Exception("Invalid output directory: " + _output);
347 }
348 if (!dir.canWrite()) {
349 throw new Exception("Cannot write to output directory: "
350 + _output);
351 }
352
353 String filter = commands.getOptionValue(FILTER);
354 _port = Integer.parseInt(commands.getOptionValue(PORT, DEFAULT_PORT));
355
356 // load the provider configuration
357 _config = Configuration.read(config);
358
359 // load the filter (if supplied)
360 loadFilter(filter);
361
362 // initialise and start the services
363 startServices();
364 }
365
366 /***
367 * Returns the current provider being tested against
368 *
369 * @return the current provider being tested against, or <code>null</code>
370 * if no test is being run
371 */
372 protected ProviderLoader getProvider() {
373 return _provider;
374 }
375
376 /***
377 * Clean up any resources allocated
378 *
379 * @throws Exception for any error
380 */
381 protected void tearDown() throws Exception {
382 _config = null;
383 if (_services != null) {
384 _services.stopAll();
385 }
386 }
387
388 /***
389 * Start the services
390 *
391 * @throws Exception for any error
392 */
393 protected void startServices() throws Exception {
394 registerServices(_services);
395 _services.startAll();
396 }
397
398 /***
399 * Register services
400 *
401 * @param services the service group to register the services with
402 * @throws ServiceException for any error
403 */
404 protected void registerServices(ServiceGroup services)
405 throws ServiceException {
406
407 RmiRegistryService registry = new RmiRegistryService(_port);
408 services.add(registry.getName(), registry);
409
410 SnapshotService snapshot = new SnapshotService(this, _port);
411 services.add(snapshot.getName(), snapshot);
412
413 TestTerminatorService terminator = new TestTerminatorService(
414 this, _port);
415 services.add(terminator.getName(), terminator);
416
417 services.startAll();
418 }
419
420 /***
421 * Returns the value of the <code>jmscts.home</code> system property,
422 * defaulting to the value of <code>user.dir</code> if its not set
423 *
424 * @return the value of the <code>jmscts.home</code> system property
425 */
426 protected String getHome() {
427 return System.getProperty("jmscts.home",
428 System.getProperty("user.dir"));
429 }
430
431 /***
432 * Removes nested TestSuite instances from <code>test</code>, adding the
433 * contained Test instances to <code>suite</code>, in order for the
434 * ProviderTestRunner to be invoked successfully.
435 *
436 * @param suite the resulting test suite
437 * @param test if an instance of TestSuite, this method will be called
438 * recursively with each contained Test; else the test will be added
439 * directly to <code>suite</code>
440 */
441 protected void mergeSuites(TestSuite suite, Test test) {
442 if (test instanceof TestSuite) {
443 Enumeration iter = ((TestSuite) test).tests();
444 while (iter.hasMoreElements()) {
445 mergeSuites(suite, (Test) iter.nextElement());
446 }
447 } else {
448 suite.addTest(test);
449 }
450 }
451
452 /***
453 * Loads the filter configuration file
454 *
455 * @param filter the filter configuration file path
456 * @throws Exception for any error
457 */
458 private void loadFilter(String filter) throws Exception {
459 if (filter != null) {
460 FileReader filterReader = null;
461 try {
462 filterReader = new FileReader(filter);
463 _filter = Filter.unmarshal(filterReader);
464 } finally {
465 if (filterReader != null) {
466 filterReader.close();
467 }
468 }
469 }
470 }
471
472 }
This page was automatically generated by Maven