package junit.runner;

import junit.framework.*;
import java.lang.reflect.*;
import java.text.NumberFormat;
import java.io.*;
import java.util.*;

/**
 * Base class for all test runners.
 * This class was born live on stage in Sardinia during XP2000.
 */
public abstract class BaseTestRunner implements TestListener {
    public static final String SUITE_METHODNAME= "suite";

    private static Properties fPreferences;
    static int fgMaxMessageLength= 500;
    static boolean fgFilterStack= true;
    boolean fLoading= true;

    /*
    * Implementation of TestListener
    */
    public synchronized void startTest(Test test) {
        testStarted(test.toString());
    }

    protected static void setPreferences(Properties preferences) {
        fPreferences= preferences;
    }

    protected static Properties getPreferences() {
        if (fPreferences == null) {
            fPreferences= new Properties();
             fPreferences.put("loading", "true");
             fPreferences.put("filterstack", "true");
              readPreferences();
        }
        return fPreferences;
    }

    public static void savePreferences() throws IOException {
        FileOutputStream fos= new FileOutputStream(getPreferencesFile());
        try {
            getPreferences().store(fos, "");
        } finally {
            fos.close();
        }
    }

    public void setPreference(String key, String value) {
        getPreferences().setProperty(key, value);
    }

    public synchronized void endTest(Test test) {
        testEnded(test.toString());
    }

    public synchronized void addError(final Test test, final Throwable t) {
        testFailed(TestRunListener.STATUS_ERROR, test, t);
    }

    public synchronized void addFailure(final Test test, final AssertionFailedError t) {
        testFailed(TestRunListener.STATUS_FAILURE, test, t);
    }

    // TestRunListener implementation

    public abstract void testStarted(String testName);

    public abstract void testEnded(String testName);

    public abstract void testFailed(int status, Test test, Throwable t);

    /**
     * Returns the Test corresponding to the given suite. This is
     * a template method, subclasses override runFailed(), clearStatus().
     */
    public Test getTest(String suiteClassName) {
        if (suiteClassName.length() <= 0) {
            clearStatus();
            return null;
        }
        Class testClass= null;
        try {
            testClass= loadSuiteClass(suiteClassName);
        } catch (ClassNotFoundException e) {
            String clazz= e.getMessage();
            if (clazz == null)
                clazz= suiteClassName;
            runFailed("Class not found \""+clazz+"\"");
            return null;
        } catch(Exception e) {
            runFailed("Error: "+e.toString());
            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); // 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;
    }

    /**
     * Returns the formatted string of the elapsed time.
     */
    public String elapsedTimeAsString(long runTime) {
        return NumberFormat.getInstance().format((double)runTime/1000);
    }

    /**
     * Processes the command line arguments and
     * returns the name of the suite class to run or null
     */
    protected String processArguments(String[] args) {
        String suiteName= null;
        for (int i= 0; i < args.length; i++) {
            if (args[i].equals("-noloading")) {
                setLoading(false);
            } else if (args[i].equals("-nofilterstack")) {
                fgFilterStack= false;
            } else if (args[i].equals("-c")) {
                if (args.length > i+1)
                    suiteName= extractClassName(args[i+1]);
                else
                    System.out.println("Missing Test class name");
                i++;
            } else {
                suiteName= args[i];
            }
        }
        return suiteName;
    }

    /**
     * Sets the loading behaviour of the test runner
     */
    public void setLoading(boolean enable) {
        fLoading= enable;
    }
    /**
     * Extract the class name from a String in VA/Java style
     */
    public String extractClassName(String className) {
        if(className.startsWith("Default package for"))
            return className.substring(className.lastIndexOf(".")+1);
        return className;
    }

    /**
     * Truncates a String to the maximum length.
     */
    public static String truncate(String s) {
        if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
            s= s.substring(0, fgMaxMessageLength)+"...";
        return s;
    }

    /**
     * Override to define how to handle a failed loading of
     * a test suite.
     */
    protected abstract void runFailed(String message);

    /**
     * Returns the loaded Class for a suite name.
     */
    protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
        return getLoader().load(suiteClassName);
    }

    /**
     * Clears the status message.
     */
    protected void clearStatus() { // Belongs in the GUI TestRunner class
    }

    /**
     * Returns the loader to be used.
     */
    public TestSuiteLoader getLoader() {
        if (useReloadingTestSuiteLoader())
            return new ReloadingTestSuiteLoader();
        return new StandardTestSuiteLoader();
    }

    protected boolean useReloadingTestSuiteLoader() {
        return getPreference("loading").equals("true") && !inVAJava() && fLoading;
    }

    private static File getPreferencesFile() {
         String home= System.getProperty("user.home");
         return new File(home, "junit.properties");
     }

     private static void readPreferences() {
         InputStream is= null;
         try {
             is= new FileInputStream(getPreferencesFile());
             setPreferences(new Properties(getPreferences()));
            getPreferences().load(is);
        } catch (IOException e) {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e1) {
            }
        }
     }

     public static String getPreference(String key) {
         return getPreferences().getProperty(key);
     }

     public static int getPreference(String key, int dflt) {
         String value= getPreference(key);
         int intValue= dflt;
         if (value == null)
             return intValue;
         try {
             intValue= Integer.parseInt(value);
          } catch (NumberFormatException ne) {
         }
         return intValue;
     }

     public static boolean inVAJava() {
        try {
            Class.forName("com.ibm.uvm.tools.DebugSupport");
        }
        catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * Returns a filtered stack trace
     */
    public static String getFilteredTrace(Throwable t) {
        StringWriter stringWriter= new StringWriter();
        PrintWriter writer= new PrintWriter(stringWriter);
        t.printStackTrace(writer);
        StringBuffer buffer= stringWriter.getBuffer();
        String trace= buffer.toString();
        return BaseTestRunner.getFilteredTrace(trace);
    }

    /**
     * Filters stack frames from internal JUnit classes
     */
    public static String getFilteredTrace(String stack) {
        if (showStackRaw())
            return stack;

        StringWriter sw= new StringWriter();
        PrintWriter pw= new PrintWriter(sw);
        StringReader sr= new StringReader(stack);
        // BEGIN android-changed
        // Use a sensible default buffer size
        BufferedReader br= new BufferedReader(sr, 1000);
        // END android-changed

        String line;
        try {
            while ((line= br.readLine()) != null) {
                if (!filterLine(line))
                    pw.println(line);
            }
        } catch (Exception IOException) {
            return stack; // return the stack unfiltered
        }
        return sw.toString();
    }

    protected static boolean showStackRaw() {
        return !getPreference("filterstack").equals("true") || fgFilterStack == false;
    }

    static boolean filterLine(String line) {
        String[] patterns= new String[] {
            "junit.framework.TestCase",
            "junit.framework.TestResult",
            "junit.framework.TestSuite",
            "junit.framework.Assert.", // don't filter AssertionFailure
            "junit.swingui.TestRunner",
            "junit.awtui.TestRunner",
            "junit.textui.TestRunner",
            "java.lang.reflect.Method.invoke("
        };
        for (int i= 0; i < patterns.length; i++) {
            if (line.indexOf(patterns[i]) > 0)
                return true;
        }
        return false;
    }

     static {
         fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
     }

}
