/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.dbcp2;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import java.util.Random;
import java.util.Stack;

import org.junit.After;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

// XXX FIX ME XXX
// this class still needs some cleanup, but at least
// this consolidates most of the relevant test code
// in a fairly re-usable fashion
// XXX FIX ME XXX

/**
 * Base test suite for DBCP pools.
 */
public abstract class TestConnectionPool {

    @After
    public void tearDown() throws Exception {
        // Close any connections opened by the test
        while (!connections.isEmpty()) {
            Connection conn = connections.pop();
            try {
                conn.close();
            } catch (final Exception ex) {
                // ignore
            } finally {
                conn = null;
            }
        }
    }

    protected abstract Connection getConnection() throws Exception;

    protected int getMaxTotal() {
        return 10;
    }

    protected long getMaxWaitMillis() {
        return 100L;
    }

    /** Connections opened during the course of a test */
    protected Stack<Connection> connections = new Stack<>();

    /** Acquire a connection and push it onto the connections stack */
    protected Connection newConnection() throws Exception {
        final Connection connection = getConnection();
        connections.push(connection);
        return connection;
    }

    // ----------- Utility Methods ---------------------------------

    protected String getUsername(final Connection conn) throws SQLException {
        final Statement stmt = conn.createStatement();
        final ResultSet rs = stmt.executeQuery("select username");
        if (rs.next()) {
            return rs.getString(1);
        }
        return null;
    }

    // ----------- tests ---------------------------------

    @Test
    public void testClearWarnings() throws Exception {
        final Connection[] c = new Connection[getMaxTotal()];
        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
            assertTrue(c[i] != null);

            // generate SQLWarning on connection
            try (CallableStatement cs = c[i].prepareCall("warning")){
            }
        }

        for (final Connection element : c) {
            assertNotNull(element.getWarnings());
        }

        for (final Connection element : c) {
            element.close();
        }

        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
        }

        for (final Connection element : c) {
            // warnings should have been cleared by putting the connection back in the pool
            assertNull(element.getWarnings());
        }

        for (final Connection element : c) {
            element.close();
        }
    }

    @Test
    public void testIsClosed() throws Exception {
        for(int i=0;i<getMaxTotal();i++) {
            final Connection conn = newConnection();
            assertNotNull(conn);
            assertTrue(!conn.isClosed());
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
            conn.close();
            assertTrue(conn.isClosed());
        }
    }

    /**
     * Verify the close method can be called multiple times on a single connection without
     * an exception being thrown.
     */
    @Test
    public void testCanCloseConnectionTwice() throws Exception {
        for (int i = 0; i < getMaxTotal(); i++) { // loop to show we *can* close again once we've borrowed it from the pool again
            final Connection conn = newConnection();
            assertNotNull(conn);
            assertTrue(!conn.isClosed());
            conn.close();
            assertTrue(conn.isClosed());
            conn.close();
            assertTrue(conn.isClosed());
        }
    }

    @Test
    public void testCanCloseStatementTwice() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        assertTrue(!conn.isClosed());
        for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
            final Statement stmt = conn.createStatement();
            assertNotNull(stmt);
            assertFalse(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
        }
        conn.close();
    }

    @Test
    public void testCanClosePreparedStatementTwice() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        assertTrue(!conn.isClosed());
        for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            assertFalse(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
        }
        conn.close();
    }

    @Test
    public void testCanCloseCallableStatementTwice() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        assertTrue(!conn.isClosed());
        for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
            final PreparedStatement stmt = conn.prepareCall("select * from dual");
            assertNotNull(stmt);
            assertFalse(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
            stmt.close();
            assertTrue(isClosed(stmt));
        }
        conn.close();
    }

    @Test
    public void testCanCloseResultSetTwice() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        assertTrue(!conn.isClosed());
        for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertFalse(isClosed(rset));
            rset.close();
            assertTrue(isClosed(rset));
            rset.close();
            assertTrue(isClosed(rset));
            rset.close();
            assertTrue(isClosed(rset));
        }
        conn.close();
    }

    @Test
    public void testBackPointers() throws Exception {
        // normal statement
        Connection conn = newConnection();
        assertBackPointers(conn, conn.createStatement());
        conn = newConnection();
        assertBackPointers(conn, conn.createStatement(0, 0));
        conn = newConnection();
        assertBackPointers(conn, conn.createStatement(0, 0, 0));

        // prepared statement
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual"));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual", 0));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0, 0));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual", new int[0]));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareStatement("select * from dual", new String[0]));

        // callable statement
        conn = newConnection();
        assertBackPointers(conn, conn.prepareCall("select * from dual"));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0));
        conn = newConnection();
        assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0, 0));
    }

    protected void assertBackPointers(final Connection conn, final Statement statement) throws SQLException {
        assertFalse(conn.isClosed());
        assertFalse(isClosed(statement));

        assertSame("statement.getConnection() should return the exact same connection instance that was used to create the statement",
                conn, statement.getConnection());

        final ResultSet resultSet = statement.getResultSet();
        assertFalse(isClosed(resultSet));
        assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
                statement, resultSet.getStatement());

        final ResultSet executeResultSet = statement.executeQuery("select * from dual");
        assertFalse(isClosed(executeResultSet));
        assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
                statement, executeResultSet.getStatement());

        final ResultSet keysResultSet = statement.getGeneratedKeys();
        assertFalse(isClosed(keysResultSet));
        assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
                statement, keysResultSet.getStatement());

        ResultSet preparedResultSet = null;
        if (statement instanceof PreparedStatement) {
            final PreparedStatement preparedStatement = (PreparedStatement) statement;
            preparedResultSet = preparedStatement.executeQuery();
            assertFalse(isClosed(preparedResultSet));
            assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
                    statement, preparedResultSet.getStatement());
        }


        resultSet.getStatement().getConnection().close();
        assertTrue(conn.isClosed());
        assertTrue(isClosed(statement));
        assertTrue(isClosed(resultSet));
        assertTrue(isClosed(executeResultSet));
        assertTrue(isClosed(keysResultSet));
        if (preparedResultSet != null) {
            assertTrue(isClosed(preparedResultSet));
        }
    }

    @Test
    public void testSimple() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        final PreparedStatement stmt = conn.prepareStatement("select * from dual");
        assertNotNull(stmt);
        final ResultSet rset = stmt.executeQuery();
        assertNotNull(rset);
        assertTrue(rset.next());
        rset.close();
        stmt.close();
        conn.close();
    }

    @Test
    public void testRepeatedBorrowAndReturn() throws Exception {
        for(int i=0;i<100;i++) {
            final Connection conn = newConnection();
            assertNotNull(conn);
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
            conn.close();
        }
    }

    @Test
    public void testSimple2() throws Exception {
        Connection conn = newConnection();
        assertNotNull(conn);
        {
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
        }
        {
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
        }
        conn.close();
        try (Statement s = conn.createStatement()){
            fail("Can't use closed connections");
        } catch(final SQLException e) {
            // expected
        }

        conn = newConnection();
        assertNotNull(conn);
        {
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
        }
        {
            final PreparedStatement stmt = conn.prepareStatement("select * from dual");
            assertNotNull(stmt);
            final ResultSet rset = stmt.executeQuery();
            assertNotNull(rset);
            assertTrue(rset.next());
            rset.close();
            stmt.close();
        }
        conn.close();
        conn = null;
    }

    @Test
    public void testPooling() throws Exception {
        // Grab a maximal set of open connections from the pool
        final Connection[] c = new Connection[getMaxTotal()];
        final Connection[] u = new Connection[getMaxTotal()];
        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
            if (c[i] instanceof DelegatingConnection) {
                u[i] = ((DelegatingConnection<?>) c[i]).getInnermostDelegate();
            } else {
                for (int j = 0; j <= i; j++) {
                    c[j].close();
                }
                return; // skip this test
            }
        }
        // Close connections one at a time and get new ones, making sure
        // the new ones come from the pool
        for (final Connection element : c) {
            element.close();
            final Connection con = newConnection();
            final Connection underCon =
                ((DelegatingConnection<?>) con).getInnermostDelegate();
            assertTrue("Failed to get connection", underCon != null);
            boolean found = false;
            for (int j = 0; j < c.length; j++) {
                if (underCon == u[j]) {
                    found = true;
                    break;
                }
            }
            assertTrue("New connection not from pool", found);
            con.close();
        }
    }

    @Test
    public void testAutoCommitBehavior() throws Exception {
        final Connection conn0 = newConnection();
        assertNotNull("connection should not be null", conn0);
        assertTrue("autocommit should be true for conn0", conn0.getAutoCommit());

        final Connection conn1 = newConnection();
        assertTrue("autocommit should be true for conn1", conn1.getAutoCommit() );
        conn1.close();

        assertTrue("autocommit should be true for conn0", conn0.getAutoCommit());
        conn0.setAutoCommit(false);
        assertFalse("autocommit should be false for conn0", conn0.getAutoCommit());
        conn0.close();

        final Connection conn2 = newConnection();
        assertTrue("autocommit should be true for conn2", conn2.getAutoCommit() );

        final Connection conn3 = newConnection();
        assertTrue("autocommit should be true for conn3", conn3.getAutoCommit() );

        conn2.close();

        conn3.close();
    }

    /** "http://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */
    @Test
    public void testConnectionsAreDistinct() throws Exception {
        final Connection[] conn = new Connection[getMaxTotal()];
        for(int i=0;i<conn.length;i++) {
            conn[i] = newConnection();
            for(int j=0;j<i;j++) {
                assertTrue(conn[j] != conn[i]);
                assertTrue(!conn[j].equals(conn[i]));
            }
        }
        for (final Connection element : conn) {
            element.close();
        }
    }

    @Test
    public void testOpening() throws Exception {
        final Connection[] c = new Connection[getMaxTotal()];
        // test that opening new connections is not closing previous
        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
            assertTrue(c[i] != null);
            for (int j = 0; j <= i; j++) {
                assertTrue(!c[j].isClosed());
            }
        }

        for (final Connection element : c) {
            element.close();
        }
    }

    @Test
    public void testClosing() throws Exception {
        final Connection[] c = new Connection[getMaxTotal()];
        // open the maximum connections
        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
        }

        // close one of the connections
        c[0].close();
        assertTrue(c[0].isClosed());

        // get a new connection
        c[0] = newConnection();

        for (final Connection element : c) {
            element.close();
        }
    }

    @Test
    public void testMaxTotal() throws Exception {
        final Connection[] c = new Connection[getMaxTotal()];
        for (int i = 0; i < c.length; i++) {
            c[i] = newConnection();
            assertTrue(c[i] != null);
        }

        try {
            newConnection();
            fail("Allowed to open more than DefaultMaxTotal connections.");
        } catch (final java.sql.SQLException e) {
            // should only be able to open 10 connections, so this test should
            // throw an exception
        }

        for (final Connection element : c) {
            element.close();
        }
    }

    /**
     * DBCP-128: BasicDataSource.getConnection()
     * Connections don't work as hashtable keys
     */
    @Test
    public void testHashing() throws Exception {
        final Connection con = getConnection();
        final Hashtable<Connection, String> hash = new Hashtable<>();
        hash.put(con, "test");
        assertEquals("test", hash.get(con));
        assertTrue(hash.containsKey(con));
        assertTrue(hash.contains("test"));
        hash.clear();
        con.close();
    }

    @Test
    public void testThreaded() {
        final TestThread[] threads = new TestThread[getMaxTotal()];
        for(int i=0;i<threads.length;i++) {
            threads[i] = new TestThread(50,50);
            final Thread t = new Thread(threads[i]);
            t.start();
        }
        for(int i=0;i<threads.length;i++) {
            while(!(threads[i]).complete()) {
                try {
                    Thread.sleep(100L);
                } catch(final Exception e) {
                    // ignored
                }
            }
            if(threads[i] != null && threads[i].failed()) {
                fail("Thread failed: " + i);
            }
        }
    }

    class TestThread implements Runnable {
        java.util.Random _random = new java.util.Random();
        boolean _complete = false;
        boolean _failed = false;
        int _iter = 100;
        int _delay = 50;

        public TestThread() {
        }

        public TestThread(final int iter) {
            _iter = iter;
        }

        public TestThread(final int iter, final int delay) {
            _iter = iter;
            _delay = delay;
        }

        public boolean complete() {
            return _complete;
        }

        public boolean failed() {
            return _failed;
        }

        @Override
        public void run() {
            for(int i=0;i<_iter;i++) {
                try {
                    Thread.sleep(_random.nextInt(_delay));
                } catch(final Exception e) {
                    // ignored
                }
                try (Connection conn = newConnection();
                        PreparedStatement stmt = conn.prepareStatement(
                                "select 'literal', SYSDATE from dual");
                        ResultSet rset = stmt.executeQuery();) {
                    try {
                        Thread.sleep(_random.nextInt(_delay));
                    } catch(final Exception e) {
                        // ignored
                    }
                } catch(final Exception e) {
                    e.printStackTrace();
                    _failed = true;
                    _complete = true;
                    break;
                }
            }
            _complete = true;
        }
    }

    // Bugzilla Bug 24328: PooledConnectionImpl ignores resultsetType
    // and Concurrency if statement pooling is not enabled
    // http://issues.apache.org/bugzilla/show_bug.cgi?id=24328
    @Test
    public void testPrepareStatementOptions() throws Exception
    {
        final Connection conn = newConnection();
        assertNotNull(conn);
        final PreparedStatement stmt = conn.prepareStatement("select * from dual",
            ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        assertNotNull(stmt);
        final ResultSet rset = stmt.executeQuery();
        assertNotNull(rset);
        assertTrue(rset.next());

        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, rset.getType());
        assertEquals(ResultSet.CONCUR_UPDATABLE, rset.getConcurrency());

        rset.close();
        stmt.close();
        conn.close();
    }

    // Bugzilla Bug 24966: NullPointer with Oracle 9 driver
    // wrong order of passivate/close when a rset isn't closed
    @Test
    public void testNoRsetClose() throws Exception {
        final Connection conn = newConnection();
        assertNotNull(conn);
        final PreparedStatement stmt = conn.prepareStatement("test");
        assertNotNull(stmt);
        final ResultSet rset = stmt.getResultSet();
        assertNotNull(rset);
        // forget to close the resultset: rset.close();
        stmt.close();
        conn.close();
    }

    // Bugzilla Bug 26966: Connectionpool's connections always returns same
    @Test
    public void testHashCode() throws Exception {
        final Connection conn1 = newConnection();
        assertNotNull(conn1);
        final Connection conn2 = newConnection();
        assertNotNull(conn2);

        assertTrue(conn1.hashCode() != conn2.hashCode());
    }

    protected boolean isClosed(final Statement statement) {
        try {
            statement.getWarnings();
            return false;
        } catch (final SQLException e) {
            // getWarnings throws an exception if the statement is
            // closed, but could throw an exception for other reasons
            // in this case it is good enough to assume the statement
            // is closed
            return true;
        }
    }

    protected boolean isClosed(final ResultSet resultSet) {
        try {
            resultSet.getWarnings();
            return false;
        } catch (final SQLException e) {
            // getWarnings throws an exception if the statement is
            // closed, but could throw an exception for other reasons
            // in this case it is good enough to assume the result set
            // is closed
            return true;
        }
    }

    private static final boolean DISPLAY_THREAD_DETAILS=
        Boolean.valueOf(System.getProperty("TestConnectionPool.display.thread.details", "false")).booleanValue();
    // To pass this to a Maven test, use:
    // mvn test -DargLine="-DTestConnectionPool.display.thread.details=true"
    // @see http://jira.codehaus.org/browse/SUREFIRE-121

    /**
     * Launches a group of 2 * getMaxTotal() threads, each of which will attempt to obtain a connection
     * from the pool, hold it for {@code holdTime} ms, and then return it to the pool.  If {@code loopOnce} is false,
     * threads will continue this process indefinitely.  If {@code expectError} is true, exactly 1/2 of the
     * threads are expected to either throw exceptions or fail to complete. If {@code expectError} is false,
     * all threads are expected to complete successfully.
     *
     * @param holdTime time in ms that a thread holds a connection before returning it to the pool
     * @param expectError whether or not an error is expected
     * @param loopOnce whether threads should complete the borrow - hold - return cycle only once, or loop indefinitely
     * @param maxWaitMillis passed in by client - has no impact on the test itself, but does get reported
     *
     * @throws Exception
     */
    protected void multipleThreads(final int holdTime,
        final boolean expectError, final boolean loopOnce,
        final long maxWaitMillis) throws Exception {
        multipleThreads(holdTime, expectError, loopOnce, maxWaitMillis, 1, 2 * getMaxTotal(), 300);
    }

    /**
     * Launches a group of {@code numThreads} threads, each of which will attempt to obtain a connection
     * from the pool, hold it for {@code holdTime} ms, and then return it to the pool.  If {@code loopOnce} is false,
     * threads will continue this process indefinitely.  If {@code expectError} is true, exactly 1/2 of the
     * threads are expected to either throw exceptions or fail to complete. If {@code expectError} is false,
     * all threads are expected to complete successfully.  Threads are stopped after {@code duration} ms.
     *
     * @param holdTime time in ms that a thread holds a connection before returning it to the pool
     * @param expectError whether or not an error is expected
     * @param loopOnce whether threads should complete the borrow - hold - return cycle only once, or loop indefinitely
     * @param maxWaitMillis passed in by client - has no impact on the test itself, but does get reported
     * @param numThreads the number of threads
     * @param duration duration in ms of test
     *
     * @throws Exception
     */
    protected void multipleThreads(final int holdTime,
            final boolean expectError, final boolean loopOnce,
            final long maxWaitMillis, final int numStatements, final int numThreads, final long duration) throws Exception {
                final long startTime = timeStamp();
                final PoolTest[] pts = new PoolTest[numThreads];
                // Catch Exception so we can stop all threads if one fails
                final ThreadGroup threadGroup = new ThreadGroup("foo") {
                    @Override
                    public void uncaughtException(final Thread t, final Throwable e) {
                        for (final PoolTest pt : pts) {
                            pt.stop();
                        }
                    }
                };
                // Create all the threads
                for (int i = 0; i < pts.length; i++) {
                    pts[i] = new PoolTest(threadGroup, holdTime, expectError, loopOnce, numStatements);
                }
                // Start all the threads
                for (final PoolTest pt : pts) {
                    pt.start();
                }

                // Give all threads a chance to start and succeed
                Thread.sleep(duration);

                // Stop threads
                for (final PoolTest pt : pts) {
                    pt.stop();
                }

                /*
                 * Wait for all threads to terminate.
                 * This is essential to ensure that all threads have a chance to update success[0]
                 * and to ensure that the variable is published correctly.
                 */
                int done=0;
                int failed=0;
                int didNotRun = 0;
                int loops=0;
                for (final PoolTest poolTest : pts) {
                    poolTest.thread.join();
                    loops += poolTest.loops;
                    final String state = poolTest.state;
                    if (DONE.equals(state)){
                        done++;
                    }
                    if (poolTest.loops == 0){
                        didNotRun++;
                    }
                    final Throwable thrown = poolTest.thrown;
                    if (thrown != null) {
                        failed++;
                        if (!expectError || !(thrown instanceof SQLException)){
                            System.out.println("Unexpected error: "+thrown.getMessage());
                        }
                    }
                }

                final long time = timeStamp() - startTime;
                System.out.println("Multithread test time = " + time
                        + " ms. Threads: " + pts.length
                        + ". Loops: " + loops
                        + ". Hold time: " + holdTime
                        + ". maxWaitMillis: " + maxWaitMillis
                        + ". Done: " + done
                        + ". Did not run: " + didNotRun
                        + ". Failed: " + failed
                        + ". expectError: " + expectError
                        );
                if (expectError) {
                    if (DISPLAY_THREAD_DETAILS || (pts.length/2 != failed)){
                        final long offset = pts[0].created - 1000; // To reduce size of output numbers, but ensure they have 4 digits
                        System.out.println("Offset: "+offset);
                        for (int i = 0; i < pts.length; i++) {
                            final PoolTest pt = pts[i];
                            System.out.println(
                                    "Pre: " + (pt.preconnected-offset) // First, so can sort on this easily
                                    + ". Post: " + (pt.postconnected != 0 ? Long.toString(pt.postconnected-offset): "-")
                                    + ". Hash: " + pt.connHash
                                    + ". Startup: " + (pt.started-pt.created)
                                    + ". getConn(): " + (pt.connected != 0 ? Long.toString(pt.connected-pt.preconnected) : "-")
                                    + ". Runtime: " + (pt.ended-pt.started)
                                    + ". IDX: " + i
                                    + ". Loops: " + pt.loops
                                    + ". State: " + pt.state
                                    + ". thrown: "+ pt.thrown
                                    + "."
                                    );
                        }
                    }
                    if (didNotRun > 0){
                        System.out.println("NOTE: some threads did not run the code: "+didNotRun);
                    }
                    // Perform initial sanity check:
                    assertTrue("Expected some of the threads to fail",failed > 0);
                    // Assume that threads that did not run would have timed out.
                    assertEquals("WARNING: Expected half the threads to fail",pts.length/2,failed+didNotRun);
                } else {
                    assertEquals("Did not expect any threads to fail",0,failed);
                }
            }
    private static int currentThreadCount = 0;

    private static final String DONE = "Done";

    protected class PoolTest implements Runnable {
        /**
         * The number of milliseconds to hold onto a database connection
         */
        private final int connHoldTime;

        private final int numStatements;

        private volatile boolean isRun;

        private String state; // No need to be volatile if it is read after the thread finishes

        private final Thread thread;

        private Throwable thrown;

        private final Random random = new Random();

        // Debug for DBCP-318
        private final long created; // When object was created
        private long started; // when thread started
        private long ended; // when thread ended
        private long preconnected; // just before connect
        private long connected; // when thread last connected
        private long postconnected; // when thread released connection
        private int loops = 0;
        private int connHash = 0; // Connection identity hashCode (to see which one is reused)

        private final boolean stopOnException; // If true, don't rethrow Exception

        private final boolean loopOnce; // If true, don't repeat loop

        public PoolTest(final ThreadGroup threadGroup, final int connHoldTime, final boolean isStopOnException) {
            this(threadGroup, connHoldTime, isStopOnException, false, 1);
        }

        public PoolTest(final ThreadGroup threadGroup, final int connHoldTime, final boolean isStopOnException, final int numStatements) {
            this(threadGroup, connHoldTime, isStopOnException, false, numStatements);
        }

        private PoolTest(final ThreadGroup threadGroup, final int connHoldTime, final boolean isStopOnException, final boolean once, final int numStatements) {
            this.loopOnce = once;
            this.connHoldTime = connHoldTime;
            stopOnException = isStopOnException;
            isRun = true; // Must be done here so main thread is guaranteed to be able to set it false
            thrown = null;
            thread =
                new Thread(threadGroup, this, "Thread+" + currentThreadCount++);
            thread.setDaemon(false);
            created = timeStamp();
            this.numStatements = numStatements;
        }

        public void start(){
            thread.start();
        }

        @Override
        public void run() {
            started = timeStamp();
            try {
                while (isRun) {
                    loops++;
                    state = "Getting Connection";
                    preconnected = timeStamp();
                    final Connection conn = getConnection();
                    connHash = System.identityHashCode(((DelegatingConnection<?>)conn).getInnermostDelegate());
                    connected = timeStamp();
                    state = "Using Connection";
                    assertNotNull(conn);
                    final String sql = numStatements == 1 ? "select * from dual" : "select count " + random.nextInt(numStatements - 1);
                    final PreparedStatement stmt =
                        conn.prepareStatement(sql);
                    assertNotNull(stmt);
                    final ResultSet rset = stmt.executeQuery();
                    assertNotNull(rset);
                    assertTrue(rset.next());
                    state = "Holding Connection";
                    Thread.sleep(connHoldTime);
                    state = "Closing ResultSet";
                    rset.close();
                    state = "Closing Statement";
                    stmt.close();
                    state = "Closing Connection";
                    conn.close();
                    postconnected = timeStamp();
                    state = "Closed";
                    if (loopOnce){
                        break; // Or could set isRun=false
                    }
                }
                state = DONE;
            } catch (final Throwable t) {
                thrown = t;
                if (!stopOnException) {
                    throw new RuntimeException();
                }
            } finally {
                ended = timeStamp();
            }
        }

        public void stop() {
            isRun = false;
        }

        public Thread getThread() {
            return thread;
        }
    }

    long timeStamp() {
        return System.currentTimeMillis();// JVM 1.5+ System.nanoTime() / 1000000;
    }
}
