/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.framework;

import java.io.*;
import java.util.*;

import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.sessions.*;

/**
 * <p><b>Purpose</b>: TestCollection is a collection of test suites and models. When a test collection is executed
 * all the test entities registered with it are executed one by one.
 */
public abstract class TestCollection extends junit.framework.TestSuite implements TestEntity {

    /** Store the name to allow serialization, for some reason JUnit name does not serialize. */
    private String name;

    /** Stores all the tests */
    private Vector tests;

    /** Stores the summary of the tests */
    private TestResultsSummary summary;

    /** Description of the test collection */
    private String description;
    private transient TestExecutor executor;

    /** The test collection that contains this test */
    private TestEntity container;

    /** This is used only for printing test results with proper indentation */
    private int nestedCounter;

    /** The indentation string that is added to each line of result for printing. */
    private String indentationString;

    /** Stores the last tests that were run. */
    private Vector finishedTests;

    /** A flag that indicates if the test collection is inside SRG. */
    protected boolean isSRG;

    public TestCollection() {
        initialize();
    }

    /**
     * Constructs a TestSuite from the given class with the given name.
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public TestCollection(Class theClass, String name) {
        super(theClass, name);
        initialize();
    }

    /**
     * Constructs a TestSuite from the given class. Adds all the methods
     * starting with "test" as test cases to the suite.
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public TestCollection(final Class theClass) {
        super(theClass);
        initialize();
    }

    public void initialize() {
        description = "";
        nestedCounter = INITIAL_VALUE;
        tests = new Vector();
        finishedTests = new Vector();
        summary = new TestResultsSummary(this);
        if ((getName() == null) || (getName().length() == 0)) {
            setName(getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1));
        } else {
            setName(getName());
        }
    }

    /**
     * Reset the JUnit name in case serialization looses it.
     */
    @Override
    public String getName() {
        if (super.getName() == null) {
            setName(this.name);
        }
        return super.getName();
    }

    /**
     * Store the test name locally to ensure it can serialize.
     */
    @Override
    public void setName(String name) {
       super.setName(name);
       this.name = name;
    }

    /**
     * Adds a test to itself
     */
    @Override
    public final void addTest(junit.framework.Test test) {
        super.addTest(test);
        if (test instanceof TestEntity) {
            ((TestEntity)test).setContainer(this);
        }
        getTests().add(test);
    }

    public abstract void addTests();

    public void addSRGTests() {
    }

    /**
     * Adds a test collection to itself
     */
    public final void addTests(Vector theTests) {
        for (Enumeration allTests = theTests.elements(); allTests.hasMoreElements();) {
            junit.framework.Test test = (junit.framework.Test)allTests.nextElement();
            addTest(test);
        }
    }

    public final void addServerTest(TestCase theTest) {
        TestCase serverTestCase;
        Class<?> serverTestCaseClass;
        Object[] args = new Object[1];

        try {

            /** The code below is doing a roundabout version of the following (because of packaging problems):
             *
             * org.eclipse.persistence.testing.framework.ejb.ServerTestCase serverTestCase;
             * serverTestCase = new org.eclipse.persistence.testing.framework.ejb.ServerTestCase(
             *   (org.eclipse.persistence.testing.ejb20.cmp.wls.TestFramework.EJBTestCase)theTest);
             */
            serverTestCaseClass = Class.forName("org.eclipse.persistence.testing.framework.ejb.ServerTestCase");
            args[0] = theTest;
            serverTestCase = (TestCase)serverTestCaseClass.getConstructors()[0].newInstance(args);

            serverTestCase.setName(theTest.getName());
            addTest(serverTestCase);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Append test summaries of the collection of tests.
     */
    @Override
    public void appendTestResult(TestResultsSummary summary) {
        summary.appendTestCollectionResult(this);
    }

    /**
     * Computes the level for indentation.
     */
    @Override
    public void computeNestedLevel() {
        TestEntity testContainer = getContainer();

        if ((testContainer != null) && (testContainer.getNestedCounter() != INITIAL_VALUE)) {
            setNestedCounter(testContainer.getNestedCounter() + 1);
        } else {
            incrementNestedCounter();
        }
    }

    /**
     * The session is initialized to the default login from the Persistent System
     * if no explicit login is done for testing. This method must be overridden in
     * the subclasses if different login is required.
     */
    @Override
    public Session defaultLogin() {
        return (new TestSystem()).login();
    }

    /**
     * Return test collection which contains this test entity.
     */
    @Override
    public TestEntity getContainer() {
        return container;
    }

    /**
     * Return the description of the test.
     */
    public String getDescription() {
        return description;
    }

    /**
     * Return the executor.
     */
    protected TestExecutor getExecutor() {
        return executor;
    }

    public Vector getFinishedTests() {
        return finishedTests;
    }

    /**
     * Return the indentaitonString
     */
    public String getIndentationString() {
        return indentationString;
    }

    /**
     * Return the nested counter. This is used finally used to do proper indentation.
     */
    @Override
    public int getNestedCounter() {
        return nestedCounter;
    }

    /**
     * Return the summary of the test execution.
     */
    @Override
    public ResultInterface getReport() {
        return getSummary();
    }

    /**
     * Return the session.
     */
    protected org.eclipse.persistence.sessions.Session getSession() {
        return getExecutor().getSession();
    }

    /**
     * Return the session cast to DatabaseSession.
     */
    public org.eclipse.persistence.sessions.DatabaseSession getDatabaseSession() {
        return (org.eclipse.persistence.sessions.DatabaseSession)getExecutor().getSession();
    }

    /**
     * Return the session cast to AbstractSession.
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getAbstractSession() {
        return (org.eclipse.persistence.internal.sessions.AbstractSession)getExecutor().getSession();
    }

    /**
     * Return the summary of the test execution.
     */
    protected TestResultsSummary getSummary() {
        return summary;
    }

    /**
     * Return all the test entities associated with this collection.
     */
    public Vector getTests() {
        return tests;
    }

    /**
     * Counts the number of test cases that will be run by this test.
     * If the tests have not been added yet just return 1.
     */
    @Override
    public int countTestCases() {
        if (getTests().isEmpty()) {
            return 1;
        }
        return super.countTestCases();
    }

    /**
     * Returns the number of tests in this suite
     */
    @Override
    public int testCount() {
        return getTests().size();
    }

    /**
     * Returns the tests as an enumeration
     */
    @Override
    public Enumeration tests() {
        return getTests().elements();
    }

    /**
     * Returns the test at the given index
     */
    @Override
    public junit.framework.Test testAt(int index) {
        return (junit.framework.Test)getTests().elementAt(index);
    }

    @Override
    public void incrementNestedCounter() {
        setNestedCounter(getNestedCounter() + 1);
    }

    /**
     * Runs the tests and collects their result in a TestResult.
     */
    @Override
    public void run(junit.framework.TestResult result) {
        TestExecutor.setDefaultJUnitTestResult(result);
        try {
            TestExecutor executor = getExecutor();
            if (executor == null) {
                executor = TestExecutor.getDefaultExecutor();
            }
            execute(executor);
        } catch (Throwable exception) {
            if (exception instanceof TestWarningException) {
                    System.out.println("WARNING: " + exception);
            } else {
                result.addError(this, exception);
            }
        }
    }

    /**
     * Add foot note the the result for printing.
     */
    abstract protected void logFootNote(Writer log);

    /**
     * Add head note the the result for printing.
     * This method is added to migrate tests to Ora*Tst
     */
    abstract protected void logRegressionHeadNote(Writer log);

    /**
     * Add head note the the result for printing.
     */
    abstract protected void logHeadNote(Writer log);

    /**
     * Logs the result summary of the suite on the print stream.
     * This method is added to migrate tests to Ora*Tst
     */
    @Override
    public void logRegressionResult(Writer log) {
        logResult(log, false, true);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    @Override
    public void logResult(Writer log) {
        logResult(log, false, false);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    @Override
    public void logResult(Writer log, boolean logOnlyErrors) {
        logResult(log, logOnlyErrors, false);
    }

    /**
     * Logs the result summary of the suite on the print stream.
     */
    public void logResult(Writer log, boolean logOnlyErrors, boolean regression) {
        computeResultSummary();
        setIndentationString(Helper.getTabs(getNestedCounter()));

        if (regression) {
            logRegressionHeadNote(log);
        } else {
            logHeadNote(log);
        }

        for (Enumeration tests = getFinishedTests().elements(); tests.hasMoreElements();) {
            junit.framework.Test test = ((junit.framework.Test)tests.nextElement());
            if (test instanceof TestEntity) {
                TestEntity testEntity = (TestEntity)test;
                if (regression) {
                    if (!(testEntity instanceof TestCase) || !(testEntity.getReport().hasPassed() || ((TestResult)testEntity.getReport()).hasWarning())) {
                        testEntity.logRegressionResult(log);
                    }
                } else {
                    if ((!(testEntity instanceof TestCase)) || testEntity.getReport().shouldLogResult()) {
                        if (!logOnlyErrors || !(testEntity instanceof TestCollection) || !testEntity.getReport().hasPassed()) {
                            testEntity.logResult(log, logOnlyErrors);
                        }
                    }
                }
            } else {
                TestExecutor.logJUnitResult(test, log, Helper.getTabs(getNestedCounter() + 1));
            }
        }

        logFootNote(log);
        if (regression) {
            getSummary().logRegressionResult(log);
        } else {
            getSummary().logResult(log);
        }
    }

    /**
     * Compute the reuslt summary.
     */
    public void computeResultSummary() {
        getSummary().resetTotals();
        for (Enumeration tests = getFinishedTests().elements(); tests.hasMoreElements();) {
            junit.framework.Test test = ((junit.framework.Test)tests.nextElement());
            if (test instanceof TestCase) {
                TestCase testEntity = (TestCase)test;
                testEntity.appendTestResult(getSummary());
            } else if (test instanceof TestCollection) {
                TestCollection testEntity = (TestCollection)test;
                testEntity.computeResultSummary();
                testEntity.appendTestResult(getSummary());
            } else {
                junit.framework.TestResult result = (junit.framework.TestResult) TestExecutor.getJUnitTestResults().get(test);
                getSummary().appendTestResult(result);
            }
        }
    }

    /**
     * Remove the test colleciton.
     */
    protected void removeTest(TestEntity test) {
        getTests().removeElement(test);
    }

    @Override
    public boolean requiresDatabase() {
        return true;
    }

    @Override
    public abstract void resetEntity();

    /**
     * Reinitialize the nested counter value.
     */
    @Override
    public void resetNestedCounter() {
        setNestedCounter(INITIAL_VALUE);
        for (Enumeration tests = getTests().elements(); tests.hasMoreElements();) {
            Object test = tests.nextElement();
            if (test instanceof TestEntity) {
                ((TestEntity)test).resetNestedCounter();
            }
        }
    }

    /**
     * Set the test collection which contains this test
     */
    @Override
    public void setContainer(TestEntity testEntity) {
        container = testEntity;
    }

    /**
     * Set the description of the test.
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Set the executor.
     */
    public void setExecutor(TestExecutor anExecutor) {
        executor = anExecutor;
    }

    public void setFinishedTests(Vector finishedTests) {
        this.finishedTests = finishedTests;
    }

    /**
     * Set the indentaitonString
     */
    public void setIndentationString(String indentationString) {
        this.indentationString = indentationString;
    }

    /**
     * Set the nested counter value.
     */
    @Override
    public void setNestedCounter(int level) {
        this.nestedCounter = level;
    }

    /**
     * Set the summary of the test collection.
     */
    protected void setSummary(TestResultsSummary theSummary) {
        summary = theSummary;
        theSummary.setTestCollection(this);
    }

    /**
     * Set the test result.
     */
    @Override
    public void setReport(ResultInterface summary) {
        setSummary((TestResultsSummary)summary);
    }

    protected final void setTests(Vector theTests) {
        tests = theTests;
    }

    public abstract void setupEntity() throws Throwable;

    /**
     * Print the test as its name.
     */
    public String toString() {
        return getName();
    }
}
