/*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.extensions.threads;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import jsystem.framework.fixture.FixtureManager;
import jsystem.framework.report.ListenerstManager;
import jsystem.framework.report.ReportElement;
import jsystem.framework.report.Reporter;
import jsystem.framework.report.Reporter.EnumReportLevel;
import junit.framework.AssertionFailedError;
import junit.framework.SystemTestCase;
import junit.framework.TestListener;
import junit.framework.TestResult;
/**
* This class manages a group of tests that will be executed in parallel.
*/
public class TestThreadGroup {
private String groupName;
private HashMap<String, ThreadedTest> threadedTests = new HashMap<String, ThreadedTest>();
TestThreadGroup(String groupName) {
this.groupName = groupName;
}
/**
* Add a new test to the group.
* @param test - test to add.
*/
public void addTest(SystemTestCase test){
FixtureManager fm = FixtureManager.getInstance();
// set current fixture
test.setFixture(fm.getFixture(fm.getCurrentFixture()).getClass());
ThreadedTest threadedTest = new ThreadedTest(test);
if (!test.getTestDocumentation().isEmpty()){
threadedTests.put(test.getTestDocumentation(), threadedTest);
} else {
threadedTests.put(test.getName(), threadedTest);
}
}
/**
* Start the execution of all the tests that were added.
*/
public void start(){
ListenerstManager.getInstance().startBufferingReports(true);
for (String threadName : threadedTests.keySet()) {
threadedTests.get(threadName).setName(threadName);
if (TestThreadFactory.getInstance().isRunInParallel()){
threadedTests.get(threadName).start();
}
else {
threadedTests.get(threadName).run();
}
}
}
/**
* Join all the executions.
* @param timeout - the time to wait in milliseconds.
* @throws Exception
*/
public void join(long timeout) throws Exception{
ListenerstManager.getInstance().report("Joining " + threadedTests.size()+ " running tests");
for (String threadName : threadedTests.keySet()) {
threadedTests.get(threadName).join(timeout);
}
ListenerstManager.getInstance().report("Finished joining " + threadedTests.size() + " running tests");
for (String threadName : threadedTests.keySet()) {
if(threadedTests.get(threadName).isAlive()){
ListenerstManager.getInstance().report("Thread name '" + threadName + "' was still alive after timeout - interrupting thread", false);
threadedTests.get(threadName).interrupt();
}
}
ListenerstManager.getInstance().stopBufferingReports();
List<ReportElement> list = ListenerstManager.getInstance().getReportsBuffer();
if (list == null){
return;
}
ListenerstManager.getInstance().clearReportsBuffer();
HashMap<String, List<ReportElement>> reportsGroup = new HashMap<String, List<ReportElement>>();
//sort reports according to the threaded tests
for(ReportElement el: list){
if(!reportsGroup.containsKey(el.getOriginator())){
ArrayList<ReportElement> group = new ArrayList<ReportElement>();
reportsGroup.put(el.getOriginator(), group);
}
reportsGroup.get(el.getOriginator()).add(el);
}
if (TestThreadFactory.getInstance().isRunInParallel()){
for (String threadName : threadedTests.keySet()) {
ListenerstManager.getInstance().startLevel(threadName, EnumReportLevel.CurrentPlace);
//print buffered reports under correct level
for(ReportElement el: reportsGroup.get(threadName)){
//set threaded test fail status
if (el.getStatus() == Reporter.FAIL){
threadedTests.get(threadName).setPass(false);
// if report fail was found
if (threadedTests.get(threadName).getTest().getTestResult().wasSuccessful()){
threadedTests.get(threadName).setFailReports(true);
}
// if exception fail was found
else {
continue;
}
}
ListenerstManager.getInstance().report(el);
}
if (!threadedTests.get(threadName).isPass()){
if (threadedTests.get(threadName).isFailReports()){
threadedTests.get(threadName).setPass(false);
//print exception fail report, if exist
threadedTests.get(threadName).getTest().setPass(false);
threadedTests.get(threadName).getTest().getTestResult().addFailure(threadedTests.get(threadName).getTest(),
new AssertionFailedError("Fail report was submitted"));
threadedTests.get(threadName).setThrown(threadedTests.get(threadName).getTest().getTestResult().failures().nextElement().thrownException());
ListenerstManager.getInstance().addFailure(threadedTests.get(threadName).getTest(), (AssertionFailedError)threadedTests.get(threadName).getThrown());
}
else if (threadedTests.get(threadName).getTest().getTestResult().errorCount() > 0) {
//print exception message, if thrown
threadedTests.get(threadName).getTest().setPass(false);
threadedTests.get(threadName).setThrown(threadedTests.get(threadName).getTest().getTestResult().errors().nextElement().thrownException());
ListenerstManager.getInstance().addError(threadedTests.get(threadName).getTest(), threadedTests.get(threadName).getThrown());
}
}
ListenerstManager.getInstance().stopLevel();
}
}
else {
for(ReportElement el: reportsGroup.get("main")){
ListenerstManager.getInstance().report(el);
}
}
TestThreadFactory.getInstance().removeGroup(groupName);
}
/**
* @return group name.
*/
public String getGroupName() {
return groupName;
}
}
/**
* This class execute group tests in parallel.
*
*/
class ThreadedTest extends Thread{
private SystemTestCase test;
public SystemTestCase getTest() {
return test;
}
public void setTest(SystemTestCase test) {
this.test = test;
}
private boolean isPass = false;
private boolean failReports = false;
private Throwable thrown;
public ThreadedTest(SystemTestCase test){
this.test = test;
}
/**
* Run the test.
*/
public void run(){
test.run(new TestResult() {
public void addListener(TestListener listener) {
}
});
isPass = test.getTestResult().wasSuccessful();
//print exception reports, if exist
if (!isPass){
if (test.getTestResult().errorCount() > 0) {
thrown = test.getTestResult().errors().nextElement().thrownException();
}
ListenerstManager.getInstance().addError(test, thrown);
}
}
public void setPass(boolean isPass) {
this.isPass = isPass;
}
/**
* @return true if test was failed.
*/
public boolean isPass() {
return isPass;
}
/**
* @return true if test was failed with reports.
*/
public boolean isFailReports() {
return failReports;
}
public void setFailReports(boolean failReports) {
this.failReports = failReports;
}
public void setThrown(Throwable thrown) {
this.thrown = thrown;
}
/**
* @return exception that thrown by the test.
*/
public Throwable getThrown() {
return thrown;
}
}