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

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

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

import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
import org.apache.commons.pool2.KeyedObjectPool;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.TestKeyedObjectPool;
import org.apache.commons.pool2.VisitTracker;
import org.apache.commons.pool2.VisitTrackerFactory;
import org.apache.commons.pool2.Waiter;
import org.apache.commons.pool2.WaiterFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @version $Revision$
 */
public class TestGenericKeyedObjectPool extends TestKeyedObjectPool {

    @Override
    protected KeyedObjectPool<Object,Object> makeEmptyPool(int mincapacity) {
        KeyedPooledObjectFactory<Object,Object> perKeyFactory =
                new SimplePerKeyFactory();
        GenericKeyedObjectPool<Object,Object> perKeyPool =
            new GenericKeyedObjectPool<Object,Object>(perKeyFactory);
        perKeyPool.setMaxTotalPerKey(mincapacity);
        perKeyPool.setMaxIdlePerKey(mincapacity);
        return perKeyPool;
    }

    @Override
    protected KeyedObjectPool<Object,Object> makeEmptyPool(KeyedPooledObjectFactory<Object,Object> fac) {
        return new GenericKeyedObjectPool<Object,Object>(fac);
    }

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

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

    /** setUp(): {@code new GenericKeyedObjectPool<String,String>(factory)} */
    private GenericKeyedObjectPool<String,String> pool = null;
    /** setUp(): {@code new SimpleFactory<String>()} */
    private SimpleFactory<String> factory = null;
    private static final Integer KEY_ZERO = Integer.valueOf(0);
    private static final Integer KEY_ONE = Integer.valueOf(1);
    private static final Integer KEY_TWO = Integer.valueOf(2);

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

    @Override
    @After
    public void tearDown() throws Exception {
        super.tearDown();
        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=GenericKeyedObjectPool,*"),
                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(timeout=60000)
    public void testNegativeMaxTotalPerKey() throws Exception {
        pool.setMaxTotalPerKey(-1);
        pool.setBlockWhenExhausted(false);
        String obj = pool.borrowObject("");
        assertEquals("0",obj);
        pool.returnObject("",obj);
    }

    @Test(timeout=60000)
    public void testNumActiveNumIdle2() throws Exception {
        assertEquals(0,pool.getNumActive());
        assertEquals(0,pool.getNumIdle());
        assertEquals(0,pool.getNumActive("A"));
        assertEquals(0,pool.getNumIdle("A"));
        assertEquals(0,pool.getNumActive("B"));
        assertEquals(0,pool.getNumIdle("B"));

        String objA0 = pool.borrowObject("A");
        String objB0 = pool.borrowObject("B");

        assertEquals(2,pool.getNumActive());
        assertEquals(0,pool.getNumIdle());
        assertEquals(1,pool.getNumActive("A"));
        assertEquals(0,pool.getNumIdle("A"));
        assertEquals(1,pool.getNumActive("B"));
        assertEquals(0,pool.getNumIdle("B"));

        String objA1 = pool.borrowObject("A");
        String objB1 = pool.borrowObject("B");

        assertEquals(4,pool.getNumActive());
        assertEquals(0,pool.getNumIdle());
        assertEquals(2,pool.getNumActive("A"));
        assertEquals(0,pool.getNumIdle("A"));
        assertEquals(2,pool.getNumActive("B"));
        assertEquals(0,pool.getNumIdle("B"));

        pool.returnObject("A",objA0);
        pool.returnObject("B",objB0);

        assertEquals(2,pool.getNumActive());
        assertEquals(2,pool.getNumIdle());
        assertEquals(1,pool.getNumActive("A"));
        assertEquals(1,pool.getNumIdle("A"));
        assertEquals(1,pool.getNumActive("B"));
        assertEquals(1,pool.getNumIdle("B"));

        pool.returnObject("A",objA1);
        pool.returnObject("B",objB1);

        assertEquals(0,pool.getNumActive());
        assertEquals(4,pool.getNumIdle());
        assertEquals(0,pool.getNumActive("A"));
        assertEquals(2,pool.getNumIdle("A"));
        assertEquals(0,pool.getNumActive("B"));
        assertEquals(2,pool.getNumIdle("B"));
    }

    @Test(timeout=60000)
    public void testMaxIdle() throws Exception {
        pool.setMaxTotalPerKey(100);
        pool.setMaxIdlePerKey(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(""));
        }

        for(int i=0;i<100;i++) {
            active[i] = pool.borrowObject("a");
        }
        assertEquals(100,pool.getNumActive("a"));
        assertEquals(0,pool.getNumIdle("a"));
        for(int i=0;i<100;i++) {
            pool.returnObject("a",active[i]);
            assertEquals(99 - i,pool.getNumActive("a"));
            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("a"));
        }

        // total number of idle instances is twice maxIdle
        assertEquals(16, pool.getNumIdle());
        // Each pool is at the sup
        assertEquals(8, pool.getNumIdle(""));
        assertEquals(8, pool.getNumIdle("a"));

    }

    @Test(timeout=60000)
    public void testMaxTotalPerKey() throws Exception {
        pool.setMaxTotalPerKey(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 testMaxTotalPerKeyZero() throws Exception {
        pool.setMaxTotalPerKey(0);
        pool.setBlockWhenExhausted(false);

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

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

        String o1 = pool.borrowObject("a");
        assertNotNull(o1);
        String o2 = pool.borrowObject("a");
        assertNotNull(o2);
        String o3 = pool.borrowObject("b");
        assertNotNull(o3);
        try {
            pool.borrowObject("c");
            fail("Expected NoSuchElementException");
        } catch(NoSuchElementException e) {
            // expected
        }

        assertEquals(0, pool.getNumIdle());

        pool.returnObject("b", o3);
        assertEquals(1, pool.getNumIdle());
        assertEquals(1, pool.getNumIdle("b"));

        Object o4 = pool.borrowObject("b");
        assertNotNull(o4);
        assertEquals(0, pool.getNumIdle());
        assertEquals(0, pool.getNumIdle("b"));

        pool.setMaxTotal(4);
        Object o5 = pool.borrowObject("b");
        assertNotNull(o5);

        assertEquals(2, pool.getNumActive("a"));
        assertEquals(2, pool.getNumActive("b"));
        assertEquals(pool.getMaxTotal(),
                pool.getNumActive("b") + pool.getNumActive("b"));
        assertEquals(pool.getNumActive(),
                pool.getMaxTotal());
    }

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

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

    @Test(timeout=60000)
    public void testMaxTotalLRU() throws Exception {
        pool.setMaxTotalPerKey(2);
        pool.setMaxTotal(3);

        String o1 = pool.borrowObject("a");
        assertNotNull(o1);
        pool.returnObject("a", o1);
        Thread.sleep(25);

        String o2 = pool.borrowObject("b");
        assertNotNull(o2);
        pool.returnObject("b", o2);
        Thread.sleep(25);

        String o3 = pool.borrowObject("c");
        assertNotNull(o3);
        pool.returnObject("c", o3);
        Thread.sleep(25);

        String o4 = pool.borrowObject("a");
        assertNotNull(o4);
        pool.returnObject("a", o4);
        Thread.sleep(25);

        assertSame(o1, o4);

        // this should cause b to be bumped out of the pool
        String o5 = pool.borrowObject("d");
        assertNotNull(o5);
        pool.returnObject("d", o5);
        Thread.sleep(25);

        // now re-request b, we should get a different object because it should
        // have been expelled from pool (was oldest because a was requested after b)
        String o6 = pool.borrowObject("b");
        assertNotNull(o6);
        pool.returnObject("b", o6);

        assertNotSame(o1, o6);
        assertNotSame(o2, o6);

        // second a is still in there
        String o7 = pool.borrowObject("a");
        assertNotNull(o7);
        pool.returnObject("a", o7);

        assertSame(o4, o7);
    }

    @Test(timeout=60000)
    public void testSettersAndGetters() throws Exception {
        {
            pool.setMaxTotalPerKey(123);
            assertEquals(123,pool.getMaxTotalPerKey());
        }
        {
            pool.setMaxIdlePerKey(12);
            assertEquals(12,pool.getMaxIdlePerKey());
        }
        {
            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.setBlockWhenExhausted(true);
            assertTrue(pool.getBlockWhenExhausted());
            pool.setBlockWhenExhausted(false);
            assertFalse(pool.getBlockWhenExhausted());
        }
    }
    
    /** 
     * JIRA: POOL-270 - make sure constructor correctly sets run
     * frequency of evictor timer.
     */
    @Test
    public void testContructorEvictionConfig() throws Exception {
        GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
        config.setTimeBetweenEvictionRunsMillis(500);
        config.setMinEvictableIdleTimeMillis(50);
        config.setNumTestsPerEvictionRun(5);
        GenericKeyedObjectPool<String, String> p = new GenericKeyedObjectPool<String, String>(factory, config);
        for(int i=0;i<5;i++) {
            p.addObject("one");
        }
        try { Thread.sleep(100); } catch(InterruptedException e) { }
        assertEquals(5, p.getNumIdle("one"));
        try { Thread.sleep(500); } catch(InterruptedException e) { }
        assertEquals(0, p.getNumIdle("one"));
        p.close();
    }
    

    @Test(timeout=60000)
    public void testEviction() throws Exception {
        pool.setMaxIdlePerKey(500);
        pool.setMaxTotalPerKey(500);
        pool.setNumTestsPerEvictionRun(100);
        pool.setMinEvictableIdleTimeMillis(250L);
        pool.setTimeBetweenEvictionRunsMillis(500L);

        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(""));
    }

    @Test(timeout=60000)
    public void testEviction2() throws Exception {
        pool.setMaxIdlePerKey(500);
        pool.setMaxTotalPerKey(500);
        pool.setNumTestsPerEvictionRun(100);
        pool.setMinEvictableIdleTimeMillis(500L);
        pool.setTimeBetweenEvictionRunsMillis(500L);

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

        try { Thread.sleep(1100L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 1000 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 1000);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 900 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 900);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 800 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 800);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 700 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 700);
        try { Thread.sleep(600L); } catch(InterruptedException e) { }
        assertTrue("Should be less than 600 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 600);
        try { Thread.sleep(600L); } 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());
    }

    /**
     * Kicks off <code>numThreads</code> test threads, each of which will go
     * through <code>iterations</code> borrow-return cycles with random delay
     * times &lt;= delay in between.
     *
     * @param <T>           Type of object in pool
     * @param numThreads    Number of test threads
     * @param iterations    Number of iterations for each thread
     * @param delay         Maximum delay between iterations
     * @param gkopPool      The keyed object pool to use
     */
    public <T> void runTestThreads(int numThreads, int iterations, int delay, GenericKeyedObjectPool<String,T> gkopPool) {
        ArrayList<TestThread<T>> threads = new ArrayList<TestThread<T>>();
        for(int i=0;i<numThreads;i++) {
            TestThread<T> testThread = new TestThread<T>(gkopPool, iterations, delay);
            threads.add(testThread);
            Thread t = new Thread(testThread);
            t.start();
        }
        for (TestThread<T> testThread : threads) {
            while(!(testThread.complete())) {
                try {
                    Thread.sleep(500L);
                } catch(InterruptedException e) {
                    // ignored
                }
            }
            if(testThread.failed()) {
                fail("Thread failed: " + threads.indexOf(testThread) + "\n" +
                        getExceptionTrace(testThread._exception));
            }
        }
    }

    @Test(timeout=60000)
    public void testThreaded1() throws Exception {
        pool.setMaxTotalPerKey(15);
        pool.setMaxIdlePerKey(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.setMaxTotalPerKey(maxTotal);  // (makes - destroys) bound
        factory.setValidationEnabled(true);
        pool.setMaxTotal(maxTotal);
        pool.setMaxIdlePerKey(-1);
        pool.setTestOnReturn(true);
        pool.setMaxWaitMillis(10000L);
        runTestThreads(5, 10, 50, pool);
    }

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


        //Generate a random key
        String key = "A";

        pool.preparePool(key);

        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(key);

        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(key);
        }

        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(key, 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 testMinIdleMaxTotalPerKey() throws Exception {
        pool.setMaxIdlePerKey(500);
        pool.setMinIdlePerKey(5);
        pool.setMaxTotalPerKey(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);

        String key = "A";

        pool.preparePool(key);
        assertTrue("Should be 5 idle, found " +
                pool.getNumIdle(),pool.getNumIdle() == 5);

        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(key);
        }

        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(key, 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(key);
        }

        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(key, 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 testMinIdleNoPreparePool() throws Exception {
        pool.setMaxIdlePerKey(500);
        pool.setMinIdlePerKey(5);
        pool.setMaxTotalPerKey(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);


        //Generate a random key
        String key = "A";

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

        Object active = pool.borrowObject(key);
        assertNotNull(active);

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

    @Test(timeout=60000)
    public void testFIFO() throws Exception {
        pool.setLifo(false);
        final String key = "key";
        pool.addObject(key); // "key0"
        pool.addObject(key); // "key1"
        pool.addObject(key); // "key2"
        assertEquals("Oldest", "key0", pool.borrowObject(key));
        assertEquals("Middle", "key1", pool.borrowObject(key));
        assertEquals("Youngest", "key2", pool.borrowObject(key));
        String s = pool.borrowObject(key);
        assertEquals("new-3", "key3", s);
        pool.returnObject(key, s);
        assertEquals("returned", s, pool.borrowObject(key));
        assertEquals("new-4", "key4", pool.borrowObject(key));
    }

    @Test(timeout=60000)
    public void testLIFO() throws Exception {
        pool.setLifo(true);
        final String key = "key";
        pool.addObject(key); // "key0"
        pool.addObject(key); // "key1"
        pool.addObject(key); // "key2"
        assertEquals("Youngest", "key2", pool.borrowObject(key));
        assertEquals("Middle", "key1", pool.borrowObject(key));
        assertEquals("Oldest", "key0", pool.borrowObject(key));
        String s = pool.borrowObject(key);
        assertEquals("new-3", "key3", s);
        pool.returnObject(key, s);
        assertEquals("returned", s, pool.borrowObject(key));
        assertEquals("new-4", "key4", pool.borrowObject(key));
    }

    /**
     * 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);
        checkEvictionOrder(true);
    }

    private void checkEvictionOrder(boolean lifo) throws Exception {
        SimpleFactory<Integer> intFactory = new SimpleFactory<Integer>();
        GenericKeyedObjectPool<Integer,String> intPool =
            new GenericKeyedObjectPool<Integer,String>(intFactory);
        intPool.setNumTestsPerEvictionRun(2);
        intPool.setMinEvictableIdleTimeMillis(100);
        intPool.setLifo(lifo);

        for (int i = 0; i < 3; i ++) {
            Integer key = Integer.valueOf(i);
            for (int j = 0; j < 5; j++) {
                intPool.addObject(key);
            }
        }

        // Make all evictable
        Thread.sleep(200);

        /*
         * Initial state (Key, Object) pairs in order of age:
         *
         * (0,0), (0,1), (0,2), (0,3), (0,4)
         * (1,5), (1,6), (1,7), (1,8), (1,9)
         * (2,10), (2,11), (2,12), (2,13), (2,14)
         */

        intPool.evict(); // Kill (0,0),(0,1)
        assertEquals(3, intPool.getNumIdle(KEY_ZERO));
        String objZeroA = intPool.borrowObject(KEY_ZERO);
        assertTrue(lifo ? objZeroA.equals("04") : objZeroA.equals("02"));
        assertEquals(2, intPool.getNumIdle(KEY_ZERO));
        String objZeroB = intPool.borrowObject(KEY_ZERO);
        assertTrue(objZeroB.equals("03"));
        assertEquals(1, intPool.getNumIdle(KEY_ZERO));

        intPool.evict(); // Kill remaining 0 survivor and (1,5)
        assertEquals(0, intPool.getNumIdle(KEY_ZERO));
        assertEquals(4, intPool.getNumIdle(KEY_ONE));
        String objOneA = intPool.borrowObject(KEY_ONE);
        assertTrue(lifo ? objOneA.equals("19") : objOneA.equals("16"));
        assertEquals(3, intPool.getNumIdle(KEY_ONE));
        String objOneB = intPool.borrowObject(KEY_ONE);
        assertTrue(lifo ? objOneB.equals("18") : objOneB.equals("17"));
        assertEquals(2, intPool.getNumIdle(KEY_ONE));

        intPool.evict(); // Kill remaining 1 survivors
        assertEquals(0, intPool.getNumIdle(KEY_ONE));
        intPool.evict(); // Kill (2,10), (2,11)
        assertEquals(3, intPool.getNumIdle(KEY_TWO));
        String objTwoA = intPool.borrowObject(KEY_TWO);
        assertTrue(lifo ? objTwoA.equals("214") : objTwoA.equals("212"));
        assertEquals(2, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // All dead now
        assertEquals(0, intPool.getNumIdle(KEY_TWO));

        intPool.evict(); // Should do nothing - make sure no exception
        // Currently 2 zero, 2 one and 1 two active. Return them
        intPool.returnObject(KEY_ZERO, objZeroA);
        intPool.returnObject(KEY_ZERO, objZeroB);
        intPool.returnObject(KEY_ONE, objOneA);
        intPool.returnObject(KEY_ONE, objOneB);
        intPool.returnObject(KEY_TWO, objTwoA);
        // Remove all idle objects
        intPool.clear();

        // Reload
        intPool.setMinEvictableIdleTimeMillis(500);
        intFactory.counter = 0; // Reset counter
        for (int i = 0; i < 3; i ++) {
            Integer key = Integer.valueOf(i);
            for (int j = 0; j < 5; j++) {
                intPool.addObject(key);
            }
            Thread.sleep(200);
        }

        // 0's are evictable, others not
        intPool.evict(); // Kill (0,0),(0,1)
        assertEquals(3, intPool.getNumIdle(KEY_ZERO));
        intPool.evict(); // Kill (0,2),(0,3)
        assertEquals(1, intPool.getNumIdle(KEY_ZERO));
        intPool.evict(); // Kill (0,4), leave (1,5)
        assertEquals(0, intPool.getNumIdle(KEY_ZERO));
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // (1,6), (1,7)
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // (1,8), (1,9)
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // (2,10), (2,11)
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // (2,12), (2,13)
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        intPool.evict(); // (2,14), (1,5)
        assertEquals(5, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        Thread.sleep(200); // Ones now timed out
        intPool.evict(); // kill (1,6), (1,7) - (1,5) missed
        assertEquals(3, intPool.getNumIdle(KEY_ONE));
        assertEquals(5, intPool.getNumIdle(KEY_TWO));
        String obj = intPool.borrowObject(KEY_ONE);
        if (lifo) {
            assertEquals("19", obj);
        } else {
            assertEquals("15", obj);
        }
        intPool.close();
    }


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

    private void checkEvictorVisiting(boolean lifo) throws Exception {
        VisitTrackerFactory<Integer> trackerFactory = new VisitTrackerFactory<Integer>();
        GenericKeyedObjectPool<Integer,VisitTracker<Integer>> intPool =
            new GenericKeyedObjectPool<Integer,VisitTracker<Integer>>(trackerFactory);
        intPool.setNumTestsPerEvictionRun(2);
        intPool.setMinEvictableIdleTimeMillis(-1);
        intPool.setTestWhileIdle(true);
        intPool.setLifo(lifo);
        intPool.setTestOnReturn(false);
        intPool.setTestOnBorrow(false);
        for (int i = 0; i < 3; i ++) {
            trackerFactory.resetId();
            Integer key = Integer.valueOf(i);
            for (int j = 0; j < 8; j++) {
                intPool.addObject(key);
            }
        }
        intPool.evict(); // Visit oldest 2 - 00 and 01
        VisitTracker<Integer> obj = intPool.borrowObject(KEY_ZERO);
        intPool.returnObject(KEY_ZERO, obj);
        obj = intPool.borrowObject(KEY_ZERO);
        intPool.returnObject(KEY_ZERO, obj);
        //  borrow, return, borrow, return
        //  FIFO will move 0 and 1 to end - 2,3,4,5,6,7,0,1
        //  LIFO, 7 out, then in, then out, then in - 7,6,5,4,3,2,1,0
        intPool.evict();  // Should visit 02 and 03 in either case
        for (int i = 0; i < 8; i++) {
            VisitTracker<Integer> tracker = intPool.borrowObject(KEY_ZERO);
            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());
            }
        }
        // 0's are all out

        intPool.setNumTestsPerEvictionRun(3);

        intPool.evict(); // 10, 11, 12
        intPool.evict(); // 13, 14, 15

        obj = intPool.borrowObject(KEY_ONE);
        intPool.returnObject(KEY_ONE, obj);
        obj = intPool.borrowObject(KEY_ONE);
        intPool.returnObject(KEY_ONE, obj);
        obj = intPool.borrowObject(KEY_ONE);
        intPool.returnObject(KEY_ONE, 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
        intPool.evict();
        // LIFO - 16, 17, 20
        // FIFO - 16, 17, 10
        intPool.evict();
        // LIFO - 21, 22, 23
        // FIFO - 11, 12, 20
        intPool.evict();
        // LIFO - 24, 25, 26
        // FIFO - 21, 22, 23
        intPool.evict();
        // LIFO - 27, 10, 11
        // FIFO - 24, 25, 26
        for (int i = 0; i < 8; i++) {
            VisitTracker<Integer> tracker = intPool.borrowObject(KEY_ONE);
            if ((lifo && tracker.getId() > 1) ||
                    (!lifo && tracker.getId() > 2)) {
                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());
            }
        }
        intPool.close();

        // Randomly generate some 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 < smallPrimes.length; i++) {
            for (int j = 0; j < 5; j++) {// Try the tests a few times
                // Can't use clear as some objects are still active so create
                // a new pool
                trackerFactory = new VisitTrackerFactory<Integer>();
                intPool = new GenericKeyedObjectPool<Integer,VisitTracker<Integer>>(trackerFactory);
                intPool.setMaxIdlePerKey(-1);
                intPool.setMaxTotalPerKey(-1);
                intPool.setNumTestsPerEvictionRun(smallPrimes[i]);
                intPool.setMinEvictableIdleTimeMillis(-1);
                intPool.setTestWhileIdle(true);
                intPool.setLifo(lifo);
                intPool.setTestOnReturn(false);
                intPool.setTestOnBorrow(false);

                int zeroLength = 10 + random.nextInt(20);
                for (int k = 0; k < zeroLength; k++) {
                    intPool.addObject(KEY_ZERO);
                }
                int oneLength = 10 + random.nextInt(20);
                for (int k = 0; k < oneLength; k++) {
                    intPool.addObject(KEY_ONE);
                }
                int twoLength = 10 + random.nextInt(20);
                for (int k = 0; k < twoLength; k++) {
                    intPool.addObject(KEY_TWO);
                }

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

                // Total instances in pool
                int totalInstances = zeroLength + oneLength + twoLength;

                // Number of times evictor should have cycled through pools
                int cycleCount = (runs * intPool.getNumTestsPerEvictionRun()) /
                        totalInstances;

                // Look at elements and make sure they are visited cycleCount
                // or cycleCount + 1 times
                VisitTracker<Integer> tracker = null;
                int visitCount = 0;
                for (int k = 0; k < zeroLength; k++) {
                    tracker = intPool.borrowObject(KEY_ZERO);
                    visitCount = tracker.getValidateCount();
                    if (visitCount < cycleCount || visitCount > cycleCount + 1){
                        fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j,
                                "k", k, "visitCount", visitCount, "cycleCount", cycleCount,
                                "totalInstances", totalInstances, zeroLength, oneLength, twoLength));
                    }
                }
                for (int k = 0; k < oneLength; k++) {
                    tracker = intPool.borrowObject(KEY_ONE);
                    visitCount = tracker.getValidateCount();
                    if (visitCount < cycleCount || visitCount > cycleCount + 1){
                        fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j,
                                "k", k, "visitCount", visitCount, "cycleCount", cycleCount,
                                "totalInstances", totalInstances, zeroLength, oneLength, twoLength));
                    }
                }
                int visits[] = new int[twoLength];
                for (int k = 0; k < twoLength; k++) {
                    tracker = intPool.borrowObject(KEY_TWO);
                    visitCount = tracker.getValidateCount();
                    visits[k] = visitCount;
                    if (visitCount < cycleCount || visitCount > cycleCount + 1){
                        StringBuilder sb = new StringBuilder("Visits:");
                        for (int l = 0; l <= k; l++){
                            sb.append(visits[l]).append(' ');
                        }
                        fail(formatSettings("TWO "+sb.toString(), "runs", runs, "lifo", lifo, "i", i, "j", j,
                                "k", k, "visitCount", visitCount, "cycleCount", cycleCount,
                                "totalInstances", totalInstances, zeroLength, oneLength, twoLength));
                    }
                }
                intPool.close();
            }
        }
    }

    /*
     * 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;

        GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
        config.setMaxTotalPerKey(maxTotal);
        config.setFairness(true);
        config.setLifo(false);
        config.setMaxIdlePerKey(maxTotal);

        pool = new GenericKeyedObjectPool<String, String>(factory, config);

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

        // 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, "0" + String.valueOf(i % maxTotal), "0");
            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("0", 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]._exception.toString());
            }
        }
    }

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

        // Make constructor arguments all different from defaults
        int maxTotalPerKey = 1;
        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;
        KeyedPooledObjectFactory<Object,Object> dummyFactory = new DummyFactory();

        GenericKeyedObjectPool<Object,Object> objPool =
                new GenericKeyedObjectPool<Object,Object>(dummyFactory);
        assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY, objPool.getMaxTotalPerKey());
        assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY, objPool.getMaxIdlePerKey());
        assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, objPool.getMaxWaitMillis());
        assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY, objPool.getMinIdlePerKey());
        assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL, objPool.getMaxTotal());
        assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                objPool.getMinEvictableIdleTimeMillis());
        assertEquals(BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                objPool.getNumTestsPerEvictionRun());
        assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW),
                Boolean.valueOf(objPool.getTestOnBorrow()));
        assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN),
                Boolean.valueOf(objPool.getTestOnReturn()));
        assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE),
                Boolean.valueOf(objPool.getTestWhileIdle()));
        assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                objPool.getTimeBetweenEvictionRunsMillis());
        assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED),
                Boolean.valueOf(objPool.getBlockWhenExhausted()));
        assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_LIFO),
                Boolean.valueOf(objPool.getLifo()));
        objPool.close();

        GenericKeyedObjectPoolConfig config =
                new GenericKeyedObjectPoolConfig();
        config.setLifo(lifo);
        config.setMaxTotalPerKey(maxTotalPerKey);
        config.setMaxIdlePerKey(maxIdle);
        config.setMinIdlePerKey(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);
        objPool = new GenericKeyedObjectPool<Object,Object>(dummyFactory, config);
        assertEquals(maxTotalPerKey, objPool.getMaxTotalPerKey());
        assertEquals(maxIdle, objPool.getMaxIdlePerKey());
        assertEquals(maxWait, objPool.getMaxWaitMillis());
        assertEquals(minIdle, objPool.getMinIdlePerKey());
        assertEquals(maxTotal, objPool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                objPool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun, objPool.getNumTestsPerEvictionRun());
        assertEquals(Boolean.valueOf(testOnBorrow),
                Boolean.valueOf(objPool.getTestOnBorrow()));
        assertEquals(Boolean.valueOf(testOnReturn),
                Boolean.valueOf(objPool.getTestOnReturn()));
        assertEquals(Boolean.valueOf(testWhileIdle),
                Boolean.valueOf(objPool.getTestWhileIdle()));
        assertEquals(timeBetweenEvictionRunsMillis,
                objPool.getTimeBetweenEvictionRunsMillis());
        assertEquals(Boolean.valueOf(blockWhenExhausted),
                Boolean.valueOf(objPool.getBlockWhenExhausted()));
        assertEquals(Boolean.valueOf(lifo),
                Boolean.valueOf(objPool.getLifo()));
        objPool.close();
    }

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

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

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

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

    @Test(timeout=60000)
    public void testExceptionOnActivateDuringBorrow() throws Exception {
        String obj1 = pool.borrowObject("one");
        String obj2 = pool.borrowObject("one");
        pool.returnObject("one", obj1);
        pool.returnObject("one", 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("one");
        assertEquals(1, pool.getNumActive("one"));
        assertEquals(0, pool.getNumIdle("one"));
        assertEquals(1, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());

        pool.returnObject("one", 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("one");
            fail("Expecting NoSuchElementException");
        } catch (NoSuchElementException ex) {
            // expected
        }
        assertEquals(0, pool.getNumActive("one"));
        assertEquals(0, pool.getNumIdle("one"));
        assertEquals(0, pool.getNumActive());
        assertEquals(0, pool.getNumIdle());
    }

    @Test(timeout=60000)
    public void testBlockedKeyDoesNotBlockPool() throws Exception {
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(5000);
        pool.setMaxTotalPerKey(1);
        pool.setMaxTotal(-1);
        pool.borrowObject("one");
        long start = System.currentTimeMillis();
        // Needs to be in a separate thread as this will block
        Runnable simple = new SimpleTestThread<String>(pool, "one");
        (new Thread(simple)).start();
        // This should be almost instant. If it isn't it means this thread got
        // stuck behind the thread created above which is bad.
        // Give other thread a chance to start
        Thread.sleep(1000);
        pool.borrowObject("two");
        long end = System.currentTimeMillis();
        // If it fails it will be more than 4000ms (5000 less the 1000 sleep)
        // If it passes it should be almost instant
        // Use 3000ms as the threshold - should avoid timing issues on most
        // (all? platforms)
        assertTrue ("Elapsed time: "+(end-start)+" should be less than 4000",(end-start) < 4000);

    }

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

    /*
     * Test multi-threaded pool access.
     * Multiple keys, multiple threads, but maxActive only allows half the threads to succeed.
     *
     * This test was prompted by Continuum build failures in the Commons DBCP test case:
     * TestSharedPoolDataSource.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 = 4 * maxWait; // how long to hold connection
        final int keyCount = 4; // number of different keys
        final int threadsPerKey = 5; // number of threads to grab the key initially
        pool.setBlockWhenExhausted(true);
        pool.setMaxWaitMillis(maxWait);
        pool.setMaxTotalPerKey(threadsPerKey);
        // Create enough threads so half the threads will have to wait
        WaitingTestThread wtt[] = new WaitingTestThread[keyCount * threadsPerKey * 2];
        for(int i=0; i < wtt.length; i++){
            wtt[i] = new WaitingTestThread(pool,Integer.toString(i % keyCount),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 +
                    " KeyCount: " + keyCount +
                    " MaxActive: " + threadsPerKey +
                    " 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) +
                        " Key: " + (wt._key) +
                        " ObjId: " + wt.objectId
                        );
            }
        }
        assertEquals("Expected half the threads to fail",wtt.length/2,failed);
    }

    /**
     * Test case for POOL-180.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=200000)
    public void testMaxActivePerKeyExceeded() throws Exception {
        WaiterFactory<String> waiterFactory = new WaiterFactory<String>(0, 20, 0, 0, 0, 0, 8, 5, 0);
        // TODO Fix this. Can't use local pool since runTestThreads uses the
        //      protected pool field
        GenericKeyedObjectPool<String,Waiter> waiterPool =
                new GenericKeyedObjectPool<String,Waiter>(waiterFactory);
        waiterPool.setMaxTotalPerKey(5);
        waiterPool.setMaxTotal(8);
        waiterPool.setTestOnBorrow(true);
        waiterPool.setMaxIdlePerKey(5);
        waiterPool.setMaxWaitMillis(-1);
        runTestThreads(20, 300, 250, waiterPool);
        waiterPool.close();
    }

    /**
     * Test to make sure that clearOldest does not destroy instances that have been checked out.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testClearOldest() throws Exception {
        // Make destroy have some latency so clearOldest takes some time
        WaiterFactory<String> waiterFactory = new WaiterFactory<String>(0, 20, 0, 0, 0, 0, 50, 5, 0);
        GenericKeyedObjectPool<String,Waiter> waiterPool =
                new GenericKeyedObjectPool<String,Waiter>(waiterFactory);
        waiterPool.setMaxTotalPerKey(5);
        waiterPool.setMaxTotal(50);
        waiterPool.setLifo(false);
        // Load the pool with idle instances - 5 each for 10 keys
        for (int i = 0; i < 10; i++) {
            final String key = Integer.valueOf(i).toString();
            for (int j = 0; j < 5; j++) {
               waiterPool.addObject(key);
            }
            // Make sure order is maintained
            Thread.sleep(20);
        }
        // Now set up a race - one thread wants a new instance, triggering clearOldest
        // Other goes after an element on death row
        // See if we end up with dead man walking
        SimpleTestThread<Waiter> t2 = new SimpleTestThread<Waiter>(waiterPool, "51");
        Thread thread2 = new Thread(t2);
        thread2.start();  // Triggers clearOldest, killing all of the 0's and the 2 oldest 1's
        Thread.sleep(50); // Wait for clearOldest to kick off, but not long enough to reach the 1's
        Waiter waiter = waiterPool.borrowObject("1");
        Thread.sleep(200); // Wait for execution to happen
        waiterPool.returnObject("1", waiter);  // Will throw IllegalStateException if dead
        waiterPool.close();
    }


    /**
     * Verifies that threads that get parked waiting for keys not in use
     * when the pool is at maxTotal eventually get served.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testLivenessPerKey() throws Exception {
        pool.setMaxIdlePerKey(3);
        pool.setMaxTotal(3);
        pool.setMaxTotalPerKey(3);
        pool.setMaxWaitMillis(3000);  // Really a timeout for the test

        // Check out and briefly hold 3 "1"s
        WaitingTestThread t1 = new WaitingTestThread(pool, "1", 100);
        WaitingTestThread t2 = new WaitingTestThread(pool, "1", 100);
        WaitingTestThread t3 = new WaitingTestThread(pool, "1", 100);
        t1.start();
        t2.start();
        t3.start();

        // Try to get a "2" while all capacity is in use.
        // Thread will park waiting on empty queue. Verify it gets served.
        pool.borrowObject("2");
    }

    /**
     * POOL-192
     * Verify that clear(key) does not leak capacity.
     *
     * @throws Exception May occur in some failure modes
     */
    @Test(timeout=60000)
    public void testClear() throws Exception {
        pool.setMaxTotal(2);
        pool.setMaxTotalPerKey(2);
        pool.setBlockWhenExhausted(false);
        pool.addObject("one");
        pool.addObject("one");
        assertEquals(2, pool.getNumIdle());
        pool.clear("one");
        assertEquals(0, pool.getNumIdle());
        assertEquals(0, pool.getNumIdle("one"));
        String obj1 = pool.borrowObject("one");
        String obj2 = pool.borrowObject("one");
        pool.returnObject("one", obj1);
        pool.returnObject("one", obj2);
        pool.clear();
        assertEquals(0, pool.getNumIdle());
        assertEquals(0, pool.getNumIdle("one"));
        pool.borrowObject("one");
        pool.borrowObject("one");
        pool.close();
    }

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

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

        // Create a separate thread to try and borrow another object
        WaitingTestThread wtt = new WaitingTestThread(pool, "a", 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);
    }

    /**
     * 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;
        final String key = "one";
        pool.setMaxTotal(nObjects);
        pool.setMaxTotalPerKey(nObjects);
        pool.setMaxIdlePerKey(nObjects);
        final String [] obj = new String[nObjects];
        for (int i = 0; i < nObjects; i++) {
            obj[i] = pool.borrowObject(key);
        }
        for (int i = 0; i < nObjects; i++) {
            if (i % 2 == 0) {
                pool.returnObject(key, 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,key, 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());
    }

    // POOL-259
    @Test
    public void testClientWaitStats() throws Exception {
        SimpleFactory<String> factory = new SimpleFactory<String>();
        // Give makeObject a little latency
        factory.setMakeLatency(200);
        final GenericKeyedObjectPool<String, String> pool = new GenericKeyedObjectPool<String, String>(
                factory, new GenericKeyedObjectPoolConfig());
        String s = pool.borrowObject("one");
        // 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("one", s);
        pool.borrowObject("one");
        // 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 {
        factory.enableValidation = true;

        pool.setMaxTotal(1);
        pool.setTestOnCreate(true);
        pool.setTestOnBorrow(false);
        pool.setTestOnReturn(false);
        pool.setTestWhileIdle(false);

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

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

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

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

    /*
     * Very simple test thread that just tries to borrow an object from
     * the provided pool with the specified key and returns it
     */
    static class SimpleTestThread<T> implements Runnable {
        private final KeyedObjectPool<String,T> _pool;
        private final String _key;

        public SimpleTestThread(KeyedObjectPool<String,T> pool, String key) {
            _pool = pool;
            _key = key;
        }

        @Override
        public void run() {
            try {
                T obj = _pool.borrowObject(_key);
                _pool.returnObject(_key, obj);
            } catch (Exception e) {
                // Ignore
            }
        }
    }

    /*
     * Very simple test thread that just tries to borrow an object from
     * the provided pool with the specified key and returns it after a wait
     */
    static class WaitingTestThread extends Thread {
        private final KeyedObjectPool<String,String> _pool;
        private final String _key;
        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(KeyedObjectPool<String,String> pool, String key, long pause) {
            _pool = pool;
            _key = key;
            _pause = pause;
            _thrown = null;
        }

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

    static class TestThread<T> implements Runnable {
        private final java.util.Random _random = new java.util.Random();

        /** GKOP to hit */
        private final KeyedObjectPool<String,T> _pool;
        /** number of borrow/return iterations */
        private final int _iter;
        /** delay before borrow */
        private final int _startDelay;
        /** delay before return */
        private final int _holdTime;
        /** whether or not delays are random (with max = configured values) */
        private final boolean _randomDelay;
        /** expected object */
        private final T _expectedObject;
        /** key used in borrow / return sequence - null means random */
        private final String _key;

        private volatile boolean _complete = false;
        private volatile boolean _failed = false;
        private volatile Exception _exception;

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

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

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

        public TestThread(KeyedObjectPool<String,T> pool, int iter, int startDelay,
            int holdTime, boolean randomDelay, T expectedObject, String key) {
            _pool = pool;
            _iter = iter;
            _startDelay = startDelay;
            _holdTime = holdTime;
            _randomDelay = randomDelay;
            _expectedObject = expectedObject;
            _key = key;

        }

        public boolean complete() {
            return _complete;
        }

        public boolean failed() {
            return _failed;
        }

        @Override
        public void run() {
            for(int i=0;i<_iter;i++) {
                String key = _key == null ? String.valueOf(_random.nextInt(3)) : _key;
                try {
                    Thread.sleep(_randomDelay ? _random.nextInt(_startDelay) : _startDelay);
                } catch(InterruptedException e) {
                    // ignored
                }
                T obj = null;
                try {
                    obj = _pool.borrowObject(key);
                } catch(Exception e) {
                    _exception = e;
                    _failed = true;
                    _complete = true;
                    break;
                }

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

                try {
                    Thread.sleep(_randomDelay ? _random.nextInt(_holdTime) : _holdTime);
                } catch(InterruptedException e) {
                    // ignored
                }
                try {
                    _pool.returnObject(key,obj);
                } catch(Exception e) {
                    _exception = e;
                    _failed = true;
                    _complete = true;
                    break;
                }
            }
            _complete = true;
        }
    }

    static class SimpleFactory<K> implements KeyedPooledObjectFactory<K,String> {
        public SimpleFactory() {
            this(true);
        }
        public SimpleFactory(boolean valid) {
            this.valid = valid;
        }
        @Override
        public PooledObject<String> makeObject(K key) throws Exception {
            if (exceptionOnCreate) {
                throw new Exception();
            }
            doWait(makeLatency);
            String out = null;
            synchronized(this) {
                activeCount++;
                if (activeCount > maxTotalPerKey) {
                    throw new IllegalStateException(
                        "Too many active instances: " + activeCount);
                }
                out = String.valueOf(key) + String.valueOf(counter++);
            }
            return new DefaultPooledObject<String>(out);
        }
        @Override
        public void destroyObject(K key, PooledObject<String> obj) throws Exception {
            doWait(destroyLatency);
            synchronized(this) {
                activeCount--;
            }
            if (exceptionOnDestroy) {
                throw new Exception();
            }
        }
        @Override
        public boolean validateObject(K key, PooledObject<String> obj) {
            if (enableValidation) {
                return validateCounter++%2 == 0 ? evenValid : oddValid;
            } else {
                return valid;
            }
        }
        @Override
        public void activateObject(K key, PooledObject<String> obj) throws Exception {
            if (exceptionOnActivate) {
                if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) {
                    throw new Exception();
                }
            }
        }
        @Override
        public void passivateObject(K key, PooledObject<String> obj) throws Exception {
            if (exceptionOnPassivate) {
                throw new Exception();
            }
        }

        public void setMaxTotalPerKey(int maxTotalPerKey) {
            this.maxTotalPerKey = maxTotalPerKey;
        }
        public void setDestroyLatency(long destroyLatency) {
            this.destroyLatency = destroyLatency;
        }
        public void setMakeLatency(long makeLatency) {
            this.makeLatency = makeLatency;
        }
        public void setValidationEnabled(boolean b) {
            enableValidation = b;
        }
        void setEvenValid(boolean valid) {
            evenValid = valid;
        }
        void setValid(boolean valid) {
            evenValid = valid;
            oddValid = valid;
        }

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

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

        public void setThrowExceptionOnPassivate(boolean b) {
            exceptionOnPassivate = b;
        }

        volatile int counter = 0;
        boolean valid;

        int activeCount = 0;
        int validateCounter = 0;
        boolean evenValid = true;
        boolean oddValid = true;
        boolean enableValidation = false;
        long destroyLatency = 0;
        long makeLatency = 0;
        volatile int maxTotalPerKey = Integer.MAX_VALUE;
        boolean exceptionOnPassivate = false;
        boolean exceptionOnActivate = false;
        boolean exceptionOnDestroy = false;
        boolean exceptionOnCreate = false;

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

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

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

    private String getExceptionTrace(Throwable t){
        StringWriter sw = new StringWriter();
        t.printStackTrace(new PrintWriter(sw));
        return sw.toString();
    }

    private String formatSettings(String title, String s, int i, String s0, boolean b0, String s1, int i1, String s2, int i2, String s3, int i3,
            String s4, int i4, String s5, int i5, String s6, int i6, int zeroLength, int oneLength, int twoLength){
        StringBuilder sb = new StringBuilder(80);
        sb.append(title).append(' ');
        sb.append(s).append('=').append(i).append(' ');
        sb.append(s0).append('=').append(b0).append(' ');
        sb.append(s1).append('=').append(i1).append(' ');
        sb.append(s2).append('=').append(i2).append(' ');
        sb.append(s3).append('=').append(i3).append(' ');
        sb.append(s4).append('=').append(i4).append(' ');
        sb.append(s5).append('=').append(i5).append(' ');
        sb.append(s6).append('=').append(i6).append(' ');
        sb.append("Lengths=").append(zeroLength).append(',').append(oneLength).append(',').append(twoLength).append(' ');
        return sb.toString();
    }

    /**
     * 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());
    }

    /**
     * Verify that threads blocked waiting on a depleted pool get served when a checked out instance
     * is invalidated.
     *
     * JIRA: POOL-240
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testInvalidateWaiting()
        throws Exception {

        GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
        config.setMaxTotal(2);
        config.setBlockWhenExhausted(true);
        config.setMinIdlePerKey(0);
        config.setMaxWaitMillis(-1);
        config.setNumTestsPerEvictionRun(Integer.MAX_VALUE); // always test all idle objects
        config.setTestOnBorrow(true);
        config.setTestOnReturn(false);
        config.setTestWhileIdle(true);
        config.setTimeBetweenEvictionRunsMillis(-1);

        final GenericKeyedObjectPool<Integer, Object> pool =
                new GenericKeyedObjectPool<Integer, Object>(
                        new ObjectFactory(), config);

        // Allocate both objects with this thread
        pool.borrowObject(Integer.valueOf(1)); // object1
        Object object2 = pool.borrowObject(Integer.valueOf(1));

        // Cause a thread to block waiting for an object
        ExecutorService executorService =
                Executors.newSingleThreadExecutor(new DaemonThreadFactory());
        final Semaphore signal = new Semaphore(0);
        Future<Exception> result = executorService.submit(new Callable<Exception>() {

            @Override
            public Exception call() {
                try {
                    signal.release();
                    Object object3 = pool.borrowObject(Integer.valueOf(1));
                    pool.returnObject(Integer.valueOf(1), object3);
                    signal.release();
                } catch (Exception e) {
                    return e;
                } catch (Throwable e) {
                    return new Exception(e);
                }

                return null;
            }
        });

        // Wait for the thread to start
        assertTrue(signal.tryAcquire(5, TimeUnit.SECONDS));

        // Attempt to ensure that test thread is blocked waiting for an object
        Thread.sleep(500);

        pool.invalidateObject(Integer.valueOf(1), object2);

        assertTrue("Call to invalidateObject did not unblock pool waiters.",
                   signal.tryAcquire(2, TimeUnit.SECONDS));

        if (result.get() != null) {
            throw new AssertionError(result.get());
        }
    }


    private static class DaemonThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setDaemon(true);
            return t;
        }
    }


    /**
     * 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<String> factory = new SimpleFactory<String>();
        GenericKeyedObjectPool<String, String> pool = new GenericKeyedObjectPool<String, String>(factory);
        pool.setMaxTotalPerKey(2);
        pool.setMaxWaitMillis(500);
        // Borrow an instance and hold if for 5 seconds
        WaitingTestThread thread1 = new WaitingTestThread(pool, "one", 5000);
        thread1.start();
        // Borrow another instance
        String obj = pool.borrowObject("one");
        // Launch another thread - will block, but fail in 500 ms
        WaitingTestThread thread2 = new WaitingTestThread(pool, "one", 100);
        thread2.start();
        // Invalidate the object borrowed by this thread - should allow thread2 to create
        Thread.sleep(20);
        pool.invalidateObject("one", 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<String> factory = new SimpleFactory<String>();
        factory.setValid(false); // Validate will always fail
        factory.setValidationEnabled(true);
        GenericKeyedObjectPool<String, String> pool = new GenericKeyedObjectPool<String, String>(factory);
        pool.setMaxTotalPerKey(2);
        pool.setMaxWaitMillis(1500);
        pool.setTestOnReturn(true);
        pool.setTestOnBorrow(false);
        // Borrow an instance and hold if for 5 seconds
        WaitingTestThread thread1 = new WaitingTestThread(pool,"one", 5000);
        thread1.start();
        // Borrow another instance and return it after 500 ms (validation will fail)
        WaitingTestThread thread2 = new WaitingTestThread(pool,"one", 500);
        thread2.start();
        Thread.sleep(50);
        // Try to borrow an object
        String obj = pool.borrowObject("one");
        pool.returnObject("one", obj);
    }

    /**
     * Verify that factory exceptions creating objects do not corrupt per key create count.
     *
     * JIRA: POOL-243
     *
     * @throws Exception May occur in some failure modes
     */
    @Test
    public void testMakeObjectException()
        throws Exception {
        SimpleFactory<String> factory = new SimpleFactory<String>();
        GenericKeyedObjectPool<String, String> pool = new GenericKeyedObjectPool<String, String>(factory);
        pool.setMaxTotalPerKey(1);
        pool.setBlockWhenExhausted(false);
        factory.exceptionOnCreate = true;
        try {
            pool.borrowObject("One");
        } catch (Exception ex) {
            // expected
        }
        factory.exceptionOnCreate = false;
        pool.borrowObject("One");
    }

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

    private static class SimplePerKeyFactory
            extends BaseKeyedPooledObjectFactory<Object,Object> {
        ConcurrentHashMap<Object,AtomicInteger> map =
                new ConcurrentHashMap<Object,AtomicInteger>();
        @Override
        public Object create(Object key) throws Exception {
            int counter = 0;
            AtomicInteger Counter = map.get(key);
            if(null != Counter) {
                counter = Counter.incrementAndGet();
            } else {
                map.put(key, new AtomicInteger(0));
                counter = 0;
            }
            return String.valueOf(key) + String.valueOf(counter);
        }
        @Override
        public PooledObject<Object> wrap(Object value) {
            return new DefaultPooledObject<Object>(value);
        }
    }

    private static class ObjectFactory
        extends BaseKeyedPooledObjectFactory<Integer, Object> {

        @Override
        public Object create(Integer key)
            throws Exception {
            return new Object();
        }

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


