KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > MultiThreadedTestCase


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model;
35
36 import edu.rice.cs.drjava.DrJavaTestCase;
37 import edu.rice.cs.drjava.ui.DefinitionsPaneTest;
38 import edu.rice.cs.util.Log;
39
40 import junit.framework.AssertionFailedError;
41
42 /** TestCase which can fail if another thread causes an error or failure.
43   * @version $Id: MultiThreadedTestCase.java 4026 2006-10-31 15:50:16Z rcartwright $
44   */

45 public abstract class MultiThreadedTestCase extends DrJavaTestCase {
46   public MultiThreadedTestCase() { super(); }
47   public MultiThreadedTestCase(String JavaDoc name) { super(name); }
48   
49   /** Flag to keep track of whether or not a test failed in another thread (not the testing thread). */
50   protected volatile static boolean _testFailed = false;
51
52   /** Initialize test state to not failed. */
53   public void setUp() throws Exception JavaDoc {
54     super.setUp();
55     _testFailed = false;
56     ExceptionHandler.ONLY.reset();
57     Thread.setDefaultUncaughtExceptionHandler(ExceptionHandler.ONLY);
58   }
59
60   /** If any test failed, print a message saying that some test failed in another thread (not the testing thread). */
61   public void tearDown() throws Exception JavaDoc {
62     ExceptionHandler.ONLY.rethrow();
63     if (_testFailed) fail("test failed in another thread");
64     DefinitionsPaneTest._log.log("MultithreadedTestCase.tearDown() calling super.tearDown()");
65     super.tearDown();
66   }
67
68   /** This method prints the failure message to System.out and kills the JVM. Just calling fail() doesn't always cause
69     * the test to fail, because the listener is often called from another thread.
70     */

71   protected static void listenerFail(String JavaDoc s) {
72     StackTraceElement JavaDoc[] trace = Thread.getAllStackTraces().get(Thread.currentThread());
73     System.out.println("TEST FAILED in a listener thread");
74     System.out.println("Failing thread stack trace:\n " + Log.traceToString(trace));
75 // new AssertionFailedError(s).printStackTrace(System.out);
76
_testFailed = true;
77     fail(s);
78   }
79   
80   /** Join with a thread, i.e. continue only after that thread has terminated. If the join is interrupted, an
81     * UnexpectedException is thrown.
82     * @param t thread to join with
83     */

84   public static void join(Thread JavaDoc t) {
85     try { t.join(); }
86     catch(InterruptedException JavaDoc e) {
87       throw new edu.rice.cs.util.UnexpectedException(e, "Thread.join was unexpectedly interrupted.");
88     }
89   }
90   
91   /** Wait for a notify or notifyAll. If the wait is interrupted, an UnexpectedException is thrown.
92    * @param o object to wait for
93    */

94   public static void wait(Object JavaDoc o) {
95     try { o.wait(); }
96     catch(InterruptedException JavaDoc e) {
97       e.printStackTrace();
98       throw new edu.rice.cs.util.UnexpectedException(e, "Thread.wait was unexpectedly interrupted.");
99     }
100   }
101   
102   /** Class that stores exceptions thrown in other threads so they can be rethrown in the main thread.
103     * AssertionFailedErrors thrown in other threads do not count as AssertionFailedErrors in the
104     * main class, i.e. if an assertion fails in a thread that is not the main thread, the unit test will not fail!
105     */

106   private static class ExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
107     
108     /** Stored throwable, or null if nothing stored. */
109     private volatile Throwable JavaDoc _e = null;
110     
111     /** Stored thread that threw or null if none. */
112     private volatile java.lang.Thread JavaDoc _t = null;
113     
114     /** Thread that spawns the other threads. */
115     private volatile java.lang.Thread JavaDoc _mainThread = java.lang.Thread.currentThread();
116     
117     /** Gets called if an uncaught exception occurs in a thread.
118       * @param t the thread
119       * @param e the uncaught exception
120       */

121     public void uncaughtException(java.lang.Thread JavaDoc t, Throwable JavaDoc e) {
122       _t = t;
123       _e = e;
124       if (_mainThread != null) {
125         System.out.println("Uncaught Exception in spawned thread within a MultiThreadedTestCase:");
126         e.printStackTrace(System.out);
127         _mainThread.interrupt();
128       }
129     }
130     
131     /** Reset the stored exception and thread. */
132     public void reset() {
133       _t = null;
134       _e = null;
135     }
136     
137     /** Rethrow the exception, if one was stored. */
138     public void rethrow() {
139       if (exceptionOccurred()) {
140         if (_e instanceof Error JavaDoc) throw (Error JavaDoc)_e;
141         if (_e instanceof RuntimeException JavaDoc) throw (RuntimeException JavaDoc)_e;
142         else {
143           // avoid checked exceptions
144
throw new AssertionFailedError("Exception in thread "+_t+": "+_e);
145         }
146       }
147     }
148     
149     /** Returns true if an exception has occurred.
150       * @return true if exception has occurred
151       */

152     public boolean exceptionOccurred() { return (_e != null); }
153     
154     public Throwable JavaDoc getException() { return _e; }
155     
156     public java.lang.Thread JavaDoc getThread() { return _t; }
157     
158     /** Set the thread that spawns the other threads. */
159     public void setMainThread(java.lang.Thread JavaDoc mainThread) { _mainThread = mainThread; }
160     
161     /** Singleton constructor. */
162     private ExceptionHandler() { }
163     
164     /** Singleton instance. */
165     public static final ExceptionHandler ONLY = new ExceptionHandler();
166   }
167 }
168
Popular Tags