/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 3 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* Copyright 2006 - 2008 Pentaho Corporation. All rights reserved.
*
* @created Sep 8, 2005
* @author James Dixon
*/
package org.pentaho.test.platform.engine.core;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestListener;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.repository.ISolutionRepository;
import org.pentaho.platform.engine.core.messages.Messages;
import org.pentaho.platform.engine.core.system.PentahoBase;
import org.pentaho.platform.engine.core.system.PentahoSystem;
public class TestManager extends PentahoBase {
private static final long serialVersionUID = -4893201028464116019L;
public static final int STATUS_RUNNING = 1;
public static final int STATUS_SUCCESS = 2;
public static final int STATUS_FAILED = 3;
private static ArrayList<String> messages;
private static ArrayList<SuiteInfo> suites;
private static TestManager manager;
private String sampleDataDriver;
private String hibernateDriver;
public Log getLogger() {
return LogFactory.getLog(TestManager.class);
}
private static String propertyNames[] = { "os.name", //$NON-NLS-1$
"os.version", //$NON-NLS-1$
"java.version", //$NON-NLS-1$
"java.vendor", //$NON-NLS-1$
"user.language", //$NON-NLS-1$
"user.country" }; //$NON-NLS-1$
public static TestManager getInstance(TestSuite all) throws Exception {
if (manager == null) {
String testManagerClassName = PentahoSystem.getSystemSetting(
"test-suite/test-settings.xml", "test-manager", "org.pentaho.test.TestManager"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (testManagerClassName == null) {
testManagerClassName = "org.pentaho.test.TestManager"; //$NON-NLS-1$
}
Class componentClass = Class.forName(testManagerClassName.trim());
manager = (TestManager) componentClass.newInstance();
if (manager != null) {
manager.init(all);
} else {
throw new ClassNotFoundException();
}
}
return manager;
}
public int getSuiteIndex(String suite) {
for (int idx = 0; idx < suites.size(); idx++) {
if ((suites.get(idx)).className.equals(suite)) {
return idx;
}
}
return -1;
}
public String getSuite(int idx) {
if (idx < suites.size()) {
return (suites.get(idx)).className;
}
return null;
}
protected Enumeration getSuites(TestSuite all) {
return all.tests();
}
private void init(TestSuite all) {
Enumeration suitesEnum = getSuites(all);
suites = new ArrayList<SuiteInfo>();
while (suitesEnum.hasMoreElements()) {
TestSuite suite = (TestSuite) suitesEnum.nextElement();
SuiteInfo suiteInfo = new SuiteInfo(suite);
suites.add(suiteInfo);
suiteInfo.init();
}
// TODO find out the JDBC driver for the Sample Data connection
// TODO find out the JDBC driver for the Hibernate connection
sampleDataDriver = Messages.getInstance().getString("UI.USER_TEST_SUITE_UNKNOWN"); //$NON-NLS-1$
hibernateDriver = Messages.getInstance().getString("UI.USER_TEST_SUITE_UNKNOWN"); //$NON-NLS-1$
}
public SuiteInfo getSuite(String suiteClass) {
for (int idx = 0; idx < suites.size(); idx++) {
SuiteInfo suiteInfo = suites.get(idx);
if (suiteInfo.className.equals(suiteClass)) {
return suiteInfo;
}
}
return null;
}
public Document getStatus(IPentahoSession userSession) {
Document doc = DocumentHelper.createDocument();
Element root = doc.addElement("test-suites"); //$NON-NLS-1$
Element propertiesNode = root.addElement("properties"); //$NON-NLS-1$
Properties properties = System.getProperties();
for (String propertyName : propertyNames) {
String value = properties.getProperty(propertyName);
Element propertyNode = propertiesNode.addElement("property"); //$NON-NLS-1$
propertyNode.addAttribute("name", propertyName); //$NON-NLS-1$
propertyNode.addAttribute("value", value); //$NON-NLS-1$
}
// add some standard settings
Element propertyNode = propertiesNode.addElement("property"); //$NON-NLS-1$
propertyNode.addAttribute("name", Messages.getInstance().getString("UI.USER_TEST_SUITE_SOLUTION_REPOSITORY")); //$NON-NLS-1$ //$NON-NLS-2$
propertyNode.addAttribute("value", PentahoSystem.get(ISolutionRepository.class, userSession).getClass().toString()); //$NON-NLS-1$
propertyNode = propertiesNode.addElement("property"); //$NON-NLS-1$
propertyNode.addAttribute("name", "data.driver"); //$NON-NLS-1$ //$NON-NLS-2$
propertyNode.addAttribute("value", sampleDataDriver); //$NON-NLS-1$
propertyNode = propertiesNode.addElement("property"); //$NON-NLS-1$
propertyNode.addAttribute("name", "repository.driver"); //$NON-NLS-1$ //$NON-NLS-2$
propertyNode.addAttribute("value", hibernateDriver); //$NON-NLS-1$
for (int idx = 0; idx < suites.size(); idx++) {
SuiteInfo suiteInfo = suites.get(idx);
suiteInfo.getStatus(root);
}
return doc;
}
public TestInfo getTest(String suiteClass, String method) {
SuiteInfo suiteInfo = getSuite(suiteClass);
if (suiteInfo == null) {
return null;
}
TestInfo test = suiteInfo.getTest(method);
return test;
}
public void runSuite(String suiteClass) {
SuiteInfo suite = getSuite(suiteClass);
if (suite != null) {
suite.run();
}
}
public void runTest(String suiteClass, String method) {
TestInfo test = getTest(suiteClass, method);
test.run();
}
public static List<String> getMessagesList() {
return messages;
}
public class SuiteInfo implements TestListener {
private int NOT_RUNNING = 0;
private int PASS = 1;
private int FAIL = 2;
private int RUNNING = 3;
private int runCount = 0;
private int passCount = 0;
private int errorCount = 0;
private int failCount = 0;
private int status;
private HashMap<String,TestInfo> methodMap = new HashMap<String,TestInfo>();
private HashMap<Test,TestInfo> testMap = new HashMap<Test,TestInfo>();
private ArrayList<TestInfo> testList = new ArrayList<TestInfo>();
private TestSuite suite;
private String name;
private String className;
TestResult result;
private String message;
private int testCount;
public SuiteInfo(TestSuite suite) {
this.suite = suite;
name = suite.getName();
name = name.substring(name.lastIndexOf('.') + 1);
className = suite.getName();
testCount = suite.countTestCases();
result = new TestResult();
result.addListener(this);
}
public void init() {
Enumeration testsEnum = suite.tests();
while (testsEnum.hasMoreElements()) {
Test test = (Test) testsEnum.nextElement();
TestInfo testInfo = new TestInfo(test, this);
addTestInfo(testInfo);
}
}
public void addTestInfo(TestInfo info) {
methodMap.put(info.methodName, info);
testMap.put(info.test, info);
testList.add(info);
}
public TestInfo getTest(String method) {
return methodMap.get(method);
}
public void run() {
status = RUNNING;
suite.run(result);
}
public void stop() {
result.stop();
status = NOT_RUNNING;
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_STOPPED"); //$NON-NLS-1$
}
public void addError(Test test, Throwable error) {
message = error.getMessage();
errorCount++;
status = FAIL;
TestInfo testInfo = testMap.get(test);
testInfo.addError(error);
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_FAILED"); //$NON-NLS-1$
}
public void addFailure(Test test, AssertionFailedError error) {
message = error.getMessage();
failCount++;
status = FAIL;
TestInfo testInfo = testMap.get(test);
testInfo.addFailure(error);
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_FAILED"); //$NON-NLS-1$
}
public void endTest(Test test) {
if (status != FAIL) {
passCount++;
}
status = NOT_RUNNING;
TestInfo testInfo = testMap.get(test);
testInfo.endTest();
message = ""; //$NON-NLS-1$
}
public void startTest(Test test) {
runCount++;
TestInfo testInfo = testMap.get(test);
testInfo.startTest();
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_RUNNING"); //$NON-NLS-1$
}
public Node getStatus(Element parent) {
Element node = parent.addElement("suite"); //$NON-NLS-1$
node.addAttribute("class", className); //$NON-NLS-1$
node.addAttribute("name", name); //$NON-NLS-1$
node.addAttribute("test-count", Integer.toString(testCount)); //$NON-NLS-1$
node.addAttribute("run-count", Integer.toString(runCount)); //$NON-NLS-1$
node.addAttribute("pass-count", Integer.toString(passCount)); //$NON-NLS-1$
node.addAttribute("fail-count", Integer.toString(errorCount + failCount)); //$NON-NLS-1$
Element messageNode = node.addElement("message"); //$NON-NLS-1$
Element tests = node.addElement("tests"); //$NON-NLS-1$
int currentPassCount = 0;
int currentRunCount = 0;
int currentFailCount = 0;
for (int idx = 0; idx < testList.size(); idx++) {
TestInfo test = testList.get(idx);
test.getStatus(tests);
if (test.lastResult == PASS) {
currentPassCount++;
}
if (test.lastResult == FAIL) {
currentFailCount++;
}
if (test.lastResult != test.NOT_RUN) {
currentRunCount++;
}
}
if (currentRunCount == 0) {
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_NOT_RUN"); //$NON-NLS-1$
} else if (currentRunCount == currentPassCount && currentRunCount < testCount) {
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_SOME_PASSED"); //$NON-NLS-1$
} else if (currentRunCount == currentPassCount && currentRunCount == testCount) {
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_ALL_PASSED"); //$NON-NLS-1$
} else if (currentFailCount > 0) {
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_SOME_FAILURES"); //$NON-NLS-1$
}
messageNode.setText((message == null) ? "" : message); //$NON-NLS-1$
return node;
}
}
public class TestInfo implements TestListener {
private int NOT_RUNNING = 0;
private int PASS = 1;
private int FAIL = 2;
private int NOT_RUN = 3;
private int RUNNING = 3;
private int runCount = 0;
private int passCount = 0;
private int errorCount = 0;
private int failCount = 0;
private int status = NOT_RUNNING;
private int lastResult = NOT_RUN;
private Date timestamp;
private String message;
private Test test;
private String name;
private String methodName;
TestResult result;
double duration = 0;
DecimalFormat fmt = new DecimalFormat("#.000"); //$NON-NLS-1$
SuiteInfo suiteInfo;
public TestInfo(Test test, SuiteInfo suiteInfo) {
this.test = test;
this.suiteInfo = suiteInfo;
String testName = test.toString();
testName = testName.substring(0, testName.indexOf('('));
methodName = testName;
name = testName.substring(4);
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_NOT_RUN"); //$NON-NLS-1$
result = new TestResult();
result.addListener(this);
}
public void run() {
status = RUNNING;
timestamp = new Date();
test.run(result);
}
public void stop() {
result.stop();
status = NOT_RUNNING;
duration = -1;
}
public void addError(Test theTest, Throwable error) {
suiteInfo.addError(theTest, error);
}
public void addError(Throwable error) {
errorCount++;
status = FAIL;
message = error.getLocalizedMessage();
duration = -1;
}
public void addFailure(Test theTest, AssertionFailedError error) {
suiteInfo.addFailure(theTest, error);
}
public void addFailure(AssertionFailedError error) {
failCount++;
status = FAIL;
message = error.getLocalizedMessage();
duration = -1;
}
public void endTest(Test theTest) {
suiteInfo.endTest(theTest);
}
public void endTest() {
if (status != FAIL) {
passCount++;
Date now = new Date();
duration = (now.getTime() - timestamp.getTime());
lastResult = PASS;
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_PASSED"); //$NON-NLS-1$
} else {
lastResult = FAIL;
}
status = NOT_RUNNING;
}
public void startTest(Test theTest) {
suiteInfo.startTest(theTest);
}
public void startTest() {
runCount++;
status = RUNNING;
message = Messages.getInstance().getString("UI.USER_TEST_SUITE_RUNNING"); //$NON-NLS-1$
timestamp = new Date();
}
public Node getStatus(Element parent) {
Element node = parent.addElement("test"); //$NON-NLS-1$
node.addAttribute("method", methodName); //$NON-NLS-1$
node.addAttribute("name", name); //$NON-NLS-1$
node
.addAttribute(
"last-run", (timestamp == null) ? Messages.getInstance().getString("UI.USER_TEST_SUITE_UNKNOWN") : DateFormat.getDateTimeInstance().format(timestamp)); //$NON-NLS-1$ //$NON-NLS-2$
node.addAttribute("run-count", Integer.toString(runCount)); //$NON-NLS-1$
node.addAttribute("pass-count", Integer.toString(passCount)); //$NON-NLS-1$
node.addAttribute("fail-count", Integer.toString(errorCount + failCount)); //$NON-NLS-1$
if (lastResult == FAIL) {
node.addAttribute("duration", "-1"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
node.addAttribute("duration", fmt.format(duration / 1000)); //$NON-NLS-1$
}
Element messageNode = node.addElement("message"); //$NON-NLS-1$
messageNode.setText((message == null) ? "" : message); //$NON-NLS-1$
return node;
}
}
}