/**
*
*/
package org.jboss.test.faces;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import junit.framework.TestResult;
/**
* @author asmirnov
* @author Nick Belaevski
*/
public abstract class AbstractThreadedTest extends TestCase {
/**
* The threads that are executing.
*/
private Thread threads[] = null;
/**
* The tests TestResult.*/
private TestResult testResult = null;
public void interruptThreads() {
if(threads != null) {
for(int i = 0;i < threads.length;i++) {
threads[i].interrupt();
}
}
}
/**
* Override run so we can squirrel away the test result.
*
*/
@Override
public void run(final TestResult result) {
testResult = result;
super.run(result);
testResult = null;
}
/**
* Create instances of classes and run threads with it.
* @param clazz - class of test thread implementation.
* @param numThreads - number of threads to run.
* @throws InstantiationException
* @throws IllegalAccessException
*/
protected void runTestCaseThreads(Class<?> clazz, int numThreads) {
TestCaseRunnable[] runnables = new TestCaseRunnable[numThreads];
for (int i = 0; i < runnables.length; i++) {
try {
runnables[i]= (TestCaseRunnable) clazz.newInstance();
} catch (Exception e) {
testResult.addError(this, e);
return;
}
}
runTestCaseRunnables(runnables);
}
/**
* Run the test case threads.
* @param runnables - array with instances of {@link TestCaseRunnable} with concrete tests
*/
protected void runTestCaseRunnables (final TestCaseRunnable[] runnables) {
if(runnables == null) {
throw new IllegalArgumentException("runnables is null");
}
threads = new Thread[runnables.length];
for(int i = 0;i < threads.length;i++) {
threads[i] = new Thread(runnables[i]);
}
for(int i = 0;i < threads.length;i++) {
threads[i].start();
}
try {
for(int i = 0;i < threads.length;i++) {
threads[i].join();
}
}
catch(InterruptedException ignore) {
System.out.println("Thread join interrupted.");
}
threads = null;
}
/**
* Handle an exception. Since multiple threads won't have their
* exceptions caught the threads must manually catch them and call
* <code>handleException ()</code>.
* @param t Exception to handle.*/
private void handleException(final Throwable t) {
synchronized(testResult) {
if(t instanceof AssertionFailedError) {
testResult.addFailure(this, (AssertionFailedError)t);
}
else {
testResult.addError(this, t);
}
}
}
/**
* A test case thread. Override runTestCase () and define
* behaviour of test in there.*/
public abstract class TestCaseRunnable implements Runnable {
/**
* Override this to define the test*/
public abstract void runTestCase()
throws Throwable;
/**
* Run the test in an environment where
* we can handle the exceptions generated by the test method.*/
public void run() {
try {
runTestCase();
}
catch(Throwable t) /* Any other exception we handle and then we interrupt the other threads.*/ {
handleException(t);
interruptThreads();
}
}
}
}