/*
 * 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.pool2.impl;

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.assertTrue;
import static org.junit.Assert.fail;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PoolUtils;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.SwallowedExceptionListener;
import org.apache.commons.pool2.TestBaseObjectPool;
import org.apache.commons.pool2.VisitTracker;
import org.apache.commons.pool2.VisitTrackerFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @version $Revision$
 */
public class TestGenericObjectPool extends TestBaseObjectPool {

    @Override
    protected ObjectPool<String> makeEmptyPool(int mincap) {
       GenericObjectPool<String> mtPool =
               new GenericObjectPool<String>(new SimpleFactory());
       mtPool.setMaxTotal(mincap);
       mtPool.setMaxIdle(mincap);
       return mtPool;
    }

    @Override
    protected ObjectPool<Object> makeEmptyPool(
            final PooledObjectFactory<Object> fac) {
        return new GenericObjectPool<Object>(fac);
    }

    @Override
    protected Object getNthObject(int n) {
        return String.valueOf(n);
    }

    @Before
    public void setUp() throws Exception {
        factory = new SimpleFactory();
        pool = new GenericObjectPool<String>(factory);
    }

    @After
    public void tearDown() throws Exception {
        String poolName = pool.getJmxName().toString();
        pool.clear();
        pool.close();
        pool = null;
        factory = null;

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> result = mbs.queryNames(new ObjectName(
                "org.apache.commoms.pool2:type=GenericObjectPool,*"), null);
        // There should be no registered pools at this point
        int registeredPoolCount = result.size();
        StringBuilder msg = new StringBuilder("Current pool is: ");
        msg.append(poolName);
        msg.append("  Still open pools are: ");
        for (ObjectName name : result) {
            // Clean these up ready for the next test
            msg.append(name.toString());
            msg.append(" created via\n");
            msg.append(mbs.getAttribute(name, "CreationStackTrace"));
            msg.append('\n');
            mbs.unregisterMBean(name);
        }
        Assert.assertEquals(msg.toString(), 0, registeredPoolCount);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testConstructorNullFactory() {
        // add dummy assert (won't be invoked because of IAE) to avoid "unused" warning
        assertNotNull(new GenericObjectPool<String>(null));
        // TODO this currently causes tearDown to report an error
        // Looks like GOP needs to call close() or jmxUnregister() before throwing IAE
    }

    @Test(timeout=60000)
    public void testConstructors() throws Exception {

        // Make constructor arguments all different from defaults
        int minIdle = 2;
        long maxWait = 3;
        int maxIdle = 4;
        int maxTotal = 5;
        long minEvictableIdleTimeMillis = 6;
        int numTestsPerEvictionRun = 7;
        boolean testOnBorrow = true;
        boolean testOnReturn = true;
        boolean testWhileIdle = true;
        long timeBetweenEvictionRunsMillis = 8;
        boolean blockWhenExhausted = false;
        boolean lifo = false;
        PooledObjectFactory<Object> dummyFactory = new DummyFactory();
        GenericObjectPool<Object> dummyPool =
                new GenericObjectPool<Object>(dummyFactory);
        assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_IDLE, dummyPool.getMaxIdle());
        assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, dummyPool.getMaxWaitMillis());
        assertEquals(GenericObjectPoolConfig.DEFAULT_MIN_IDLE, dummyPool.getMinIdle());
        assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL, dummyPool.getMaxTotal());
        assertEquals(GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                dummyPool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                dummyPool.getNumTestsPerEvictionRun());
        assertEquals(Boolean.valueOf(GenericObjectPoolConfig.DEFAULT_TEST_ON_BORROW),
                Boolean.valueOf(dummyPool.getTestOnBorrow()));
        assertEquals(Boolean.valueOf(GenericObjectPoolConfig.DEFAULT_TEST_ON_RETURN),
                Boolean.valueOf(dummyPool.getTestOnReturn()));
        assertEquals(Boolean.valueOf(GenericObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE),
                Boolean.valueOf(dummyPool.getTestWhileIdle()));
        assertEquals(GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                dummyPool.getTimeBetweenEvictionRunsMillis());
        assertEquals(Boolean.valueOf(GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED),
                Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
        assertEquals(Boolean.valueOf(GenericObjectPoolConfig.DEFAULT_LIFO),
                Boolean.valueOf(dummyPool.getLifo()));
        dummyPool.close();

        GenericObjectPoolConfig config =
                new GenericObjectPoolConfig();
        config.setLifo(lifo);
        config.setMaxIdle(maxIdle);
        config.setMinIdle(minIdle);
        config.setMaxTotal(maxTotal);
        config.setMaxWaitMillis(maxWait);
        config.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        config.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setTestWhileIdle(testWhileIdle);
        config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        config.setBlockWhenExhausted(blockWhenExhausted);
        dummyPool = new GenericObjectPool<Object>(dummyFactory, config);
        assertEquals(maxIdle, dummyPool.getMaxIdle());
        assertEquals(maxWait, dummyPool.getMaxWaitMillis());
        assertEquals(minIdle, dummyPool.getMinIdle());
        assertEquals(maxTotal, dummyPool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                dummyPool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun, dummyPool.getNumTestsPerEvictionRun());
        assertEquals(Boolean.valueOf(testOnBorrow),
                Boolean.valueOf(dummyPool.getTestOnBorrow()));
        assertEquals(Boolean.valueOf(testOnReturn),
                Boolean.valueOf(dummyPool.getTestOnReturn()));
        assertEquals(Boolean.valueOf(testWhileIdle),
                Boolean.valueOf(dummyPool.getTestWhileIdle()));
        assertEquals(timeBetweenEvictionRunsMillis,
                dummyPool.getTimeBetweenEvictionRunsMillis());
        assertEquals(Boolean.valueOf(blockWhenExhausted),
                Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
        assertEquals(Boolean.valueOf(lifo), Boolean.valueOf(dummyPool.getLifo()));
        dummyPool.close();
    }

    @Test(timeout=60000)
    public void testWhenExhaustedFail() throws Exception {
        pool.setMaxTotal(1);
        pool.setBlockWhenExhausted(false);
        String obj1 = pool.borrowObject();
        assertNotNull(obj1);
        try {
            pool.borrowObject();
            fail("Expected NoSuchElementException");
        } catch(NoSuchElementException e) {
            // expected
        }
        pool.returnObject(obj1);
        assertEquals(1, pool.getNumIdle());
        pool.close();
    }

    @Test(timeout=60000)
    public void testWhenExhaustedBlock() throws Exception {
        pool.setMaxTotal(1);
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(10L);
        String obj1 = pool.borrowObject();
        assertNotNull(obj1);
        try {
            pool.borrowObject();
            fail("Expected NoSuchElementException");
        } catch(NoSuchElementException e) {
            // expected
        }
        pool.returnObject(obj1);
        pool.close();
    }

    @Test(timeout=60000)
    public void testWhenExhaustedBlockInterupt() throws Exception {
        pool.setMaxTotal(1);
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(-1);
        String obj1 = pool.borrowObject();

        // Make sure on object was obtained
        assertNotNull(obj1);

        // Create a separate thread to try and borrow another object
        WaitingTestThread wtt = new WaitingTestThread(pool, 200000);
        wtt.start();
        // Give wtt time to start
        Thread.sleep(200);
        wtt.interrupt();

        // Give interupt time to take effect
        Thread.sleep(200);

        // Check thread was interrupted
        assertTrue(wtt._thrown instanceof InterruptedException);

        // Return object to the pool
        pool.returnObject(obj1);

        // Bug POOL-162 - check there is now an object in the pool
        pool.setMaxWaitMillis(10L);
        String obj2 = null;
        try {
             obj2 = pool.borrowObject();
            assertNotNull(obj2);
        } catch(NoSuchElementException e) {
            // Not expected
            fail("NoSuchElementException not expected");
        }
        pool.returnObject(obj2);
        pool.close();

    }

    @Test(timeout=60000)
    public void testEvictWhileEmpty() throws Exception {
        pool.evict();
        pool.evict();
        pool.close();
    }

    /**
     * Tests addObject contention between ensureMinIdle triggered by
     * the Evictor with minIdle &gt; 0 and borrowObject.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testEvictAddObjects() throws Exception {
        factory.setMakeLatency(300);
        factory.setMaxTotal(2);
        pool.setMaxTotal(2);
        pool.setMinIdle(1);
        pool.borrowObject(); // numActive = 1, numIdle = 0
        // Create a test thread that will run once and try a borrow after
        // 150ms fixed delay
        TestThread<String> borrower = new TestThread<String>(pool, 1, 150, false);
        Thread borrowerThread = new Thread(borrower);
        // Set evictor to run in 100 ms - will create idle instance
        pool.setTimeBetweenEvictionRunsMillis(100);
        borrowerThread.start();  // Off to the races
        borrowerThread.join();
        assertTrue(!borrower.failed());
    }

    @Test(timeout=60000)
    public void testEvictLIFO() throws Exception {
        checkEvict(true);
    }

    @Test(timeout=60000)
    public void testEvictFIFO() throws Exception {
        checkEvict(false);
    }

    private void checkEvict(boolean lifo) throws Exception {
        // yea this is hairy but it tests all the code paths in GOP.evict()
        pool.setSoftMinEvictableIdleTimeMillis(10);
        pool.setMinIdle(2);
        pool.setTestWhileIdle(true);
        pool.setLifo(lifo);
        PoolUtils.prefill(pool, 5);
        pool.evict();
        factory.setEvenValid(false);
        factory.setOddValid(false);
        factory.setThrowExceptionOnActivate(true);
        pool.evict();
        PoolUtils.prefill(pool, 5);
        factory.setThrowExceptionOnActivate(false);
        factory.setThrowExceptionOnPassivate(true);
        pool.evict();
        factory.setThrowExceptionOnPassivate(false);
        factory.setEvenValid(true);
        factory.setOddValid(true);
        Thread.sleep(125);
        pool.evict();
        assertEquals(2, pool.getNumIdle());
    }

    /**
     * Test to make sure evictor visits least recently used objects first,
     * regardless of FIFO/LIFO.
     *
     * JIRA: POOL-86
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testEvictionOrder() throws Exception {
        checkEvictionOrder(false);
        tearDown();
        setUp();
        checkEvictionOrder(true);
    }

    private void checkEvictionOrder(boolean lifo) throws Exception {
        checkEvictionOrderPart1(lifo);
        tearDown();
        setUp();
        checkEvictionOrderPart2(lifo);
    }

    private void checkEvictionOrderPart1(boolean lifo) throws Exception {
        pool.setNumTestsPerEvictionRun(2);
        pool.setMinEvictableIdleTimeMillis(100);
        pool.setLifo(lifo);
        for (int i = 0; i < 5; i++) {
            pool.addObject();
            Thread.sleep(100);
        }
        // Order, oldest to youngest, is "0", "1", ...,"4"
        pool.evict(); // Should evict "0" and "1"
        Object obj = pool.borrowObject();
        assertTrue("oldest not evicted", !obj.equals("0"));
        assertTrue("second oldest not evicted", !obj.equals("1"));
        // 2 should be next out for FIFO, 4 for LIFO
        assertEquals("Wrong instance returned", lifo ? "4" : "2" , obj);
    }

    private void checkEvictionOrderPart2(boolean lifo) throws Exception {
        // Two eviction runs in sequence
        pool.setNumTestsPerEvictionRun(2);
        pool.setMinEvictableIdleTimeMillis(100);
        pool.setLifo(lifo);
        for (int i = 0; i < 5; i++) {
            pool.addObject();
            Thread.sleep(100);
        }
        pool.evict(); // Should evict "0" and "1"
        pool.evict(); // Should evict "2" and "3"
        Object obj = pool.borrowObject();
        assertEquals("Wrong instance remaining in pool", "4", obj);
    }

    /**
     * Verifies that the evictor visits objects in expected order
     * and frequency.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testEvictorVisiting() throws Exception {
        checkEvictorVisiting(true);
        checkEvictorVisiting(false);
    }

    private void checkEvictorVisiting(boolean lifo) throws Exception {
        VisitTrackerFactory<Object> trackerFactory = new VisitTrackerFactory<Object>();
        GenericObjectPool<VisitTracker<Object>> trackerPool =
                new GenericObjectPool<VisitTracker<Object>>(trackerFactory);
        trackerPool.setNumTestsPerEvictionRun(2);
        trackerPool.setMinEvictableIdleTimeMillis(-1);
        trackerPool.setTestWhileIdle(true);
        trackerPool.setLifo(lifo);
        trackerPool.setTestOnReturn(false);
        trackerPool.setTestOnBorrow(false);
        for (int i = 0; i < 8; i++) {
            trackerPool.addObject();
        }
        trackerPool.evict(); // Visit oldest 2 - 0 and 1
        VisitTracker<Object> obj = trackerPool.borrowObject();
        trackerPool.returnObject(obj);
        obj = trackerPool.borrowObject();
        trackerPool.returnObject(obj);
        //  borrow, return, borrow, return
        //  FIFO will move 0 and 1 to end
        //  LIFO, 7 out, then in, then out, then in
        trackerPool.evict();  // Should visit 2 and 3 in either case
        for (int i = 0; i < 8; i++) {
            VisitTracker<Object> tracker = trackerPool.borrowObject();
            if (tracker.getId() >= 4) {
                assertEquals("Unexpected instance visited " + tracker.getId(),
                        0, tracker.getValidateCount());
            } else {
                assertEquals("Instance " +  tracker.getId() +
                        " visited wrong number of times.",
                        1, tracker.getValidateCount());
            }
        }
        trackerPool.close();

        trackerFactory = new VisitTrackerFactory<Object>();
        trackerPool = new GenericObjectPool<VisitTracker<Object>>(trackerFactory);
        trackerPool.setNumTestsPerEvictionRun(3);
        trackerPool.setMinEvictableIdleTimeMillis(-1);
        trackerPool.setTestWhileIdle(true);
        trackerPool.setLifo(lifo);
        trackerPool.setTestOnReturn(false);
        trackerPool.setTestOnBorrow(false);
        for (int i = 0; i < 8; i++) {
            trackerPool.addObject();
        }
        trackerPool.evict(); // 0, 1, 2
        trackerPool.evict(); // 3, 4, 5
        obj = trackerPool.borrowObject();
        trackerPool.returnObject(obj);
        obj = trackerPool.borrowObject();
        trackerPool.returnObject(obj);
        obj = trackerPool.borrowObject();
        trackerPool.returnObject(obj);
        // borrow, return, borrow, return
        //  FIFO 3,4,5,6,7,0,1,2
        //  LIFO 7,6,5,4,3,2,1,0
        // In either case, pointer should be at 6
        trackerPool.evict();
        // Should hit 6,7,0 - 0 for second time
        for (int i = 0; i < 8; i++) {
            VisitTracker<Object> tracker = trackerPool.borrowObject();
            if (tracker.getId() != 0) {
                assertEquals("Instance " +  tracker.getId() +
                        " visited wrong number of times.",
                        1, tracker.getValidateCount());
            } else {
                assertEquals("Instance " +  tracker.getId() +
                        " visited wrong number of times.",
                        2, tracker.getValidateCount());
            }
        }
        trackerPool.close();

        // Randomly generate a pools with random numTests
        // and make sure evictor cycles through elements appropriately
        int[] smallPrimes = {2, 3, 5, 7};
        Random random = new Random();
        random.setSeed(System.currentTimeMillis());
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 5; j++) {
                trackerPool = new GenericObjectPool<VisitTracker<Object>>(trackerFactory);
                trackerPool.setNumTestsPerEvictionRun(smallPrimes[i]);
                trackerPool.setMinEvictableIdleTimeMillis(-1);
                trackerPool.setTestWhileIdle(true);
                trackerPool.setLifo(lifo);
                trackerPool.setTestOnReturn(false);
                trackerPool.setTestOnBorrow(false);
                trackerPool.setMaxIdle(-1);
                int instanceCount = 10 + random.nextInt(20);
                trackerPool.setMaxTotal(instanceCount);
                for (int k = 0; k < instanceCount; k++) {
                    trackerPool.addObject();
                }

                // Execute a random number of evictor runs
                int runs = 10 + random.nextInt(50);
                for (int k = 0; k < runs; k++) {
                    trackerPool.evict();
                }

                // Number of times evictor should have cycled through the pool
                int cycleCount = (runs * trackerPool.getNumTestsPerEvictionRun()) /
                        instanceCount;

                // Look at elements and make sure they are visited cycleCount
                // or cycleCount + 1 times
                VisitTracker<Object> tracker = null;
                int visitCount = 0;
                for (int k = 0; k < instanceCount; k++) {
                    tracker = trackerPool.borrowObject();
                    assertTrue(trackerPool.getNumActive() <= trackerPool.getMaxTotal());
                    visitCount = tracker.getValidateCount();
                    assertTrue(visitCount >= cycleCount &&
                            visitCount <= cycleCount + 1);
                }
                trackerPool.close();
            }
        }
    }

    @Test(timeout=60000)
    public void testExceptionOnPassivateDuringReturn() throws Exception {
        String obj = pool.borrowObject();
        factory.setThrowExceptionOnPassivate(true);
        pool.returnObject(obj);
        assertEquals(0,pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testExceptionOnDestroyDuringBorrow() throws Exception {
        factory.setThrowExceptionOnDestroy(true);
        pool.setTestOnBorrow(true);
        pool.borrowObject();
        factory.setValid(false); // Make validation fail on next borrow attempt
        try {
            pool.borrowObject();
            fail("Expecting NoSuchElementException");
        } catch (NoSuchElementException ex) {
            // expected
        }
        assertEquals(1, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testExceptionOnDestroyDuringReturn() throws Exception {
        factory.setThrowExceptionOnDestroy(true);
        pool.setTestOnReturn(true);
        String obj1 = pool.borrowObject();
        pool.borrowObject();
        factory.setValid(false); // Make validation fail
        pool.returnObject(obj1);
        assertEquals(1, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testExceptionOnActivateDuringBorrow() throws Exception {
        String obj1 = pool.borrowObject();
        String obj2 = pool.borrowObject();
        pool.returnObject(obj1);
        pool.returnObject(obj2);
        factory.setThrowExceptionOnActivate(true);
        factory.setEvenValid(false);
        // Activation will now throw every other time
        // First attempt throws, but loop continues and second succeeds
        String obj = pool.borrowObject();
        assertEquals(1, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());

        pool.returnObject(obj);
        factory.setValid(false);
        // Validation will now fail on activation when borrowObject returns
        // an idle instance, and then when attempting to create a new instance
        try {
            pool.borrowObject();
            fail("Expecting NoSuchElementException");
        } catch (NoSuchElementException ex) {
            // expected
        }
        assertEquals(0, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testNegativeMaxTotal() throws Exception {
        pool.setMaxTotal(-1);
        pool.setBlockWhenExhausted(false);
        String obj = pool.borrowObject();
        assertEquals(getNthObject(0),obj);
        pool.returnObject(obj);
    }

    @Test(timeout=60000)
    public void testMaxIdle() throws Exception {
        pool.setMaxTotal(100);
        pool.setMaxIdle(8);
        String[] active = new String[100];
        for(int i=0;i<100;i++) {
            active[i] = pool.borrowObject();
        }
        assertEquals(100,pool.getNumActive());
        assertEquals(0,pool.getNumIdle());
        for(int i=0;i<100;i++) {
            pool.returnObject(active[i]);
            assertEquals(99 - i,pool.getNumActive());
            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
        }
    }

    @Test(timeout=60000)
    public void testMaxIdleZero() throws Exception {
        pool.setMaxTotal(100);
        pool.setMaxIdle(0);
        String[] active = new String[100];
        for(int i=0;i<100;i++) {
            active[i] = pool.borrowObject();
        }
        assertEquals(100,pool.getNumActive());
        assertEquals(0,pool.getNumIdle());
        for(int i=0;i<100;i++) {
            pool.returnObject(active[i]);
            assertEquals(99 - i,pool.getNumActive());
            assertEquals(0, pool.getNumIdle());
        }
    }

    @Test(timeout=60000)
    public void testMaxTotal() throws Exception {
        pool.setMaxTotal(3);
        pool.setBlockWhenExhausted(false);

        pool.borrowObject();
        pool.borrowObject();
        pool.borrowObject();
        try {
            pool.borrowObject();
            fail("Expected NoSuchElementException");
        } catch(NoSuchElementException e) {
            // expected
        }
    }

    @Test(timeout=60000)
    public void testTimeoutNoLeak() throws Exception {
        pool.setMaxTotal(2);
        pool.setMaxWaitMillis(10);
        pool.setBlockWhenExhausted(true);
        String obj = pool.borrowObject();
        String obj2 = pool.borrowObject();
        try {
            pool.borrowObject();
            fail("Expecting NoSuchElementException");
        } catch (NoSuchElementException ex) {
            // expected
        }
        pool.returnObject(obj2);
        pool.returnObject(obj);

        pool.borrowObject();
        pool.borrowObject();
    }

    @Test(timeout=60000)
    public void testMaxTotalZero() throws Exception {
        pool.setMaxTotal(0);
        pool.setBlockWhenExhausted(false);

        try {
            pool.borrowObject();
            fail("Expected NoSuchElementException");
        } catch(NoSuchElementException e) {
            // expected
        }
    }

    @Test(timeout=60000)
    @SuppressWarnings("rawtypes")
    public void testMaxTotalUnderLoad() {
        // Config
        int numThreads = 199; // And main thread makes a round 200.
        int numIter = 20;
        int delay = 25;
        int maxTotal = 10;

        factory.setMaxTotal(maxTotal);
        pool.setMaxTotal(maxTotal);
        pool.setBlockWhenExhausted(true);
        pool.setTimeBetweenEvictionRunsMillis(-1);

        // Start threads to borrow objects
        TestThread[] threads = new TestThread[numThreads];
        for(int i=0;i<numThreads;i++) {
            // Factor of 2 on iterations so main thread does work whilst other
            // threads are running. Factor of 2 on delay so average delay for
            // other threads == actual delay for main thread
            threads[i] = new TestThread<String>(pool, numIter * 2, delay * 2);
            Thread t = new Thread(threads[i]);
            t.start();
        }
        // Give the threads a chance to start doing some work
        try {
            Thread.sleep(5000);
        } catch(InterruptedException e) {
            // ignored
        }

        for (int i = 0; i < numIter; i++) {
            String obj = null;
            try {
                try {
                    Thread.sleep(delay);
                } catch(InterruptedException e) {
                    // ignored
                }
                obj = pool.borrowObject();
                // Under load, observed _numActive > _maxTotal
                if (pool.getNumActive() > pool.getMaxTotal()) {
                    throw new IllegalStateException("Too many active objects");
                }
                try {
                    Thread.sleep(delay);
                } catch(InterruptedException e) {
                    // ignored
                }
            } catch (Exception e) {
                // Shouldn't happen
                e.printStackTrace();
                fail("Exception on borrow");
            } finally {
                if (obj != null) {
                    try {
                        pool.returnObject(obj);
                    } catch (Exception e) {
                        // Ignore
                    }
                }
            }
        }

        for(int i=0;i<numThreads;i++) {
            while(!(threads[i]).complete()) {
                try {
                    Thread.sleep(500L);
                } catch(InterruptedException e) {
                    // ignored
                }
            }
            if(threads[i].failed()) {
                fail("Thread "+i+" failed: "+threads[i]._error.toString());
            }
        }
    }

    /**
     * This is the test case for POOL-263. It is disabled since it will always
     * pass without artificial delay being injected into GOP.returnObject() and
     * a way to this this hasn't currently been found that doesn't involve
     * polluting the GOP implementation. The artificial delay needs to be
     * inserted just before the final call to isLifo() in the returnObject()
     * method.
     */
    //@Test(timeout=60000)
    public void testReturnObject() throws Exception {

        pool.setMaxTotal(1);
        pool.setMaxIdle(-1);
        String active = pool.borrowObject();

        assertEquals(1, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());

        Thread t = new Thread() {

            @Override
            public void run() {
                pool.close();
            }

        };
        t.start();

        pool.returnObject(active);

        // Wait for the close() thread to complete
        while (t.isAlive()) {
            Thread.sleep(50);
        }

        assertEquals(0, pool.getNumIdle());
    }


    @Test(timeout=60000)
    public void testSettersAndGetters() throws Exception {
        {
            // The object receives an Exception during its creation to prevent
            // memory leaks. See BaseGenericObjectPool constructor for more details.
            assertTrue(false == "".equals(pool.getCreationStackTrace()));
        }
        {
            assertEquals(0, pool.getBorrowedCount());
        }
        {
            assertEquals(0, pool.getReturnedCount());
        }
        {
            assertEquals(0, pool.getCreatedCount());
        }
        {
            assertEquals(0, pool.getDestroyedCount());
        }
        {
            assertEquals(0, pool.getDestroyedByEvictorCount());
        }
        {
            assertEquals(0, pool.getDestroyedByBorrowValidationCount());
        }
        {
            assertEquals(0, pool.getMeanActiveTimeMillis());
        }
        {
            assertEquals(0, pool.getMeanIdleTimeMillis());
        }
        {
            assertEquals(0, pool.getMeanBorrowWaitTimeMillis());
        }
        {
            assertEquals(0, pool.getMaxBorrowWaitTimeMillis());
        }
        {
            assertEquals(0, pool.getNumIdle());
        }
        {
            pool.setMaxTotal(123);
            assertEquals(123,pool.getMaxTotal());
        }
        {
            pool.setMaxIdle(12);
            assertEquals(12,pool.getMaxIdle());
        }
        {
            pool.setMaxWaitMillis(1234L);
            assertEquals(1234L,pool.getMaxWaitMillis());
        }
        {
            pool.setMinEvictableIdleTimeMillis(12345L);
            assertEquals(12345L,pool.getMinEvictableIdleTimeMillis());
        }
        {
            pool.setNumTestsPerEvictionRun(11);
            assertEquals(11,pool.getNumTestsPerEvictionRun());
        }
        {
            pool.setTestOnBorrow(true);
            assertTrue(pool.getTestOnBorrow());
            pool.setTestOnBorrow(false);
            assertTrue(!pool.getTestOnBorrow());
        }
        {
            pool.setTestOnReturn(true);
            assertTrue(pool.getTestOnReturn());
            pool.setTestOnReturn(false);
            assertTrue(!pool.getTestOnReturn());
        }
        {
            pool.setTestWhileIdle(true);
            assertTrue(pool.getTestWhileIdle());
            pool.setTestWhileIdle(false);
            assertTrue(!pool.getTestWhileIdle());
        }
        {
            pool.setTimeBetweenEvictionRunsMillis(11235L);
            assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis());
        }
        {
            pool.setSoftMinEvictableIdleTimeMillis(12135L);
            assertEquals(12135L,pool.getSoftMinEvictableIdleTimeMillis());
        }
        {
            pool.setBlockWhenExhausted(true);
            assertTrue(pool.getBlockWhenExhausted());
            pool.setBlockWhenExhausted(false);
            assertFalse(pool.getBlockWhenExhausted());
        }
    }

    @Test(timeout=60000)
    public void testDefaultConfiguration() throws Exception {
        assertConfiguration(new GenericObjectPoolConfig(),pool);
    }

    @Test(timeout=60000)
    public void testSetConfig() throws Exception {
        GenericObjectPoolConfig expected = new GenericObjectPoolConfig();
        assertConfiguration(expected,pool);
        expected.setMaxTotal(2);
        expected.setMaxIdle(3);
        expected.setMaxWaitMillis(5L);
        expected.setMinEvictableIdleTimeMillis(7L);
        expected.setNumTestsPerEvictionRun(9);
        expected.setTestOnCreate(true);
        expected.setTestOnBorrow(true);
        expected.setTestOnReturn(true);
        expected.setTestWhileIdle(true);
        expected.setTimeBetweenEvictionRunsMillis(11L);
        expected.setBlockWhenExhausted(false);
        pool.setConfig(expected);
        assertConfiguration(expected,pool);
    }

    @Test(timeout=60000)
    public void testStartAndStopEvictor() throws Exception {
        // set up pool without evictor
        pool.setMaxIdle(6);
        pool.setMaxTotal(6);
        pool.setNumTestsPerEvictionRun(6);
        pool.setMinEvictableIdleTimeMillis(100L);

        for(int j=0;j<2;j++) {
            // populate the pool
            {
                String[] active = new String[6];
                for(int i=0;i<6;i++) {
                    active[i] = pool.borrowObject();
                }
                for(int i=0;i<6;i++) {
                    pool.returnObject(active[i]);
                }
            }

            // note that it stays populated
            assertEquals("Should have 6 idle",6,pool.getNumIdle());

            // start the evictor
            pool.setTimeBetweenEvictionRunsMillis(50L);

            // wait a second (well, .2 seconds)
            try { Thread.sleep(200L); } catch(InterruptedException e) { }

            // assert that the evictor has cleared out the pool
            assertEquals("Should have 0 idle",0,pool.getNumIdle());

            // stop the evictor
            pool.startEvictor(0L);
        }
    }

    @Test(timeout=60000)
    public void testEvictionWithNegativeNumTests() throws Exception {
        // when numTestsPerEvictionRun is negative, it represents a fraction of the idle objects to test
        pool.setMaxIdle(6);
        pool.setMaxTotal(6);
        pool.setNumTestsPerEvictionRun(-2);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);

        String[] active = new String[6];
        for(int i=0;i<6;i++) {
            active[i] = pool.borrowObject();
        }
        for(int i=0;i<6;i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(100L); } catch(InterruptedException e) { }
        assertTrue("Should at most 6 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 6);
        try { Thread.sleep(100L); } catch(InterruptedException e) { }
        assertTrue("Should at most 3 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 3);
        try { Thread.sleep(100L); } catch(InterruptedException e) { }
        assertTrue("Should be at most 2 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 2);
        try { Thread.sleep(100L); } catch(InterruptedException e) { }
        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testEviction() throws Exception {
        pool.setMaxIdle(500);
        pool.setMaxTotal(500);
        pool.setNumTestsPerEvictionRun(100);
        pool.setMinEvictableIdleTimeMillis(250L);
        pool.setTimeBetweenEvictionRunsMillis(500L);
        pool.setTestWhileIdle(true);

        String[] active = new String[500];
        for(int i=0;i<500;i++) {
            active[i] = pool.borrowObject();
        }
        for(int i=0;i<500;i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(1000L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());

        for(int i=0;i<500;i++) {
            active[i] = pool.borrowObject();
        }
        for(int i=0;i<500;i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(1000L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
    }

    public static class TestEvictionPolicy<T> implements EvictionPolicy<T> {

        private final AtomicInteger callCount = new AtomicInteger(0);

        @Override
        public boolean evict(EvictionConfig config, PooledObject<T> underTest,
                int idleCount) {
            if (callCount.incrementAndGet() > 1500) {
                return true;
            } else {
                return false;
            }
        }
    }

    @Test(timeout=60000)
    public void testEvictionPolicy() throws Exception {
        pool.setMaxIdle(500);
        pool.setMaxTotal(500);
        pool.setNumTestsPerEvictionRun(500);
        pool.setMinEvictableIdleTimeMillis(250L);
        pool.setTimeBetweenEvictionRunsMillis(500L);
        pool.setTestWhileIdle(true);

        // ClassNotFoundException
        try {
            pool.setEvictionPolicyClassName(Long.toString(System.currentTimeMillis()));
            fail("setEvictionPolicyClassName must throw an error if the class name is invalid.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        // InstantiationException
        try {
            pool.setEvictionPolicyClassName(java.io.Serializable.class.getName());
            fail("setEvictionPolicyClassName must throw an error if the class name is invalid.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        // IllegalAccessException
        try {
            pool.setEvictionPolicyClassName(java.util.Collections.class.getName());
            fail("setEvictionPolicyClassName must throw an error if the class name is invalid.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        pool.setEvictionPolicyClassName(TestEvictionPolicy.class.getName());
        assertEquals(TestEvictionPolicy.class.getName(), pool.getEvictionPolicyClassName());

        String[] active = new String[500];
        for(int i=0;i<500;i++) {
            active[i] = pool.borrowObject();
        }
        for(int i=0;i<500;i++) {
            pool.returnObject(active[i]);
        }

        // Eviction policy ignores first 1500 attempts to evict and then always
        // evicts. After 1s, there should have been two runs of 500 tests so no
        // evictions
        try { Thread.sleep(1000L); } catch(InterruptedException e) { }
        assertEquals("Should be 500 idle", 500, pool.getNumIdle());
        // A further 1s wasn't enough so allow 2s for the evictor to clear out
        // all of the idle objects.
        try { Thread.sleep(2000L); } catch(InterruptedException e) { }
        assertEquals("Should be 0 idle", 0, pool.getNumIdle());
    }


    @Test(timeout=60000)
    public void testEvictionSoftMinIdle() throws Exception {
        class TimeTest extends BasePooledObjectFactory<TimeTest> {
            private final long createTime;
            public TimeTest() {
                createTime = System.currentTimeMillis();
            }
            @Override
            public TimeTest create() throws Exception {
                return new TimeTest();
            }
            @Override
            public PooledObject<TimeTest> wrap(TimeTest value) {
                return new DefaultPooledObject<TimeTest>(value);
            }
            public long getCreateTime() {
                return createTime;
            }
        }

        GenericObjectPool<TimeTest> timePool =
            new GenericObjectPool<TimeTest>(new TimeTest());

        timePool.setMaxIdle(5);
        timePool.setMaxTotal(5);
        timePool.setNumTestsPerEvictionRun(5);
        timePool.setMinEvictableIdleTimeMillis(3000L);
        timePool.setSoftMinEvictableIdleTimeMillis(1000L);
        timePool.setMinIdle(2);

        TimeTest[] active = new TimeTest[5];
        Long[] creationTime = new Long[5] ;
        for(int i=0;i<5;i++) {
            active[i] = timePool.borrowObject();
            creationTime[i] = Long.valueOf((active[i]).getCreateTime());
        }

        for(int i=0;i<5;i++) {
            timePool.returnObject(active[i]);
        }

        // Soft evict all but minIdle(2)
        Thread.sleep(1500L);
        timePool.evict();
        assertEquals("Idle count different than expected.", 2, timePool.getNumIdle());

        // Hard evict the rest.
        Thread.sleep(2000L);
        timePool.evict();
        assertEquals("Idle count different than expected.", 0, timePool.getNumIdle());
        timePool.close();
    }

    @Test(timeout=60000)
    public void testEvictionInvalid() throws Exception {

        final GenericObjectPool<Object> invalidFactoryPool =
                new GenericObjectPool<Object>(new InvalidFactory());

        invalidFactoryPool.setMaxIdle(1);
        invalidFactoryPool.setMaxTotal(1);
        invalidFactoryPool.setTestOnBorrow(false);
        invalidFactoryPool.setTestOnReturn(false);
        invalidFactoryPool.setTestWhileIdle(true);
        invalidFactoryPool.setMinEvictableIdleTimeMillis(100000);
        invalidFactoryPool.setNumTestsPerEvictionRun(1);

        Object p = invalidFactoryPool.borrowObject();
        invalidFactoryPool.returnObject(p);

        // Run eviction in a separate thread
        Thread t = new EvictionThread<Object>(invalidFactoryPool);
        t.start();

        // Sleep to make sure evictor has started
        Thread.sleep(300);

        try {
            invalidFactoryPool.borrowObject(1);
        } catch (NoSuchElementException nsee) {
            // Ignore
        }

        // Make sure evictor has finished
        Thread.sleep(1000);

        // Should have an empty pool
        assertEquals("Idle count different than expected.", 0, invalidFactoryPool.getNumIdle());
        assertEquals("Total count different than expected.", 0, invalidFactoryPool.getNumActive());
        invalidFactoryPool.close();
    }

    /**
     * POOL-231 - verify that concurrent invalidates of the same object do not
     * corrupt pool destroyCount.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testConcurrentInvalidate() throws Exception {
        // Get allObjects and idleObjects loaded with some instances
        final int nObjects = 1000;
        pool.setMaxTotal(nObjects);
        pool.setMaxIdle(nObjects);
        final String[] obj = new String[nObjects];
        for (int i = 0; i < nObjects; i++) {
            obj[i] = pool.borrowObject();
        }
        for (int i = 0; i < nObjects; i++) {
            if (i % 2 == 0) {
                pool.returnObject(obj[i]);
            }
        }
        final int nThreads = 20;
        final int nIterations = 60;
        final InvalidateThread[] threads = new InvalidateThread[nThreads];
        // Randomly generated list of distinct invalidation targets
        final ArrayList<Integer> targets = new ArrayList<Integer>();
        final Random random = new Random();
        for (int j = 0; j < nIterations; j++) {
            // Get a random invalidation target
            Integer targ = Integer.valueOf(random.nextInt(nObjects));
            while (targets.contains(targ)) {
                targ = Integer.valueOf(random.nextInt(nObjects));
            }
            targets.add(targ);
            // Launch nThreads threads all trying to invalidate the target
            for (int i = 0; i < nThreads; i++) {
                threads[i] = new InvalidateThread(pool, obj[targ.intValue()]);
            }
            for (int i = 0; i < nThreads; i++) {
                new Thread(threads[i]).start();
            }
            boolean done = false;
            while (!done) {
                done = true;
                for (int i = 0; i < nThreads; i++) {
                    done = done && threads[i].complete();
                }
                Thread.sleep(100);
            }
        }
        Assert.assertEquals(nIterations, pool.getDestroyedCount());
    }

    /**
     * Attempts to invalidate an object, swallowing IllegalStateException.
     */
    static class InvalidateThread implements Runnable {
        private final String obj;
        private final ObjectPool<String> pool;
        private boolean done = false;
        public InvalidateThread(ObjectPool<String> pool, String obj) {
            this.obj = obj;
            this.pool = pool;
        }
        @Override
        public void run() {
            try {
                pool.invalidateObject(obj);
            } catch (IllegalStateException ex) {
                // Ignore
            } catch (Exception ex) {
                Assert.fail("Unexpected exception " + ex.toString());
            } finally {
                done = true;
            }
        }
        public boolean complete() {
            return done;
        }
    }

    @Test(timeout=60000)
    public void testMinIdle() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxTotal(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        String[] active = new String[5];
        active[0] = pool.borrowObject();

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        for(int i=1 ; i<5 ; i++) {
            active[i] = pool.borrowObject();
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        for(int i=0 ; i<5 ; i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
    }

    @Test(timeout=60000)
    public void testMinIdleMaxTotal() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxTotal(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        String[] active = new String[10];

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        for(int i=0 ; i<5 ; i++) {
            active[i] = pool.borrowObject();
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);

        for(int i=0 ; i<5 ; i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);

        for(int i=0 ; i<10 ; i++) {
            active[i] = pool.borrowObject();
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);

        for(int i=0 ; i<10 ; i++) {
            pool.returnObject(active[i]);
        }

        try { Thread.sleep(150L); } catch(InterruptedException e) { }
        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
    }

    /**
     * Kicks off <numThreads> test threads, each of which will go through
     * <iterations> borrow-return cycles with random delay times <= delay
     * in between.
     */
    @SuppressWarnings({
        "rawtypes", "unchecked"
    })
    private void runTestThreads(int numThreads, int iterations, int delay, GenericObjectPool testPool) {
        TestThread[] threads = new TestThread[numThreads];
        for(int i=0;i<numThreads;i++) {
            threads[i] = new TestThread<String>(testPool,iterations,delay);
            Thread t = new Thread(threads[i]);
            t.start();
        }
        for(int i=0;i<numThreads;i++) {
            while(!(threads[i]).complete()) {
                try {
                    Thread.sleep(500L);
                } catch(InterruptedException e) {
                    // ignored
                }
            }
            if(threads[i].failed()) {
                fail("Thread "+i+" failed: "+threads[i]._error.toString());
            }
        }
    }

    @Test(timeout=60000)
    public void testThreaded1() throws Exception {
        pool.setMaxTotal(15);
        pool.setMaxIdle(15);
        pool.setMaxWaitMillis(1000L);
        runTestThreads(20, 100, 50, pool);
    }

    /**
     * Verifies that maxTotal is not exceeded when factory destroyObject
     * has high latency, testOnReturn is set and there is high incidence of
     * validation failures.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testMaxTotalInvariant() throws Exception {
        int maxTotal = 15;
        factory.setEvenValid(false);     // Every other validation fails
        factory.setDestroyLatency(100);  // Destroy takes 100 ms
        factory.setMaxTotal(maxTotal); // (makes - destroys) bound
        factory.setValidationEnabled(true);
        pool.setMaxTotal(maxTotal);
        pool.setMaxIdle(-1);
        pool.setTestOnReturn(true);
        pool.setMaxWaitMillis(1000L);
        runTestThreads(5, 10, 50, pool);
    }

    @Test(timeout=60000)
    public void testConcurrentBorrowAndEvict() throws Exception {

        pool.setMaxTotal(1);
        pool.addObject();

        for( int i=0; i<5000; i++) {
            ConcurrentBorrowAndEvictThread one =
                    new ConcurrentBorrowAndEvictThread(true);
            ConcurrentBorrowAndEvictThread two =
                    new ConcurrentBorrowAndEvictThread(false);

            one.start();
            two.start();
            one.join();
            two.join();

            pool.returnObject(one.obj);

            /* Uncomment this for a progress indication
            if (i % 10 == 0) {
                System.out.println(i/10);
            }
            */
        }
    }

    /**
     * Verifies that concurrent threads never "share" instances
     */
    @Test
    public void testNoInstanceOverlap() {
        final int maxTotal = 5;
        final int numThreads = 100;
        final int delay = 1;
        final int iterations = 1000;
        AtomicIntegerFactory factory = new AtomicIntegerFactory();
        GenericObjectPool<AtomicInteger> pool = new GenericObjectPool<AtomicInteger>(factory);
        pool.setMaxTotal(maxTotal);
        pool.setMaxIdle(maxTotal);
        pool.setTestOnBorrow(true);
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(-1);
        runTestThreads(numThreads, iterations, delay, pool);
        Assert.assertEquals(0, pool.getDestroyedByBorrowValidationCount());
    }

    /**
     * POOL-189
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testWhenExhaustedBlockClosePool() throws Exception {
        pool.setMaxTotal(1);
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(-1);
        Object obj1 = pool.borrowObject();

        // Make sure an object was obtained
        assertNotNull(obj1);

        // Create a separate thread to try and borrow another object
        WaitingTestThread wtt = new WaitingTestThread(pool, 200);
        wtt.start();
        // Give wtt time to start
        Thread.sleep(200);

        // close the pool (Bug POOL-189)
        pool.close();

        // Give interrupt time to take effect
        Thread.sleep(200);

        // Check thread was interrupted
        assertTrue(wtt._thrown instanceof InterruptedException);
    }

    private class ConcurrentBorrowAndEvictThread extends Thread {
        private final boolean borrow;
        public String obj;

        public ConcurrentBorrowAndEvictThread(boolean borrow) {
            this.borrow = borrow;
        }

        @Override
        public void run() {
            try {
                if (borrow) {
                    obj = pool.borrowObject();
                } else {
                    pool.evict();
                }
            } catch (Exception e) { /* Ignore */}
        }
    }

    static class TestThread<T> implements Runnable {

        /** source of random delay times */
        private final java.util.Random _random;

        /** pool to borrow from */
        private final ObjectPool<T> _pool;

        /** number of borrow attempts */
        private final int _iter;

        /** delay before each borrow attempt */
        private final int _startDelay;

        /** time to hold each borrowed object before returning it */
        private final int _holdTime;

        /** whether or not start and hold time are randomly generated */
        private final boolean _randomDelay;

        /** object expected to be borrowed (fail otherwise) */
        private final Object _expectedObject;

        private volatile boolean _complete = false;
        private volatile boolean _failed = false;
        private volatile Throwable _error;

        public TestThread(ObjectPool<T> pool) {
            this(pool, 100, 50, true, null);
        }

        public TestThread(ObjectPool<T> pool, int iter) {
            this(pool, iter, 50, true, null);
        }

        public TestThread(ObjectPool<T> pool, int iter, int delay) {
            this(pool, iter, delay, true, null);
        }

        public TestThread(ObjectPool<T> pool, int iter, int delay,
                boolean randomDelay) {
            this(pool, iter, delay, randomDelay, null);
        }

        public TestThread(ObjectPool<T> pool, int iter, int delay,
                boolean randomDelay, Object obj) {
            this(pool, iter, delay, delay, randomDelay, obj);
        }

        public TestThread(ObjectPool<T> pool, int iter, int startDelay,
            int holdTime, boolean randomDelay, Object obj) {
        _pool = pool;
        _iter = iter;
        _startDelay = startDelay;
        _holdTime = holdTime;
        _randomDelay = randomDelay;
        _random = _randomDelay ? new Random() : null;
        _expectedObject = obj;
    }

        public boolean complete() {
            return _complete;
        }

        public boolean failed() {
            return _failed;
        }

        @Override
        public void run() {
            for(int i=0;i<_iter;i++) {
                long startDelay =
                    _randomDelay ? (long)_random.nextInt(_startDelay) : _startDelay;
                long holdTime =
                    _randomDelay ? (long)_random.nextInt(_holdTime) : _holdTime;
                try {
                    Thread.sleep(startDelay);
                } catch(InterruptedException e) {
                    // ignored
                }
                T obj = null;
                try {
                    obj = _pool.borrowObject();
                } catch(Exception e) {
                    _error = e;
                    _failed = true;
                    _complete = true;
                    break;
                }

                if (_expectedObject != null && !_expectedObject.equals(obj)) {
                    _error = new Throwable("Expected: "+_expectedObject+ " found: "+obj);
                    _failed = true;
                    _complete = true;
                    break;
                }

                try {
                    Thread.sleep(holdTime);
                } catch(InterruptedException e) {
                    // ignored
                }
                try {
                    _pool.returnObject(obj);
                } catch(Exception e) {
                    _error = e;
                    _failed = true;
                    _complete = true;
                    break;
                }
            }
            _complete = true;
        }
    }

    @Test(timeout=60000)
    public void testFIFO() throws Exception {
        String o = null;
        pool.setLifo(false);
        pool.addObject(); // "0"
        pool.addObject(); // "1"
        pool.addObject(); // "2"
        assertEquals("Oldest", "0", pool.borrowObject());
        assertEquals("Middle", "1", pool.borrowObject());
        assertEquals("Youngest", "2", pool.borrowObject());
        o = pool.borrowObject();
        assertEquals("new-3", "3", o);
        pool.returnObject(o);
        assertEquals("returned-3", o, pool.borrowObject());
        assertEquals("new-4", "4", pool.borrowObject());
    }

    @Test(timeout=60000)
    public void testLIFO() throws Exception {
        String o = null;
        pool.setLifo(true);
        pool.addObject(); // "0"
        pool.addObject(); // "1"
        pool.addObject(); // "2"
        assertEquals("Youngest", "2", pool.borrowObject());
        assertEquals("Middle", "1", pool.borrowObject());
        assertEquals("Oldest", "0", pool.borrowObject());
        o = pool.borrowObject();
        assertEquals("new-3", "3", o);
        pool.returnObject(o);
        assertEquals("returned-3", o, pool.borrowObject());
        assertEquals("new-4", "4", pool.borrowObject());
    }

    @Test(timeout=60000)
    public void testAddObject() throws Exception {
        assertEquals("should be zero idle", 0, pool.getNumIdle());
        pool.addObject();
        assertEquals("should be one idle", 1, pool.getNumIdle());
        assertEquals("should be zero active", 0, pool.getNumActive());
        String obj = pool.borrowObject();
        assertEquals("should be zero idle", 0, pool.getNumIdle());
        assertEquals("should be one active", 1, pool.getNumActive());
        pool.returnObject(obj);
        assertEquals("should be one idle", 1, pool.getNumIdle());
        assertEquals("should be zero active", 0, pool.getNumActive());
    }

    protected GenericObjectPool<String> pool = null;

    private SimpleFactory factory = null;

    private void assertConfiguration(GenericObjectPoolConfig expected, GenericObjectPool<?> actual) throws Exception {
        assertEquals("testOnCreate",Boolean.valueOf(expected.getTestOnCreate()),
                Boolean.valueOf(actual.getTestOnCreate()));
        assertEquals("testOnBorrow",Boolean.valueOf(expected.getTestOnBorrow()),
                Boolean.valueOf(actual.getTestOnBorrow()));
        assertEquals("testOnReturn",Boolean.valueOf(expected.getTestOnReturn()),
                Boolean.valueOf(actual.getTestOnReturn()));
        assertEquals("testWhileIdle",Boolean.valueOf(expected.getTestWhileIdle()),
                Boolean.valueOf(actual.getTestWhileIdle()));
        assertEquals("whenExhaustedAction",
                Boolean.valueOf(expected.getBlockWhenExhausted()),
                Boolean.valueOf(actual.getBlockWhenExhausted()));
        assertEquals("maxTotal",expected.getMaxTotal(),actual.getMaxTotal());
        assertEquals("maxIdle",expected.getMaxIdle(),actual.getMaxIdle());
        assertEquals("maxWait",expected.getMaxWaitMillis(),actual.getMaxWaitMillis());
        assertEquals("minEvictableIdleTimeMillis",expected.getMinEvictableIdleTimeMillis(),actual.getMinEvictableIdleTimeMillis());
        assertEquals("numTestsPerEvictionRun",expected.getNumTestsPerEvictionRun(),actual.getNumTestsPerEvictionRun());
        assertEquals("timeBetweenEvictionRunsMillis",expected.getTimeBetweenEvictionRunsMillis(),actual.getTimeBetweenEvictionRunsMillis());
    }

    public static class SimpleFactory implements PooledObjectFactory<String> {
        public SimpleFactory() {
            this(true);
        }
        public SimpleFactory(boolean valid) {
            this(valid,valid);
        }
        public SimpleFactory(boolean evalid, boolean ovalid) {
            evenValid = evalid;
            oddValid = ovalid;
        }
        public synchronized void setValid(boolean valid) {
            setEvenValid(valid);
            setOddValid(valid);
        }
        public synchronized void setEvenValid(boolean valid) {
            evenValid = valid;
        }
        public synchronized void setOddValid(boolean valid) {
            oddValid = valid;
        }
        public synchronized void setThrowExceptionOnPassivate(boolean bool) {
            exceptionOnPassivate = bool;
        }
        public synchronized void setMaxTotal(int maxTotal) {
            this.maxTotal = maxTotal;
        }
        public synchronized void setDestroyLatency(long destroyLatency) {
            this.destroyLatency = destroyLatency;
        }
        public synchronized void setMakeLatency(long makeLatency) {
            this.makeLatency = makeLatency;
        }
        public synchronized void setValidateLatency(long validateLatency) {
            this.validateLatency = validateLatency;
        }
        @Override
        public PooledObject<String> makeObject() {
            final long waitLatency;
            synchronized(this) {
                activeCount++;
                if (activeCount > maxTotal) {
                    throw new IllegalStateException(
                        "Too many active instances: " + activeCount);
                }
                waitLatency = makeLatency;
            }
            if (waitLatency > 0) {
                doWait(waitLatency);
            }
            final int counter;
            synchronized(this) {
                counter = makeCounter++;
            }
            return new DefaultPooledObject<String>(String.valueOf(counter));
        }
        @Override
        public void destroyObject(PooledObject<String> obj) throws Exception {
            final long waitLatency;
            final boolean hurl;
            synchronized(this) {
                waitLatency = destroyLatency;
                hurl = exceptionOnDestroy;
            }
            if (waitLatency > 0) {
                doWait(waitLatency);
            }
            synchronized(this) {
                activeCount--;
            }
            if (hurl) {
                throw new Exception();
            }
        }
        @Override
        public boolean validateObject(PooledObject<String> obj) {
            final boolean validate;
            final boolean evenTest;
            final boolean oddTest;
            final long waitLatency;
            final int counter;
            synchronized(this) {
                validate = enableValidation;
                evenTest = evenValid;
                oddTest = oddValid;
                counter = validateCounter++;
                waitLatency = validateLatency;
            }
            if (waitLatency > 0) {
                doWait(waitLatency);
            }
            if (validate) {
                return counter%2 == 0 ? evenTest : oddTest;
            }
            else {
                return true;
            }
        }
        @Override
        public void activateObject(PooledObject<String> obj) throws Exception {
            final boolean hurl;
            final boolean evenTest;
            final boolean oddTest;
            final int counter;
            synchronized(this) {
                hurl = exceptionOnActivate;
                evenTest = evenValid;
                oddTest = oddValid;
                counter = activationCounter++;
            }
            if (hurl) {
                if (!(counter%2 == 0 ? evenTest : oddTest)) {
                    throw new Exception();
                }
            }
        }
        @Override
        public void passivateObject(PooledObject<String> obj) throws Exception {
            final boolean hurl;
            synchronized(this) {
                hurl = exceptionOnPassivate;
            }
            if (hurl) {
                throw new Exception();
            }
        }
        int makeCounter = 0;
        int activationCounter = 0;
        int validateCounter = 0;
        int activeCount = 0;
        boolean evenValid = true;
        boolean oddValid = true;
        boolean exceptionOnPassivate = false;
        boolean exceptionOnActivate = false;
        boolean exceptionOnDestroy = false;
        boolean enableValidation = true;
        long destroyLatency = 0;
        long makeLatency = 0;
        long validateLatency = 0;
        int maxTotal = Integer.MAX_VALUE;

        public synchronized boolean isThrowExceptionOnActivate() {
            return exceptionOnActivate;
        }

        public synchronized void setThrowExceptionOnActivate(boolean b) {
            exceptionOnActivate = b;
        }

        public synchronized void setThrowExceptionOnDestroy(boolean b) {
            exceptionOnDestroy = b;
        }

        public synchronized boolean isValidationEnabled() {
            return enableValidation;
        }

        public synchronized void setValidationEnabled(boolean b) {
            enableValidation = b;
        }

        public synchronized int getMakeCounter() {
            return makeCounter;
        }

        private void doWait(long latency) {
            try {
                Thread.sleep(latency);
            } catch (InterruptedException ex) {
                // ignore
            }
        }
    }

    protected static class AtomicIntegerFactory
    extends BasePooledObjectFactory<AtomicInteger> {

    private long activateLatency = 0;
    private long passivateLatency = 0;
    private long createLatency = 0;
    private long destroyLatency = 0;
    private long validateLatency = 0;

    @Override
    public AtomicInteger create() {
        try {
            Thread.sleep(createLatency);
        } catch (InterruptedException ex) {}
        return new AtomicInteger(0);
    }

    @Override
    public PooledObject<AtomicInteger> wrap(AtomicInteger integer) {
        return new DefaultPooledObject<AtomicInteger>(integer);
    }

    @Override
    public void activateObject(PooledObject<AtomicInteger> p) {
        p.getObject().incrementAndGet();
        try {
            Thread.sleep(activateLatency);
        } catch (InterruptedException ex) {}
    }

    @Override
    public void passivateObject(PooledObject<AtomicInteger> p) {
        p.getObject().decrementAndGet();
        try {
            Thread.sleep(passivateLatency);
        } catch (InterruptedException ex) {}
    }

    @Override
    public boolean validateObject(PooledObject<AtomicInteger> instance) {
        try {
            Thread.sleep(validateLatency);
        } catch (InterruptedException ex) {}
        return instance.getObject().intValue() == 1;
    }

    @Override
    public void destroyObject(PooledObject<AtomicInteger> p) {
        try {
            Thread.sleep(destroyLatency);
        } catch (InterruptedException ex) {}
    }


    /**
     * @param activateLatency the activateLatency to set
     */
    public void setActivateLatency(long activateLatency) {
        this.activateLatency = activateLatency;
    }


    /**
     * @param passivateLatency the passivateLatency to set
     */
    public void setPassivateLatency(long passivateLatency) {
        this.passivateLatency = passivateLatency;
    }


    /**
     * @param createLatency the createLatency to set
     */
    public void setCreateLatency(long createLatency) {
        this.createLatency = createLatency;
    }


    /**
     * @param destroyLatency the destroyLatency to set
     */
    public void setDestroyLatency(long destroyLatency) {
        this.destroyLatency = destroyLatency;
    }


    /**
     * @param validateLatency the validateLatency to set
     */
    public void setValidateLatency(long validateLatency) {
        this.validateLatency = validateLatency;
    }
}

    @Override
    protected boolean isLifo() {
        return true;
    }

    @Override
    protected boolean isFifo() {
        return false;
    }

    /*
     * Note: This test relies on timing for correct execution. There *should* be
     * enough margin for this to work correctly on most (all?) systems but be
     * aware of this if you see a failure of this test.
     */
    @SuppressWarnings({
        "rawtypes", "unchecked"
    })
    @Test(timeout=60000)
    public void testBorrowObjectFairness() throws Exception {

        int numThreads = 40;
        int maxTotal = 40;

        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxTotal);
        config.setFairness(true);
        config.setLifo(false);

        pool = new GenericObjectPool(factory, config);

        // Exhaust the pool
        String[] objects = new String[maxTotal];
        for (int i = 0; i < maxTotal; i++) {
            objects[i] = pool.borrowObject();
        }

        // Start and park threads waiting to borrow objects
        TestThread[] threads = new TestThread[numThreads];
        for(int i=0;i<numThreads;i++) {
            threads[i] = new TestThread(pool, 1, 0, 2000, false, String.valueOf(i % maxTotal));
            Thread t = new Thread(threads[i]);
            t.start();
            // Short delay to ensure threads start in correct order
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                fail(e.toString());
            }
        }

        // Return objects, other threads should get served in order
        for (int i = 0; i < maxTotal; i++) {
            pool.returnObject(objects[i]);
        }

        // Wait for threads to finish
        for(int i=0;i<numThreads;i++) {
            while(!(threads[i]).complete()) {
                try {
                    Thread.sleep(500L);
                } catch(InterruptedException e) {
                    // ignored
                }
            }
            if(threads[i].failed()) {
                fail("Thread "+i+" failed: "+threads[i]._error.toString());
            }
        }
    }

    /**
     * On first borrow, first object fails validation, second object is OK.
     * Subsequent borrows are OK. This was POOL-152.
     */
    @Test(timeout=60000)
    public void testBrokenFactoryShouldNotBlockPool() {
        int maxTotal = 1;

        factory.setMaxTotal(maxTotal);
        pool.setMaxTotal(maxTotal);
        pool.setBlockWhenExhausted(true);
        pool.setTestOnBorrow(true);

        // First borrow object will need to create a new object which will fail
        // validation.
        String obj = null;
        Exception ex = null;
        factory.setValid(false);
        try {
            obj = pool.borrowObject();
        } catch (Exception e) {
            ex = e;
        }
        // Failure expected
        assertNotNull(ex);
        assertTrue(ex instanceof NoSuchElementException);
        assertNull(obj);

        // Configure factory to create valid objects so subsequent borrows work
        factory.setValid(true);

        // Subsequent borrows should be OK
        try {
            obj = pool.borrowObject();
        } catch (Exception e1) {
            fail();
        }
        assertNotNull(obj);
        try {
            pool.returnObject(obj);
        } catch (Exception e) {
            fail();
        }
    }

    /*
     * Very simple test thread that just tries to borrow an object from
     * the provided pool returns it after a wait
     */
    static class WaitingTestThread extends Thread {
        private final GenericObjectPool<String> _pool;
        private final long _pause;
        private Throwable _thrown;

        private long preborrow; // just before borrow
        private long postborrow; //  borrow returned
        private long postreturn; // after object was returned
        private long ended;
        private String objectId;

        public WaitingTestThread(GenericObjectPool<String> pool, long pause) {
            _pool = pool;
            _pause = pause;
            _thrown = null;
        }

        @Override
        public void run() {
            try {
                preborrow = System.currentTimeMillis();
                String obj = _pool.borrowObject();
                objectId = obj;
                postborrow = System.currentTimeMillis();
                Thread.sleep(_pause);
                _pool.returnObject(obj);
                postreturn = System.currentTimeMillis();
            } catch (Exception e) {
                _thrown = e;
            } finally{
                ended = System.currentTimeMillis();
            }
        }
    }

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

    /*
     * Test multi-threaded pool access.
     * Multiple threads, but maxTotal only allows half the threads to succeed.
     *
     * This test was prompted by Continuum build failures in the Commons DBCP test case:
     * TestPerUserPoolDataSource.testMultipleThreads2()
     * Let's see if the this fails on Continuum too!
     */
    @Test(timeout=60000)
    public void testMaxWaitMultiThreaded() throws Exception {
        final long maxWait = 500; // wait for connection
        final long holdTime = 2 * maxWait; // how long to hold connection
        final int threads = 10; // number of threads to grab the object initially
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(maxWait);
        pool.setMaxTotal(threads);
        // Create enough threads so half the threads will have to wait
        WaitingTestThread wtt[] = new WaitingTestThread[threads * 2];
        for(int i=0; i < wtt.length; i++){
            wtt[i] = new WaitingTestThread(pool,holdTime);
        }
        long origin = System.currentTimeMillis()-1000;
        for (WaitingTestThread element : wtt) {
            element.start();
        }
        int failed = 0;
        for (WaitingTestThread element : wtt) {
            element.join();
            if (element._thrown != null){
                failed++;
            }
        }
        if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){
            System.out.println(
                    "MaxWait: " + maxWait +
                    " HoldTime: " + holdTime +
                     " MaxTotal: " + threads +
                    " Threads: " + wtt.length +
                    " Failed: " + failed
                    );
            for (WaitingTestThread wt : wtt) {
                System.out.println(
                        "Preborrow: " + (wt.preborrow-origin) +
                        " Postborrow: " + (wt.postborrow != 0 ? wt.postborrow-origin : -1) +
                        " BorrowTime: " + (wt.postborrow != 0 ? wt.postborrow-wt.preborrow : -1) +
                        " PostReturn: " + (wt.postreturn != 0 ? wt.postreturn-origin : -1) +
                        " Ended: " + (wt.ended-origin) +
                        " ObjId: " + wt.objectId
                        );
            }
        }
        assertEquals("Expected half the threads to fail",wtt.length/2,failed);
    }

    /**
     * Test the following scenario:
     *   Thread 1 borrows an instance
     *   Thread 2 starts to borrow another instance before thread 1 returns its instance
     *   Thread 1 returns its instance while thread 2 is validating its newly created instance
     * The test verifies that the instance created by Thread 2 is not leaked.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testMakeConcurrentWithReturn() throws Exception {
        pool.setTestOnBorrow(true);
        factory.setValid(true);
        // Borrow and return an instance, with a short wait
        WaitingTestThread thread1 = new WaitingTestThread(pool, 200);
        thread1.start();
        Thread.sleep(50); // wait for validation to succeed
        // Slow down validation and borrow an instance
        factory.setValidateLatency(400);
        String instance = pool.borrowObject();
        // Now make sure that we have not leaked an instance
        assertEquals(factory.getMakeCounter(), pool.getNumIdle() + 1);
        pool.returnObject(instance);
        assertEquals(factory.getMakeCounter(), pool.getNumIdle());
    }

    /**
     * Ensure the pool is registered.
     */
    @Test(timeout=60000)
    public void testJmxRegistration() {
        ObjectName oname = pool.getJmxName();
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> result = mbs.queryNames(oname, null);
        Assert.assertEquals(1, result.size());
        pool.jmxUnregister();

        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setJmxEnabled(false);
        GenericObjectPool<String> poolWithoutJmx = new GenericObjectPool<String>(factory, config);
        assertNull(poolWithoutJmx.getJmxName());
        config.setJmxEnabled(true);
        poolWithoutJmx.jmxUnregister();

        config.setJmxNameBase(null);
        GenericObjectPool<String> poolWithDefaultJmxNameBase = new GenericObjectPool<String>(factory, config);
        assertNotNull(poolWithDefaultJmxNameBase.getJmxName());
    }

    /**
     * Verify that threads waiting on a depleted pool get served when a checked out object is
     * invalidated.
     *
     * JIRA: POOL-240
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testInvalidateFreesCapacity()
        throws Exception {
        SimpleFactory factory = new SimpleFactory();
        GenericObjectPool<String> pool = new GenericObjectPool<String>(factory);
        pool.setMaxTotal(2);
        pool.setMaxWaitMillis(500);
        // Borrow an instance and hold if for 5 seconds
        WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
        thread1.start();
        // Borrow another instance
        String obj = pool.borrowObject();
        // Launch another thread - will block, but fail in 500 ms
        WaitingTestThread thread2 = new WaitingTestThread(pool, 100);
        thread2.start();
        // Invalidate the object borrowed by this thread - should allow thread2 to create
        Thread.sleep(20);
        pool.invalidateObject(obj);
        Thread.sleep(600); // Wait for thread2 to timeout
        if (thread2._thrown != null) {
            fail(thread2._thrown.toString());
        }
    }

    /**
     * Verify that threads waiting on a depleted pool get served when a returning object fails
     * validation.
     *
     * JIRA: POOL-240
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testValidationFailureOnReturnFreesCapacity()
        throws Exception {
        SimpleFactory factory = new SimpleFactory();
        factory.setValid(false); // Validate will always fail
        factory.setValidationEnabled(true);
        GenericObjectPool<String> pool = new GenericObjectPool<String>(factory);
        pool.setMaxTotal(2);
        pool.setMaxWaitMillis(1500);
        pool.setTestOnReturn(true);
        pool.setTestOnBorrow(false);
        // Borrow an instance and hold if for 5 seconds
        WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
        thread1.start();
        // Borrow another instance and return it after 500 ms (validation will fail)
        WaitingTestThread thread2 = new WaitingTestThread(pool, 500);
        thread2.start();
        Thread.sleep(50);
        // Try to borrow an object
        String obj = pool.borrowObject();
        pool.returnObject(obj);
    }

    @Test
    public void testSwallowedExceptionListener() {
        pool.setSwallowedExceptionListener(null); // must simply return
        final List<Exception> swallowedExceptions = new ArrayList<Exception>();
        /*
         * A simple listener, that will throw a OOM on 3rd exception.
         */
        final SwallowedExceptionListener listener = new SwallowedExceptionListener() {
            @Override
            public void onSwallowException(Exception e) {
                if (swallowedExceptions.size() == 2) {
                    throw new OutOfMemoryError();
                } else {
                    swallowedExceptions.add(e);
                }
            }
        };
        pool.setSwallowedExceptionListener(listener);

        Exception e1 = new Exception();
        Exception e2 = new ArrayIndexOutOfBoundsException();

        pool.swallowException(e1);
        pool.swallowException(e2);

        try {
            pool.swallowException(e1);
            fail("Not supposed to get here");
        } catch (OutOfMemoryError oom) {
            // expected
        }

        assertEquals(2, swallowedExceptions.size());
    }

    // POOL-248
    @Test(expected=IllegalStateException.class)
    public void testMultipleReturnOfSameObject() throws Exception {
        final GenericObjectPool<String> pool = new GenericObjectPool<String>(
                factory, new GenericObjectPoolConfig());

        Assert.assertEquals(0, pool.getNumActive());
        Assert.assertEquals(0, pool.getNumIdle());

        String obj = pool.borrowObject();

        Assert.assertEquals(1, pool.getNumActive());
        Assert.assertEquals(0, pool.getNumIdle());

        pool.returnObject(obj);

        Assert.assertEquals(0, pool.getNumActive());
        Assert.assertEquals(1, pool.getNumIdle());

        pool.returnObject(obj);

        Assert.assertEquals(0, pool.getNumActive());
        Assert.assertEquals(1, pool.getNumIdle());
    }

    // POOL-259
    @Test
    public void testClientWaitStats() throws Exception {
        SimpleFactory factory = new SimpleFactory();
        // Give makeObject a little latency
        factory.setMakeLatency(200);
        final GenericObjectPool<String> pool = new GenericObjectPool<String>(
                factory, new GenericObjectPoolConfig());
        String s = pool.borrowObject();
        // First borrow waits on create, so wait time should be at least 200 ms
        // Allow 100ms error in clock times
        Assert.assertTrue(pool.getMaxBorrowWaitTimeMillis() >= 100);
        Assert.assertTrue(pool.getMeanBorrowWaitTimeMillis() >= 100);
        pool.returnObject(s);
        pool.borrowObject();
        // Second borrow does not have to wait on create, average should be about 100
        Assert.assertTrue(pool.getMaxBorrowWaitTimeMillis() > 100);
        Assert.assertTrue(pool.getMeanBorrowWaitTimeMillis() < 200);
        Assert.assertTrue(pool.getMeanBorrowWaitTimeMillis() > 20);
    }

    // POOL-276
    @Test
    public void testValidationOnCreateOnly() throws Exception {
        pool.setMaxTotal(1);
        pool.setTestOnCreate(true);
        pool.setTestOnBorrow(false);
        pool.setTestOnReturn(false);
        pool.setTestWhileIdle(false);

        final String o1 = pool.borrowObject();
        Assert.assertEquals("0", o1);
        Timer t = new Timer();
        t.schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        pool.returnObject(o1);
                    }
                }, 3000);

        String o2 = pool.borrowObject();
        Assert.assertEquals("0", o2);

        Assert.assertEquals(1, factory.validateCounter);
    }

    private static final class DummyFactory
            extends BasePooledObjectFactory<Object> {
        @Override
        public Object create() throws Exception {
            return null;
        }
        @Override
        public PooledObject<Object> wrap(Object value) {
            return new DefaultPooledObject<Object>(value);
        }
    }


    private static class InvalidFactory
            extends BasePooledObjectFactory<Object> {

        @Override
        public Object create() throws Exception {
            return new Object();
        }
        @Override
        public PooledObject<Object> wrap(Object value) {
            return new DefaultPooledObject<Object>(value);
        }

        @Override
        public boolean validateObject(PooledObject<Object> obj) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // Ignore
            }
            return false;
        }
    }

    private static class EvictionThread<T> extends Thread {

        private final GenericObjectPool<T> pool;

        public EvictionThread(GenericObjectPool<T> pool) {
            this.pool = pool;
        }

        @Override
        public void run() {
            try {
                pool.evict();
            } catch (Exception e) {
                // Ignore
            }
        }
    }
}
