/* * 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; } } }