Package org.eclipse.test

Source Code of org.eclipse.test.EclipseTestRunner$TestFailedException

/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestListener;
import junit.framework.TestResult;
import junit.framework.TestSuite;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;

/**
* A TestRunner for JUnit that supports Ant JUnitResultFormatters
* and running tests inside Eclipse.
* Example call: EclipseTestRunner -classname junit.samples.SimpleTest formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter
*/
public class EclipseTestRunner implements TestListener {
  class TestFailedException extends Exception {

    private static final long serialVersionUID = 6009335074727417445L;

    TestFailedException(String message) {
      super(message);
    }
   
    TestFailedException(Throwable e) {
        super(e);
    }
  }
  /**
     * No problems with this test.
     */
    public static final int SUCCESS= 0;
    /**
     * Some tests failed.
     */
    public static final int FAILURES= 1;
    /**
     * An error occured.
     */
    public static final int ERRORS= 2;
   
    private static final String SUITE_METHODNAME= "suite"
  /**
   * The current test result
   */
  private TestResult fTestResult;
  /**
   * The name of the plugin containing the test
   */
  private String fTestPluginName;
  /**
     * The corresponding testsuite.
     */
    private Test fSuite;
    /**
     * Formatters from the command line.
     */
  private static Vector fgFromCmdLine= new Vector();
  /**
     * Holds the registered formatters.
     */
    private Vector formatters= new Vector();
    /**
     * Do we stop on errors.
     */
    private boolean fHaltOnError= false;
    /**
     * Do we stop on test failures.
     */
    private boolean fHaltOnFailure= false;
    /**
     * The TestSuite we are currently running.
     */
    private JUnitTest fJunitTest;
    /**
     * output written during the test
     */
    private PrintStream fSystemError;
    /**
     * Error output during the test
     */
    private PrintStream fSystemOut;  
    /**
     * Exception caught in constructor.
     */
    private Exception fException;
    /**
     * Returncode
     */
    private int fRetCode= SUCCESS; 
   
  /**
   * The main entry point (the parameters are not yet consistent with
   * the Ant JUnitTestRunner, but eventually they should be).
   * Parameters<pre>
   * -className: the name of the testSuite
   * -testPluginName: the name of the containing plugin
     * haltOnError: halt test on errors?
     * haltOnFailure: halt test on failures?
     * -testlistener listenerClass: deprecated
     *     print a warning that this option is deprecated
     * formatter: a JUnitResultFormatter given as classname,filename.
     *    If filename is ommitted, System.out is assumed.
     * </pre>
     */
  public static void main(String[] args) throws IOException {
    System.exit(run(args));
  }
  public static int run(String[] args) throws IOException {
    String className= null;
    String testPluginName= null;
   
        boolean haltError = false;
        boolean haltFail = false;
       
        Properties props = new Properties();
   
    int startArgs= 0;
    if (args.length > 0) {
      // support the JUnit task commandline syntax where
      // the first argument is the name of the test class
      if (!args[0].startsWith("-")) {
        className= args[0];
        startArgs++;
      }
    }
    for (int i= startArgs; i < args.length; i++) {
      if (args[i].toLowerCase().equals("-classname")) {
        if (i < args.length-1)
          className= args[i+1];
        i++; 
      } else if (args[i].toLowerCase().equals("-testpluginname")) {
        if (i < args.length-1)
          testPluginName= args[i+1];
        i++; 
      } else if (args[i].startsWith("haltOnError=")) {
                haltError= Project.toBoolean(args[i].substring(12));
            } else if (args[i].startsWith("haltOnFailure=")) {
                haltFail = Project.toBoolean(args[i].substring(14));
            } else if (args[i].startsWith("formatter=")) {
                try {
                    createAndStoreFormatter(args[i].substring(10));
                } catch (BuildException be) {
                    System.err.println(be.getMessage());
                    return ERRORS;
                }
            } else if (args[i].startsWith("propsfile=")) {
                FileInputStream in = new FileInputStream(args[i].substring(10));
                props.load(in);
                in.close();
            } else if (args[i].equals("-testlistener")) {
              System.err.println("The -testlistener option is no longer supported\nuse the formatter= option instead");
              return ERRORS;
      }
        }
     
    if (className == null)
      throw new IllegalArgumentException("Test class name not specified");
   
        JUnitTest t= new JUnitTest(className);

        // Add/overlay system properties on the properties from the Ant project
        Hashtable p= System.getProperties();
        for (Enumeration _enum = p.keys(); _enum.hasMoreElements(); ) {
            Object key = _enum.nextElement();
            props.put(key, p.get(key));
        }
        t.setProperties(props);
 
      EclipseTestRunner runner= new EclipseTestRunner(t, testPluginName, haltError, haltFail);
        transferFormatters(runner);
        runner.run();
        return runner.getRetCode();
  }

    /**
     *  
     */
    public EclipseTestRunner(JUnitTest test, String testPluginName, boolean haltOnError, boolean haltOnFailure) {
        fJunitTest= test;
        fTestPluginName= testPluginName;
        fHaltOnError= haltOnError;
        fHaltOnFailure= haltOnFailure;
       
        try {
            fSuite= getTest(test.getName());
        } catch(Exception e) {
            fRetCode = ERRORS;
            fException = e;
        }
    }
 
  /**
   * Returns the Test corresponding to the given suite.
   */
  protected Test getTest(String suiteClassName) throws TestFailedException {
    if (suiteClassName.length() <= 0) {
      clearStatus();
      return null;
    }
    Class testClass= null;
    try {
      testClass= loadSuiteClass(suiteClassName);
    } catch (ClassNotFoundException e) {
        if (e.getCause() != null) {
            runFailed(e.getCause());
        }
      String clazz= e.getMessage();
      if (clazz == null)
        clazz= suiteClassName;
      runFailed("Class not found \""+clazz+"\"");
      return null;
    } catch(Exception e) {
        runFailed(e);
      return null;
    }
    Method suiteMethod= null;
    try {
      suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
     } catch(Exception e) {
       // try to extract a test suite automatically
      clearStatus();     
      return new TestSuite(testClass);
    }
     if (!Modifier.isStatic(suiteMethod.getModifiers())) {
       runFailed("suite() method must be static");
       return null;
     }
    Test test= null;
    try {
      test= (Test)suiteMethod.invoke(null, new Class[0]); // static method
      if (test == null)
        return test;
    }
    catch (InvocationTargetException e) {
      runFailed("Failed to invoke suite():" + e.getTargetException().toString());
      return null;
    }
    catch (IllegalAccessException e) {
      runFailed("Failed to invoke suite():" + e.toString());
      return null;
    }
    clearStatus();
    return test;
  }

  protected void runFailed(String message) throws TestFailedException {
    System.err.println(message);
    throw new TestFailedException(message);
  }

    protected void runFailed(Throwable e) throws TestFailedException {
      e.printStackTrace();
      throw new TestFailedException(e);
    }

  protected void clearStatus() {
  }

  /**
   * Loads the class either with the system class loader or a
   * plugin class loader if a plugin name was specified
   */
  protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
    if (fTestPluginName == null)
      return Class.forName(suiteClassName);
        Bundle bundle = Platform.getBundle(fTestPluginName);
        if (bundle == null) {
            throw new ClassNotFoundException(suiteClassName, new Exception("Could not find plugin \""
                    + fTestPluginName + "\""));
        }
       
        //is the plugin a fragment?
    Dictionary headers = bundle.getHeaders();
    String hostHeader = (String) headers.get(Constants.FRAGMENT_HOST);
    if (hostHeader != null) {
      // we are a fragment for sure
      // we need to find which is our host
      ManifestElement[] hostElement = null;
      try {
        hostElement = ManifestElement.parseHeader(Constants.FRAGMENT_HOST, hostHeader);
      } catch (BundleException e) {
        throw new RuntimeException("Could not find host for fragment:" + fTestPluginName,e);
      }
      Bundle host = Platform.getBundle(hostElement[0].getValue());
      //we really want to get the host not the fragment
      bundle = host;
    }

        return bundle.loadClass(suiteClassName);
  }
 
  public void run() {
//    IPerformanceMonitor pm = PerfMsrCorePlugin.getPerformanceMonitor(true);
   
        fTestResult= new TestResult();
        fTestResult.addListener(this);
        for (int i= 0; i < formatters.size(); i++) {
            fTestResult.addListener((TestListener)formatters.elementAt(i));
        }

        long start= System.currentTimeMillis();
        fireStartTestSuite();
       
        if (fException != null) { // had an exception in the constructor
            for (int i= 0; i < formatters.size(); i++) {
                ((TestListener)formatters.elementAt(i)).addError(null, fException);
            }
            fJunitTest.setCounts(1, 0, 1);
            fJunitTest.setRunTime(0);
        } else {
            ByteArrayOutputStream errStrm = new ByteArrayOutputStream();
            fSystemError= new PrintStream(errStrm);
           
            ByteArrayOutputStream outStrm = new ByteArrayOutputStream();
            fSystemOut= new PrintStream(outStrm);

            try {
//              pm.snapshot(1); // before
                fSuite.run(fTestResult);
            } finally {
//             pm.snapshot(2); // after   
                fSystemError.close();
                fSystemError= null;
                fSystemOut.close();
                fSystemOut= null;
                sendOutAndErr(new String(outStrm.toByteArray()), new String(errStrm.toByteArray()));
                fJunitTest.setCounts(fTestResult.runCount(), fTestResult.failureCount(), fTestResult.errorCount());
                fJunitTest.setRunTime(System.currentTimeMillis() - start);
            }
        }
        fireEndTestSuite();

        if (fRetCode != SUCCESS || fTestResult.errorCount() != 0) {
            fRetCode = ERRORS;
        } else if (fTestResult.failureCount() != 0) {
            fRetCode = FAILURES;
        }
       
//        pm.upload(getClass().getName());
    }
 
    /**
     * Returns what System.exit() would return in the standalone version.
     *
     * @return 2 if errors occurred, 1 if tests failed else 0.
     */
    public int getRetCode() {
        return fRetCode;
    }

    /*
     * @see TestListener.addFailure
     */
    public void startTest(Test t) {}

    /*
     * @see TestListener.addFailure
     */
    public void endTest(Test test) {}

    /*
     * @see TestListener.addFailure
     */
    public void addFailure(Test test, AssertionFailedError t) {
        if (fHaltOnFailure) {
            fTestResult.stop();
        }
    }

    /*
     * @see TestListener.addError
     */
    public void addError(Test test, Throwable t) {
        if (fHaltOnError) {
            fTestResult.stop();
        }
    }
   
  private void fireStartTestSuite() {
    for (int i= 0; i < formatters.size(); i++) {
            ((JUnitResultFormatter)formatters.elementAt(i)).startTestSuite(fJunitTest);
        }
    }

    private void fireEndTestSuite() {
        for (int i= 0; i < formatters.size(); i++) {
            ((JUnitResultFormatter)formatters.elementAt(i)).endTestSuite(fJunitTest);
        }
    }

    public void addFormatter(JUnitResultFormatter f) {
        formatters.addElement(f);
    }

    /**
     * Line format is: formatter=<classname>(,<pathname>)?
     */
    private static void createAndStoreFormatter(String line) throws BuildException {
        String formatterClassName= null;
        File formatterFile= null;
       
        int pos = line.indexOf(',');
        if (pos == -1) {
            formatterClassName= line;
        } else {
            formatterClassName= line.substring(0, pos);
            formatterFile= new File(line.substring(pos + 1)); // the method is package visible
        }
        fgFromCmdLine.addElement(createFormatter(formatterClassName, formatterFile));
    }

    private static void transferFormatters(EclipseTestRunner runner) {
        for (int i= 0; i < fgFromCmdLine.size(); i++) {
            runner.addFormatter((JUnitResultFormatter)fgFromCmdLine.elementAt(i));
        }
    }

  /*
   * DUPLICATED from FormatterElement, since it is package visible only
   */
    private static JUnitResultFormatter createFormatter(String classname, File outfile) throws BuildException {
      OutputStream out= System.out;

        if (classname == null) {
            throw new BuildException("you must specify type or classname");
        }
        Class f = null;
        try {
            f= EclipseTestRunner.class.getClassLoader().loadClass(classname);
        } catch (ClassNotFoundException e) {
            throw new BuildException(e);
        }

        Object o = null;
        try {
            o = f.newInstance();
        } catch (InstantiationException e) {
            throw new BuildException(e);
        } catch (IllegalAccessException e) {
            throw new BuildException(e);
        }

        if (!(o instanceof JUnitResultFormatter)) {
            throw new BuildException(classname+" is not a JUnitResultFormatter");
        }

        JUnitResultFormatter r = (JUnitResultFormatter) o;

        if (outfile != null) {
            try {
                out = new FileOutputStream(outfile);
            } catch (java.io.IOException e) {
                throw new BuildException(e);
            }
        }
        r.setOutput(out);
        return r;
    }

    private void sendOutAndErr(String out, String err) {
        for (int i=0; i<formatters.size(); i++) {
            JUnitResultFormatter formatter =
                ((JUnitResultFormatter)formatters.elementAt(i));
           
            formatter.setSystemOutput(out);
            formatter.setSystemError(err);
        }
    }
   
    protected void handleOutput(String line) {
        if (fSystemOut != null) {
            fSystemOut.println(line);
        }
    }
   
    protected void handleErrorOutput(String line) {
        if (fSystemError != null) {
            fSystemError.println(line);
        }
    }
}  
TOP

Related Classes of org.eclipse.test.EclipseTestRunner$TestFailedException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.