KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > junit > v1 > TestRunnable


1 /*
2  * @(#)TestRunnable.java
3  *
4  * The basics are taken from an article by Andy Schneider
5  * andrew.schneider@javaworld.com
6  * The article is "JUnit Best Practices"
7  * http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit_p.html
8  *
9  * Part of the GroboUtils package at:
10  * http://groboutils.sourceforge.net
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  */

30
31 package net.sourceforge.groboutils.junit.v1;
32
33 import org.apache.log4j.Logger;
34 import junit.framework.TestCase;
35 import junit.framework.TestResult;
36 import junit.framework.AssertionFailedError;
37 import junit.framework.Assert;
38
39
40 /**
41  * Instances of this class only execute in the
42  * <tt>runTestRunnables</tt> method of
43  * the <tt>MultiThreadedTestRunner</tt> class.
44  * TestCases should define inner classes as a subclass of this,
45  * implement the <tt>runTest()</tt> method, and pass in the
46  * instantiated class as part of an array to the
47  * <tt>runTestRunnables</tt> method. Call <tt>delay( long )</tt>
48  * to easily include a waiting period. This class allows for
49  * all assertions to be invoked, so that subclasses can be static or
50  * defined outside a TestCase. If an exception is thrown from the
51  * <tt>runTest()</tt> method, then all other test threads will
52  * terminate due to the error.
53  * <P>
54  * The <tt>runTest()</tt> method needs to be responsive to
55  * <tt>InterruptedException</tt>, resulting from the owning
56  * <tt>MultiThreadedTestRunner</tt> interrupting the thread in order to
57  * signal the early termination of the threads. The
58  * <tt>InterruptedException</tt>s may be propigated outside the
59  * <tt>runTest()</tt> implementation with no harmful effects. Note that
60  * this means that <tt>InterruptedException</tt>s are part of the
61  * framework, and as such carry information that your <tt>runTest()</tt>
62  * implementations cannot override; in other words, don't let your test
63  * propigate an <tt>InterruptedException</tt> to indicate an error.
64  * <P>
65  * Tests which perform a set of monitoring checks on the object-under-test
66  * should extend <tt>TestMonitorRunnable</tt>, since monitors run until
67  * told to stop. The <tt>Thread.stop()</tt> command will be sent with a
68  * <tt>MultiThreadedTestRunner.TestDeathException</tt>.
69  *
70  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
71  * @version $Date: 2003/10/03 14:26:45 $
72  * @since March 28, 2002
73  */

74 public abstract class TestRunnable extends Assert
75         implements Runnable JavaDoc
76 {
77     private static final Class JavaDoc THIS_CLASS = TestRunnable.class;
78     protected static final Logger LOG = Logger.getLogger( THIS_CLASS );
79     private static int testCount = 0;
80     
81     private MultiThreadedTestRunner mttr;
82     private int testIndex;
83     private boolean ignoreStopErrors = false;
84     
85     
86     public TestRunnable()
87     {
88         synchronized( THIS_CLASS )
89         {
90             this.testIndex = testCount++;
91         }
92     }
93     
94     
95     TestRunnable( boolean ignoreStopErrors )
96     {
97         this();
98         this.ignoreStopErrors = ignoreStopErrors;
99     }
100     
101     
102     
103     /**
104      * Performs the set of processing or checks on the object-under-test,
105      * which will be in parallel with other <tt>TestRunnable</tt>
106      * instances.
107      * <P>
108      * The implementation should be responsive to
109      * <tt>InterruptedException</tt> exceptions or to the status of
110      * <tt>Thread.isInterrupted()</tt>, as that is the signal used to tell
111      * running <tt>TestRunnable</tt> instances to halt their processing;
112      * instances which do not stop within a reasonable time frame will
113      * have <tt>Thread.stop()</tt> called on them.
114      * <P>
115      * Non-monitor instances must have this method implemented such that
116      * it runs in a finite time; if any instance executes over the
117      * <tt>MultiThreadedTestRunner</tt> instance maximum time limit, then
118      * the <tt>MultiThreadedTestRunner</tt> instance assumes that a
119      * test error occurred.
120      *
121      * @exception Throwable any exception may be thrown and will be
122      * reported as a test failure, except for
123      * <tt>InterruptedException</tt>s, which will be ignored.
124      */

125     public abstract void runTest() throws Throwable JavaDoc;
126     
127     /**
128      * Sleep for <tt>millis</tt> milliseconds. A convenience method.
129      *
130      * @exception InterruptedException if an interrupt occured during the
131      8 sleep.
132      */

133     public void delay( long millis ) throws InterruptedException JavaDoc
134     {
135         Thread.sleep( millis );
136     }
137     
138     /**
139      * Unable to make this a "final" method due to JDK 1.1 compatibility.
140      * However, implementations should not override this method.
141      */

142     public void run()
143     {
144         if (this.mttr == null)
145         {
146             throw new IllegalStateException JavaDoc(
147                 "Owning runner never defined. The runnables should only be "+
148                 "started through the MultiThreadedTestRunner instance." );
149         }
150         
151         LOG.info( "Starting test thread "+this.testIndex );
152         try
153         {
154             runTest();
155         }
156         catch (InterruptedException JavaDoc ie)
157         {
158             // ignore these exceptions - they represent the MTTR
159
// interrupting the tests.
160
}
161         catch (MultiThreadedTestRunner.TestDeathException tde)
162         {
163             // ignore these exceptions as they relate to thread-related
164
// exceptions. These represent the MTTR stopping us.
165
// Our response is to actually rethrow the exception.
166
if (!this.ignoreStopErrors)
167             {
168                 LOG.info( "Aborted test thread "+this.testIndex );
169                 throw tde;
170             }
171         }
172         catch (Throwable JavaDoc t)
173         {
174             // for any exception, handle it and interrupt the
175
// other threads
176

177             // Note that ThreadDeath exceptions must be re-thrown after
178
// the interruption has occured.
179
this.mttr.handleException( t );
180         }
181         LOG.info( "Ended test thread "+this.testIndex );
182     }
183     
184     
185     /**
186      * Returns the status of the owning <tt>MultiThreadedTestRunner</tt>
187      * instance: <tt>true</tt> means that the tests have completed (monitors
188      * may still be active), and <tt>false</tt> means that the tests are
189      * still running.
190      *
191      * @return <tt>true</tt> if the tests have completed their run,
192      * otherwise <tt>false</tt>.
193      */

194     public boolean isDone()
195     {
196         return this.mttr.areThreadsFinished();
197     }
198     
199     
200     void setTestRunner( MultiThreadedTestRunner mttr )
201     {
202         this.mttr = mttr;
203     }
204 }
205
206
Popular Tags