Package org.apache.commons.pool.impl

Source Code of org.apache.commons.pool.impl.TestGenericKeyedObjectPool

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

import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.apache.commons.pool.TestBaseKeyedObjectPool;
import org.apache.commons.pool.VisitTracker;
import org.apache.commons.pool.VisitTrackerFactory;

import java.util.HashMap;
import java.util.NoSuchElementException;
import java.util.Random;

/**
* @author Rodney Waldhoff
* @version $Revision: 606718 $ $Date: 2007-12-24 10:55:10 -0700 (Mon, 24 Dec 2007) $
*/
public class TestGenericKeyedObjectPool extends TestBaseKeyedObjectPool {
    public TestGenericKeyedObjectPool(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(TestGenericKeyedObjectPool.class);
    }

    protected KeyedObjectPool makeEmptyPool(int mincapacity) {
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(
            new KeyedPoolableObjectFactory()  {
                HashMap map = new HashMap();
                public Object makeObject(Object key) {
                    int counter = 0;
                    Integer Counter = (Integer)(map.get(key));
                    if(null != Counter) {
                        counter = Counter.intValue();
                    }
                    map.put(key,new Integer(counter + 1));
                    return String.valueOf(key) + String.valueOf(counter);
                }
                public void destroyObject(Object key, Object obj) { }
                public boolean validateObject(Object key, Object obj) { return true; }
                public void activateObject(Object key, Object obj) { }
                public void passivateObject(Object key, Object obj) { }
            }
        );
        pool.setMaxActive(mincapacity);
        pool.setMaxIdle(mincapacity);
        return pool;
    }

    protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) {
        return new GenericKeyedObjectPool(factory);
    }

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

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

    private GenericKeyedObjectPool pool = null;
    private Integer zero = new Integer(0);
    private Integer one = new Integer(1);
    private Integer two = new Integer(2);

    public void setUp() throws Exception {
        super.setUp();
        pool = new GenericKeyedObjectPool(new SimpleFactory());
    }

    public void tearDown() throws Exception {
        super.tearDown();
        pool.close();
        pool = null;
    }

    public void testNegativeMaxActive() throws Exception {
        pool.setMaxActive(-1);
        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
        Object obj = pool.borrowObject("");
        assertEquals("0",obj);
        pool.returnObject("",obj);
    }

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

        Object objA0 = pool.borrowObject("A");
        Object 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"));

        Object objA1 = pool.borrowObject("A");
        Object 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"));
    }

    public void testMaxIdle() throws Exception {
        pool.setMaxActive(100);
        pool.setMaxIdle(8);
        Object[] active = new Object[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"));
            
    }

    public void testMaxActive() throws Exception {
        pool.setMaxActive(3);
        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);

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

    public void testMaxActiveZero() throws Exception {
        pool.setMaxActive(0);
        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);

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

    public void testMaxTotal() throws Exception {
        pool.setMaxActive(2);
        pool.setMaxTotal(3);
        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);

        Object o1 = pool.borrowObject("a");
        assertNotNull(o1);
        Object o2 = pool.borrowObject("a");
        assertNotNull(o2);
        Object 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());
    }

    public void testMaxTotalZero() throws Exception {
        pool.setMaxTotal(0);
        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);

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

    public void testMaxTotalLRU() throws Exception {
        pool.setMaxActive(2);
        pool.setMaxTotal(3);
//        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW);

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

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

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

        Object 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
        Object 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)
        Object o6 = pool.borrowObject("b");
        assertNotNull(o6);
        pool.returnObject("b", o6);

        assertNotSame(o1, o6);

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

        assertSame(o4, o7);
    }

    public void testSettersAndGetters() throws Exception {
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool();
        {
            pool.setFactory(new SimpleFactory());
        }
        {
            pool.setMaxActive(123);
            assertEquals(123,pool.getMaxActive());
        }
        {
            pool.setMaxIdle(12);
            assertEquals(12,pool.getMaxIdle());
        }
        {
            pool.setMaxWait(1234L);
            assertEquals(1234L,pool.getMaxWait());
        }
        {
            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.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK);
            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction());
            pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction());
            pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW);
            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction());
        }
    }

    public void testEviction() throws Exception {
        pool.setMaxIdle(500);
        pool.setMaxActive(500);
        pool.setNumTestsPerEvictionRun(100);
        pool.setMinEvictableIdleTimeMillis(250L);
        pool.setTimeBetweenEvictionRunsMillis(500L);

        Object[] active = new Object[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(Exception e) { }
        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100);
        try { Thread.sleep(600L); } catch(Exception 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(Exception e) { }
        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle(""));
    }

    public void testEviction2() throws Exception {
        pool.setMaxIdle(500);
        pool.setMaxActive(500);
        pool.setNumTestsPerEvictionRun(100);
        pool.setMinEvictableIdleTimeMillis(500L);
        pool.setTimeBetweenEvictionRunsMillis(500L);

        Object[] active = new Object[500];
        Object[] active2 = new Object[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(1000L); } catch(Exception e) { }
        assertTrue("Should be less than 1000 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 1000);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 900 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 900);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 800 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 800);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 700 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 700);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 600 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 600);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
        try { Thread.sleep(600L); } catch(Exception e) { }
        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
    }

    /**
     * Kicks off <numThreads> test threads, each of which will go through
     * <iterations> borrow-return cycles with random delay times <= delay
     * in between.
     */
    public void runTestThreads(int numThreads, int iterations, int delay) {
        TestThread[] threads = new TestThread[numThreads];
        for(int i=0;i<numThreads;i++) {
            threads[i] = new TestThread(pool,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(Exception e) {
                    // ignored
                }
            }
            if(threads[i].failed()) {
                fail();
            }
        }
    }
   
    public void testThreaded1() throws Exception {
        pool.setMaxActive(15);
        pool.setMaxIdle(15);
        pool.setMaxWait(1000L);
        runTestThreads(20, 100, 50);
    }
   
    /**
     * Verifies that maxTotal is not exceeded when factory destroyObject
     * has high latency, testOnReturn is set and there is high incidence of
     * validation failures.
     */
    public void testMaxTotalInvariant() throws Exception {
        int maxTotal = 15;
        SimpleFactory factory = new SimpleFactory();
        factory.setEvenValid(false);     // Every other validation fails
        factory.setDestroyLatency(100)// Destroy takes 100 ms
        factory.setMaxActive(maxTotal)// (makes - destroys) bound
        factory.setValidationEnabled(true);
        pool = new GenericKeyedObjectPool(factory);
        pool.setMaxTotal(maxTotal);
        pool.setMaxIdle(-1);
        pool.setTestOnReturn(true);
        pool.setMaxWait(10000L);
        runTestThreads(5, 10, 50);
    }

    public void testMinIdle() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxActive(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);


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

        pool.preparePool(key, true);

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

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

        try { Thread.sleep(150L); } catch(Exception 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(Exception 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(Exception e) { }
        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
    }

    public void testMinIdleMaxActive() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxActive(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(100L);
        pool.setTestWhileIdle(true);

        String key = "A";

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

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

        Object[] active = new Object[10];

        try { Thread.sleep(150L); } catch(Exception 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(Exception 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(Exception 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(Exception 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(Exception e) { }
        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
    }

    public void testMinIdleNoPopulateImmediately() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxActive(10);
        pool.setNumTestsPerEvictionRun(0);
        pool.setMinEvictableIdleTimeMillis(50L);
        pool.setTimeBetweenEvictionRunsMillis(1000L);
        pool.setTestWhileIdle(true);


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

        pool.preparePool(key, false);

        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);

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

    public void testMinIdleNoPreparePool() throws Exception {
        pool.setMaxIdle(500);
        pool.setMinIdle(5);
        pool.setMaxActive(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(Exception e) { }
        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);

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

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

    public void testFIFO() throws Exception {
        pool.setLifo(false);
        final Object 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));
        assertEquals("new-3", "key3", pool.borrowObject(key));
        pool.returnObject(key, "r");
        assertEquals("returned", "r", pool.borrowObject(key));
        assertEquals("new-4", "key4", pool.borrowObject(key));
    }
   
    public void testLIFO() throws Exception {
        pool.setLifo(true);
        final Object 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));
        assertEquals("new-3", "key3", pool.borrowObject(key));
        pool.returnObject(key, "r");
        assertEquals("returned", "r", 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
     */
    public void testEvictionOrder() throws Exception {
        checkEvictionOrder(false);
        checkEvictionOrder(true);
    }
   
    private void checkEvictionOrder(boolean lifo) throws Exception {
        SimpleFactory factory = new SimpleFactory();
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory);
        pool.setNumTestsPerEvictionRun(2);
        pool.setMinEvictableIdleTimeMillis(100);
        pool.setLifo(lifo);
       
        for (int i = 0; i < 3; i ++) {
            Integer key = new Integer(i);
            for (int j = 0; j < 5; j++) {
                pool.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)
         */
       
        pool.evict(); // Kill (0,0),(0,1)
        assertEquals(3, pool.getNumIdle(zero));
        Object obj = pool.borrowObject(zero);
        assertTrue(lifo ? obj.equals("04") : obj.equals("02"));
        assertEquals(2, pool.getNumIdle(zero));
        obj = pool.borrowObject(zero);
        assertTrue(obj.equals("03"));
        assertEquals(1, pool.getNumIdle(zero));
       
        pool.evict(); // Kill remaining 0 survivor and (1,5)
        assertEquals(0, pool.getNumIdle(zero));
        assertEquals(4, pool.getNumIdle(one));
        obj = pool.borrowObject(one);
        assertTrue(lifo ? obj.equals("19") : obj.equals("16"));
        assertEquals(3, pool.getNumIdle(one));
        obj = pool.borrowObject(one);
        assertTrue(lifo ? obj.equals("18") : obj.equals("17"));
        assertEquals(2, pool.getNumIdle(one));
       
        pool.evict(); // Kill remaining 1 survivors
        assertEquals(0, pool.getNumIdle(one));
        pool.evict(); // Kill (2,10), (2,11)
        assertEquals(3, pool.getNumIdle(two));
        obj = pool.borrowObject(two);
        assertTrue(lifo ? obj.equals("214") : obj.equals("212"));
        assertEquals(2, pool.getNumIdle(two));
        pool.evict(); // All dead now
        assertEquals(0, pool.getNumIdle(two))
       
        pool.evict(); // Should do nothing - make sure no exception
        pool.evict();
       
        // Reload
        pool.setMinEvictableIdleTimeMillis(500);
        factory.counter = 0; // Reset counter
        for (int i = 0; i < 3; i ++) {
            Integer key = new Integer(i);
            for (int j = 0; j < 5; j++) {
                pool.addObject(key);
            }
            Thread.sleep(200);
        }
       
        // 0's are evictable, others not
        pool.evict(); // Kill (0,0),(0,1)
        assertEquals(3, pool.getNumIdle(zero));
        pool.evict(); // Kill (0,2),(0,3)
        assertEquals(1, pool.getNumIdle(zero));
        pool.evict(); // Kill (0,4), leave (1,5)
        assertEquals(0, pool.getNumIdle(zero));
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        pool.evict(); // (1,6), (1,7)
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        pool.evict(); // (1,8), (1,9)
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        pool.evict(); // (2,10), (2,11)
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        pool.evict(); // (2,12), (2,13)
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        pool.evict(); // (2,14), (1,5)
        assertEquals(5, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        Thread.sleep(200); // Ones now timed out
        pool.evict(); // kill (1,6), (1,7) - (1,5) missed
        assertEquals(3, pool.getNumIdle(one));
        assertEquals(5, pool.getNumIdle(two));
        obj = pool.borrowObject(one);
        assertTrue(lifo ? obj.equals("19") : obj.equals("15"))
    }
   
   
    /**
     * Verifies that the evictor visits objects in expected order
     * and frequency.
     */
    public void testEvictorVisiting() throws Exception {
        checkEvictorVisiting(true);
        checkEvictorVisiting(false)
    }
   
    private void checkEvictorVisiting(boolean lifo) throws Exception {
        VisitTrackerFactory factory = new VisitTrackerFactory();
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory);
        pool.setNumTestsPerEvictionRun(2);
        pool.setMinEvictableIdleTimeMillis(-1);
        pool.setTestWhileIdle(true);
        pool.setLifo(lifo);
        pool.setTestOnReturn(false);
        pool.setTestOnBorrow(false);
        for (int i = 0; i < 3; i ++) {
            factory.resetId();
            Integer key = new Integer(i);
            for (int j = 0; j < 8; j++) {
                pool.addObject(key);
            }
        }
        pool.evict(); // Visit oldest 2 - 00 and 01
        Object obj = pool.borrowObject(zero);
        pool.returnObject(zero, obj);
        obj = pool.borrowObject(zero);
        pool.returnObject(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
        pool.evict()// Should visit 02 and 03 in either case
        for (int i = 0; i < 8; i++) {
            VisitTracker tracker = (VisitTracker) pool.borrowObject(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
       
        pool.setNumTestsPerEvictionRun(3);
       
        pool.evict(); // 10, 11, 12
        pool.evict(); // 13, 14, 15
       
        obj = pool.borrowObject(one);
        pool.returnObject(one, obj);
        obj = pool.borrowObject(one);
        pool.returnObject(one, obj);
        obj = pool.borrowObject(one);
        pool.returnObject(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
        pool.evict();
        // LIFO - 16, 17, 20
        // FIFO - 16, 17, 10
        pool.evict();
        // LIFO - 21, 22, 23
        // FIFO - 11, 12, 20
        pool.evict();
        // LIFO - 24, 25, 26
        // FIFO - 21, 22, 23
        pool.evict();
        // LIFO - 27, skip, 10
        // FIFO - 24, 25, 26
        for (int i = 0; i < 8; i++) {
            VisitTracker tracker = (VisitTracker) pool.borrowObject(one);   
            if ((lifo && tracker.getId() > 0) ||
                    (!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());
            }
        }
       
        // 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());
        pool.setMaxIdle(-1);
        for (int i = 0; i < 4; i++) {
            pool.setNumTestsPerEvictionRun(smallPrimes[i]);
            for (int j = 0; j < 5; j++) {
                pool.clear();
                int zeroLength = 10 + random.nextInt(20);
                for (int k = 0; k < zeroLength; k++) {
                    pool.addObject(zero);
                }
                int oneLength = 10 + random.nextInt(20);
                for (int k = 0; k < oneLength; k++) {
                    pool.addObject(one);
                }
                int twoLength = 10 + random.nextInt(20);
                for (int k = 0; k < twoLength; k++) {
                    pool.addObject(two);
                }
               
                // Choose a random number of evictor runs
                int runs = 10 + random.nextInt(50);
                for (int k = 0; k < runs; k++) {
                    pool.evict();
                }
               
                // Total instances in pool
                int totalInstances = zeroLength + oneLength + twoLength;
               
                // Number of times evictor should have cycled through pools
                int cycleCount = (runs * pool.getNumTestsPerEvictionRun())
                    / totalInstances;
               
                // Look at elements and make sure they are visited cycleCount
                // or cycleCount + 1 times
                VisitTracker tracker = null;
                int visitCount = 0;
                for (int k = 0; k < zeroLength; k++) {
                    tracker = (VisitTracker) pool.borrowObject(zero);
                    visitCount = tracker.getValidateCount();                 
                    assertTrue(visitCount >= cycleCount &&
                            visitCount <= cycleCount + 1);
                }
                for (int k = 0; k < oneLength; k++) {
                    tracker = (VisitTracker) pool.borrowObject(one);
                    visitCount = tracker.getValidateCount();
                    assertTrue(visitCount >= cycleCount &&
                            visitCount <= cycleCount + 1);
                }
                for (int k = 0; k < twoLength; k++) {
                    tracker = (VisitTracker) pool.borrowObject(two);
                    visitCount = tracker.getValidateCount();
                    assertTrue(visitCount >= cycleCount &&
                            visitCount <= cycleCount + 1);
                }
            }
        }
    }
   
    public void testConstructors() {
       
        // Make constructor arguments all different from defaults
        int maxActive = 1;
        int maxIdle = 2;
        long maxWait = 3;
        int minIdle = 4;
        int maxTotal = 5;
        long minEvictableIdleTimeMillis = 6;
        int numTestsPerEvictionRun = 7;
        boolean testOnBorrow = true;
        boolean testOnReturn = true;
        boolean testWhileIdle = true;
        long timeBetweenEvictionRunsMillis = 8;
        byte whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
        boolean lifo = false;
       
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool();
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE, pool.getMaxActive());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,
                pool.getTestOnBorrow());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,
                pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
                pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        GenericKeyedObjectPool.Config config = new GenericKeyedObjectPool.Config();
        config.lifo = lifo;
        config.maxActive = maxActive;
        config.maxIdle = maxIdle;
        config.minIdle = minIdle;
        config.maxTotal = maxTotal;
        config.maxWait = maxWait;
        config.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
        config.numTestsPerEvictionRun = numTestsPerEvictionRun;
        config.testOnBorrow = testOnBorrow;
        config.testOnReturn = testOnReturn;
        config.testWhileIdle = testWhileIdle;
        config.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        config.whenExhaustedAction = whenExhaustedAction;
        pool = new GenericKeyedObjectPool(null, config);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(minIdle, pool.getMinIdle());
        assertEquals(maxTotal, pool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow,pool.getTestOnBorrow());
        assertEquals(testOnReturn,pool.getTestOnReturn());
        assertEquals(testWhileIdle,pool.getTestWhileIdle());
        assertEquals(timeBetweenEvictionRunsMillis,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(lifo, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,
                pool.getTestOnBorrow());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,
                pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
                pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,
                pool.getTestOnBorrow());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,
                pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                   maxWait, testOnBorrow, testOnReturn);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow,pool.getTestOnBorrow());
        assertEquals(testOnReturn,pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,
                pool.getTestOnBorrow());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,
                pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());

        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle, testOnBorrow, testOnReturn);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow, pool.getTestOnBorrow());
        assertEquals(testOnReturn, pool.getTestOnReturn());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE,
                pool.getTestWhileIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());

        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle, testOnBorrow, testOnReturn,
                timeBetweenEvictionRunsMillis, numTestsPerEvictionRun,
                minEvictableIdleTimeMillis, testWhileIdle);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow, pool.getTestOnBorrow());
        assertEquals(testOnReturn, pool.getTestOnReturn());
        assertEquals(testWhileIdle,
                pool.getTestWhileIdle());
        assertEquals(timeBetweenEvictionRunsMillis,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle, maxTotal, testOnBorrow, testOnReturn,
                timeBetweenEvictionRunsMillis, numTestsPerEvictionRun,
                minEvictableIdleTimeMillis, testWhileIdle);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle());
        assertEquals(maxTotal, pool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow, pool.getTestOnBorrow());
        assertEquals(testOnReturn, pool.getTestOnReturn());
        assertEquals(testWhileIdle,
                pool.getTestWhileIdle());
        assertEquals(timeBetweenEvictionRunsMillis,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn,
                timeBetweenEvictionRunsMillis, numTestsPerEvictionRun,
                minEvictableIdleTimeMillis, testWhileIdle);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(minIdle, pool.getMinIdle());
        assertEquals(maxTotal, pool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow, pool.getTestOnBorrow());
        assertEquals(testOnReturn, pool.getTestOnReturn());
        assertEquals(testWhileIdle,
                pool.getTestWhileIdle());
        assertEquals(timeBetweenEvictionRunsMillis,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo());
       
        pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction,
                maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn,
                timeBetweenEvictionRunsMillis, numTestsPerEvictionRun,
                minEvictableIdleTimeMillis, testWhileIdle, lifo);
        assertEquals(maxActive, pool.getMaxActive());
        assertEquals(maxIdle, pool.getMaxIdle());
        assertEquals(maxWait, pool.getMaxWait());
        assertEquals(minIdle, pool.getMinIdle());
        assertEquals(maxTotal, pool.getMaxTotal());
        assertEquals(minEvictableIdleTimeMillis,
                pool.getMinEvictableIdleTimeMillis());
        assertEquals(numTestsPerEvictionRun,
                pool.getNumTestsPerEvictionRun());
        assertEquals(testOnBorrow, pool.getTestOnBorrow());
        assertEquals(testOnReturn, pool.getTestOnReturn());
        assertEquals(testWhileIdle,
                pool.getTestWhileIdle());
        assertEquals(timeBetweenEvictionRunsMillis,
                pool.getTimeBetweenEvictionRunsMillis());
        assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction());
        assertEquals(lifo, pool.getLifo())
    }

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

        public TestThread(KeyedObjectPool pool) {
            _pool = pool;
        }

        public TestThread(KeyedObjectPool pool, int iter) {
            _pool = pool;
            _iter = iter;
        }

        public TestThread(KeyedObjectPool pool, int iter, int delay) {
            _pool = pool;
            _iter = iter;
            _delay = delay;
        }

        public boolean complete() {
            return _complete;
        }

        public boolean failed() {
            return _failed;
        }

        public void run() {
            for(int i=0;i<_iter;i++) {
                String key = String.valueOf(_random.nextInt(3));
                try {
                    Thread.sleep((long)_random.nextInt(_delay));
                } catch(Exception e) {
                    // ignored
                }
                Object obj = null;
                try {
                    obj = _pool.borrowObject(key);
                } catch(Exception e) {
                    e.printStackTrace();
                    _failed = true;
                    _complete = true;
                    break;
                }

                try {
                    Thread.sleep((long)_random.nextInt(_delay));
                } catch(Exception e) {
                    // ignored
                }
                try {
                    _pool.returnObject(key,obj);
                } catch(Exception e) {
                    e.printStackTrace();
                    _failed = true;
                    _complete = true;
                    break;
                }
            }
            _complete = true;
        }
    }

    static class SimpleFactory implements KeyedPoolableObjectFactory {
        public SimpleFactory() {
            this(true);
        }
        public SimpleFactory(boolean valid) {
            this.valid = valid;
        }
        public Object makeObject(Object key) {
            synchronized(this) {
                activeCount++;
                if (activeCount > maxActive) {
                    throw new IllegalStateException(
                        "Too many active instances: " + activeCount);
                }
            }
            return String.valueOf(key) + String.valueOf(counter++);
        }
        public void destroyObject(Object key, Object obj) {
            doWait(destroyLatency);
            synchronized(this) {
                activeCount--;
            }
        }
        public boolean validateObject(Object key, Object obj) {
            if (enableValidation) {
                return validateCounter++%2 == 0 ? evenValid : oddValid;
            } else {
                return valid;
            }
        }
        public void activateObject(Object key, Object obj) { }
        public void passivateObject(Object key, Object obj) { }
       
        public void setMaxActive(int maxActive) {
            this.maxActive = maxActive;
        }
        public void setDestroyLatency(long destroyLatency) {
            this.destroyLatency = destroyLatency;
        }
        public void setValidationEnabled(boolean b) {
            enableValidation = b;
        }
        void setEvenValid(boolean valid) {
            evenValid = valid;
        }
       
        int counter = 0;
        boolean valid;
       
        int activeCount = 0;
        int validateCounter = 0;
        boolean evenValid = true;
        boolean oddValid = true;
        boolean enableValidation = false;
        long destroyLatency = 0;
        int maxActive = Integer.MAX_VALUE;
       
        private void doWait(long latency) {
            try {
                Thread.sleep(latency);
            } catch (InterruptedException ex) {
                // ignore
            }
        }
    }

    protected boolean isLifo() {
        return true;
    }

    protected boolean isFifo() {
        return false;
    }

}

TOP

Related Classes of org.apache.commons.pool.impl.TestGenericKeyedObjectPool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.