/* * 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 2005 - 2013 Pentaho Corporation. All rights reserved. */ package org.pentaho.test.platform.engine.core; 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.repository2.unified.IUnifiedRepository; import org.pentaho.platform.engine.core.messages.Messages; import org.pentaho.platform.engine.core.system.PentahoBase; import org.pentaho.platform.engine.core.system.PentahoSystem; 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; 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( IUnifiedRepository.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; } } }