/*
 * 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.tests.simultaneous;

import java.io.*;
import java.util.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.sessions.server.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.framework.ui.SynchronizedTester;
import org.eclipse.persistence.testing.framework.ui.SynchronizedTestExecutor;

public class MultithreadTestCase extends AutoVerifyTestCase {
    protected TestCase[] test;
    protected int numberOfTests;
    protected boolean useSequenceConnectionPool = false;

    protected class TestEventListenerImpl implements junit.framework.TestListener {
        public static final int INITIAL = 0;
        public static final int STARTED = 1;
        public static final int FINISHED = 2;
        private int state;

        private TestEventListenerImpl() {
            state = INITIAL;
        }

        @Override
        public void addError(junit.framework.Test test, Throwable error) {
        }

        @Override
        public void addFailure(junit.framework.Test test, junit.framework.AssertionFailedError error) {
        }

        @Override
        public void endTest(junit.framework.Test test) {
            state = FINISHED;
        }

        @Override
        public void startTest(junit.framework.Test test) {
            state = STARTED;
        }

        public boolean isStarted() {
            return state == STARTED;
        }

        public boolean isFinished() {
            return state == FINISHED;
        }
    }
    ;

    protected TestEventListenerImpl[] testExecutorListener;
    protected TestExecutorWithClientSession[] testExecutorWithClientSession;
    protected SynchronizedTestExecutor[] testThread;

    protected class SynchronizedTesterImpl implements SynchronizedTester {
        public static final int INITIAL = 0;
        public static final int FINISHED = 1;
        private int state;
        private Throwable exception;

        private SynchronizedTesterImpl() {
            state = INITIAL;
        }

        @Override
        public void finishedTest() {
            state = FINISHED;
        }

        @Override
        public void notifyException(Throwable exception) {
            this.exception = exception;
        }

        public boolean isFinished() {
            return state == FINISHED;
        }

        public Throwable getException() {
            return exception;
        }
    }
    ;

    protected SynchronizedTesterImpl[] testThreadListener;
    protected Hashtable allowedExceptions;
    private Session originalSession;

    /**
     * Default constructor for MultithreadTestCase
     * Added to allow easier subclassing.  This constructor should only be used by subclasses.
     * addTests() must be called immediately after this constructor by the subclass
     */
    protected MultithreadTestCase() {
        super();
        setDescription("Runs several tests simultaneously");
        allowedExceptions = new Hashtable();
        addAllowedException("org.eclipse.persistence.exceptions.OptimisticLockException");
    }

    // MultithreadTestCase runs simultaneously each of the TestCases
    // passed in Vector tests.
    public MultithreadTestCase(Vector test) {
        this();
        setTests(test);
    }

    // If an exception occur in one of concurrently run tests,
    // MultithreadTestCase assigned this exception (and therefore status "Failed"),
    // unless the exception is on allowedExceptions list (see verify()).
    // By default, only org.eclipse.persistence.exceptions.OptimisticLockException
    // is on this list.
    // Use addAllowedException and removeAllowedException to add/remove
    // an exception to allowedExceptions list.
    public boolean addAllowedException(String exceptionClassName) {
        try {
            allowedExceptions.put(exceptionClassName, Class.forName(exceptionClassName));
            return true;
        } catch (ClassNotFoundException classNotFoundException) {
            return false;
        }
    }

    public void removeAllowedException(String exceptionClassName) {
        allowedExceptions.remove(exceptionClassName);
    }

    /**
     * Set the tests in this test case.  Refactored for easier subclassing.
     */
    public void setTests(Vector test) {
        if ((test != null) && !test.isEmpty()) {
            numberOfTests = test.size();

            this.test = new TestCase[numberOfTests];
            test.toArray(this.test);

            testExecutorWithClientSession = new TestExecutorWithClientSession[numberOfTests];
            testExecutorListener = new TestEventListenerImpl[numberOfTests];
            testThread = new SynchronizedTestExecutor[numberOfTests];
            testThreadListener = new SynchronizedTesterImpl[numberOfTests];
        }
    }

    @Override
    protected void setup() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        setupSession();

        for (int i = 0; i < numberOfTests; i++) {
            // Need this for proper idention of while printing test results
            test[i].setContainer(this);

            // To run a test we need an executor.
            // To run simultaneously several tests we need a personal
            // executor for each of them.
            // For each test an instance of a subclass of TestExecutor is created:
            // TestExecutorWithClientSession:
            //   carries clientSession;
            //   readdresses some method calls to its parent - TestExecutor, disallows other ones;
            testExecutorWithClientSession[i] = new TestExecutorWithClientSession(getExecutor());

            // That's an optional TestExecutorListener.
            // Currently not used.
            testExecutorListener[i] = new TestEventListenerImpl();
            testExecutorWithClientSession[i].setListener(testExecutorListener[i]);

            // That's a ThreadListener - it receives call backs from
            // the thread - currently used is testFinished notification.
            testThreadListener[i] = new SynchronizedTesterImpl();

            test[i].setExecutor(testExecutorWithClientSession[i]);

            // That's a personal thread for the test
            testThread[i] = new SynchronizedTestExecutor(testExecutorWithClientSession[i], test[i], testThreadListener[i]);
            testThread[i].setName("Test Thread " + i);
        }
    }

    protected void setupSession() {
        originalSession = getSession();
        Session newSession = setupNewSession(originalSession, useSequenceConnectionPool);
        getExecutor().setSession(newSession);
    }

    // In order for MultithreadTestCase to run, it needs
    // a ServerSession to be returned by TestExecutor.getSession().
    // This method takes a session originally held by TestExecutor
    // (typically DatabaseSession) - and returns the ServerSession
    // which should be set as a Session into TestExecutor.
    // The possible variants:
    //   case originalSession is a ServerSession - will use it as a new session;
    //   case originalSession is a ClientSession - will use its parent as a new session.
    //
    // This is a static method so that it could be used by other classes.
    //
    // Use resetOriginalSession before setting the originalSession
    // back into TestExecutor.
    static public Session setupNewSession(Session originalSession, boolean useSequenceConnectionPool) {
        // Note that because ServerSession.isDatabaseSession() returns true
        // it is important to call isServerSession() before
        // isDatabaseSession() is called
        if (originalSession.isServerSession()) {
            return originalSession;
        } else if (originalSession.isDatabaseSession()) {
            // The following piece mostly copied from ClientServerTestModel
            // The only thing added is initializePreallocatedSequences() -
            // don't want to re-use the sequence numbers allocated by originalSession.
            DatabaseSession databaseSession = (DatabaseSession)originalSession;
            DatabaseLogin login = (DatabaseLogin)databaseSession.getLogin().clone();
            databaseSession.getSequencingControl().initializePreallocated();
            Server serverSession = new ServerSession(login, 5, 5);
            serverSession.setSessionLog(databaseSession.getSessionLog());
            if (useSequenceConnectionPool) {
                serverSession.getSequencingControl().setShouldUseSeparateConnection(true);
            } else {
                serverSession.getSequencingControl().setShouldUseSeparateConnection(false);
            }
            serverSession.login();

            Vector descriptors = new Vector();
            for (Iterator iterator = databaseSession.getDescriptors().values().iterator();
                     iterator.hasNext();) {
                descriptors.addElement(iterator.next());
            }
            serverSession.addDescriptors(descriptors);

            return serverSession;
        } else if (originalSession.isClientSession()) {
            ClientSession clientSession = (ClientSession)originalSession;
            ServerSession serverSession = clientSession.getParent();
            return serverSession;
        } else {
            // Should never happen
            return null;
        }
    }

    // Note that currently there is nothing done
    // to resolve possible deadlocks.
    @Override
    protected void test() {
        //run test threads
        for (int i = 0; i < numberOfTests; i++) {
            testThread[i].start();
        }

        //waiting for test threads to complete
        int numberOfCompletedTests;
        do {
            numberOfCompletedTests = 0;
            for (int i = 0; i < numberOfTests; i++) {
                if (testThreadListener[i].isFinished()) {
                    numberOfCompletedTests++;
                }
            }
        } while (numberOfCompletedTests < numberOfTests);
    }

    @Override
    protected void verify() {
        EclipseLinkException exception = null;
        for (int i = 0; (i < numberOfTests) && (exception == null); i++) {
            exception = test[i].getTestResult().getException();
            if (exception != null) {
                for (Enumeration enumtr = allowedExceptions.elements();
                         enumtr.hasMoreElements() && (exception != null);) {
                    if (((Class)(enumtr.nextElement())).isInstance(exception)) {
                        exception = null;
                    }
                }
                if (exception != null) {
                    setTestException(exception);
                }
            }
        }
    }

    // the originalSession != null check is needed
    // in case reset is called more than once -
    // which may happen in case of test failure due to
    // the resent changes in AutoVerifyTestCase.
    @Override
    public void reset() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        if (originalSession != null) {
            resetSession();
        }
    }

    protected void resetSession() {
        resetOriginalSession(originalSession, getSession());
        getExecutor().setSession(originalSession);
        originalSession = null;
    }

    static public void resetOriginalSession(Session originalSession, Session newSession) {
        // Note that because ServerSession.isDatabaseSession() returns true
        // it is important to call isServerSession() before
        // isDatabaseSession() is called
        if (originalSession.isServerSession()) {
            // Assuming that originalSession == newSession
            // (see setNewSession(..))
            return;
        } else if (originalSession.isDatabaseSession()) {
            ((DatabaseSession)newSession).logout();

            DatabaseSession databaseSession = (DatabaseSession)originalSession;

            // Is this necessary? Don't know.
            // Just copied it from ClientServerTestModel
            databaseSession.logout();
            databaseSession.login();
        }
    }

    @Override
    public void logResult(Writer log) {
        super.logResult(log);

        for (int i = 0; i < numberOfTests; i++) {
            try {
                log.write(org.eclipse.persistence.internal.helper.Helper.cr() + Helper.getTabs(getNestedCounter() + 1) + "Test Thread " + i);
            } catch (IOException exception) {
            }
            test[i].logResult(log);
        }
    }

    public void useSequenceConnectionPool() {
        useSequenceConnectionPool = true;
    }
}
