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