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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimerTask;

import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.TestGenericKeyedObjectPool;
import org.junit.Assert;
import org.junit.Test;

import junit.framework.AssertionFailedError;

/**
 * Unit tests for {@link PoolUtils}.
 *
 * TODO Replace our own mocking with a mocking library like Mockito.
 */
public class TestPoolUtils {

    /** Period between checks for minIdle tests. Increase this if you happen to get too many false failures. */
    private static final int CHECK_PERIOD = 300;

    /** Times to let the minIdle check run. */
    private static final int CHECK_COUNT = 4;

    /** Sleep time to let the minIdle tests run CHECK_COUNT times. */
    private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT - 1) + CHECK_PERIOD / 2;

    @Test
    public void testCheckRethrow() {
        try {
            PoolUtils.checkRethrow(new Exception());
        } catch (final Throwable t) {
            fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError.");
        }
        try {
            PoolUtils.checkRethrow(new ThreadDeath());
            fail("PoolUtils.checkRethrow(Throwable) must rethrow ThreadDeath.");
        } catch (final ThreadDeath td) {
            // expected
        } catch (final Throwable t) {
            fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError.");
        }
        try {
            PoolUtils.checkRethrow(new InternalError()); // InternalError extends VirtualMachineError
            fail("PoolUtils.checkRethrow(Throwable) must rethrow VirtualMachineError.");
        } catch (final VirtualMachineError td) {
            // expected
        } catch (final Throwable t) {
            fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError.");
        }
    }

    @Test
    public void testJavaBeanInstantiation() {
        Assert.assertNotNull(new PoolUtils());
    }

    @Test
    public void testCheckMinIdleObjectPool() throws Exception {
        try {
            PoolUtils.checkMinIdle(null, 1, 1);
            fail("PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }
        try (@SuppressWarnings("unchecked")
            final ObjectPool<Object> pool = createProxy(ObjectPool.class, (List<String>) null)) {
            PoolUtils.checkMinIdle(pool, -1, 1);
            fail("PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();

        // Test that the minIdle check doesn't add too many idle objects
        @SuppressWarnings("unchecked")
        final PooledObjectFactory<Object> pof = createProxy(PooledObjectFactory.class, calledMethods);
        try (final ObjectPool<Object> op = new GenericObjectPool<>(pof)) {
            PoolUtils.checkMinIdle(op, 2, 100);
            Thread.sleep(1000);
            assertEquals(2, op.getNumIdle());
        }
        int makeObjectCount = 0;
        final Iterator<String> iter = calledMethods.iterator();
        while (iter.hasNext()) {
            final String methodName = iter.next();
            if ("makeObject".equals(methodName)) {
                makeObjectCount++;
            }
        }
        assertEquals("makeObject should have been called two time", 2, makeObjectCount);

        // Because this isn't deterministic and you can get false failures, try more than once.
        AssertionFailedError afe = null;
        int triesLeft = 3;
        do {
            afe = null;
            try {
                calledMethods.clear();
                try (@SuppressWarnings("unchecked")
                    final ObjectPool<Object> pool = createProxy(ObjectPool.class, calledMethods)) {
                    final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately

                    Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
                    task.cancel();
                    task.toString();

                    final List<String> expectedMethods = new ArrayList<>();
                    for (int i = 0; i < CHECK_COUNT; i++) {
                        expectedMethods.add("getNumIdle");
                        expectedMethods.add("addObject");
                    }
                    expectedMethods.add("toString");
                    assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
                }
            } catch (final AssertionFailedError e) {
                afe = e;
            }
        } while (--triesLeft > 0 && afe != null);
        if (afe != null) {
            throw afe;
        }
    }

    @Test
    public void testCheckMinIdleKeyedObjectPool() throws Exception {
        try {
            PoolUtils.checkMinIdle(null, new Object(), 1, 1);
            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object,Object> pool = createProxy(KeyedObjectPool.class, (List<String>)null)) {
            PoolUtils.checkMinIdle(pool, (Object)null, 1, 1);
            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object,Object> pool = createProxy(KeyedObjectPool.class, (List<String>)null)) {
            PoolUtils.checkMinIdle(pool, new Object(), -1, 1);
            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        final Object key = new Object();

        // Test that the minIdle check doesn't add too many idle objects
        @SuppressWarnings("unchecked")
        final KeyedPooledObjectFactory<Object,Object> kpof =
            createProxy(KeyedPooledObjectFactory.class, calledMethods);
        try (final KeyedObjectPool<Object,Object> kop =
                new GenericKeyedObjectPool<>(kpof)) {
            PoolUtils.checkMinIdle(kop, key, 2, 100);
            Thread.sleep(400);
            assertEquals(2, kop.getNumIdle(key));
            assertEquals(2, kop.getNumIdle());
        }
        int makeObjectCount = 0;
        final Iterator<String> iter = calledMethods.iterator();
        while (iter.hasNext()) {
            final String methodName = iter.next();
            if ("makeObject".equals(methodName)) {
                makeObjectCount++;
            }
        }
        assertEquals("makeObject should have been called two time", 2, makeObjectCount);

        // Because this isn't deterministic and you can get false failures, try more than once.
        AssertionFailedError afe = null;
        int triesLeft = 3;
        do {
            afe = null;
            try {
                calledMethods.clear();
                try (@SuppressWarnings("unchecked")
                final KeyedObjectPool<Object, Object> pool = createProxy(KeyedObjectPool.class, calledMethods)) {
                    // checks minIdle immediately
                    final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD);

                    Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
                    task.cancel();
                    task.toString();

                    final List<String> expectedMethods = new ArrayList<>();
                    for (int i = 0; i < CHECK_COUNT; i++) {
                        expectedMethods.add("getNumIdle");
                        expectedMethods.add("addObject");
                    }
                    expectedMethods.add("toString");
                    assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
                }
            } catch (final AssertionFailedError e) {
                afe = e;
            }
        } while (--triesLeft > 0 && afe != null);
        if (afe != null) {
            throw afe;
        }
    }

    @Test
    public void testCheckMinIdleKeyedObjectPoolKeysNulls() throws Exception {
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object,Object> pool = createProxy(KeyedObjectPool.class, (List<String>)null)) {
            PoolUtils.checkMinIdle(pool, (Collection<?>) null, 1, 1);
            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object,Object> pool = createProxy(KeyedObjectPool.class, (List<String>)null)) {
            PoolUtils.checkMinIdle(pool, (Collection<?>) Collections.emptyList(), 1, 1);
        } catch (final IllegalArgumentException iae) {
            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must accept empty lists.");
        }
    }

    @Test
    public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception {
        // Because this isn't deterministic and you can get false failures, try more than once.
        AssertionFailedError afe = null;
        int triesLeft = 3;
        do {
            afe = null;
            final List<String> calledMethods = new ArrayList<>();
            try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<String, Object> pool = createProxy(KeyedObjectPool.class, calledMethods)) {
                final Collection<String> keys = new ArrayList<>(2);
                keys.add("one");
                keys.add("two");
                // checks minIdle immediately
                final Map<String, TimerTask> tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD);

                Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
                for (final TimerTask task : tasks.values()) {
                    task.cancel();
                }

                final List<String> expectedMethods = new ArrayList<>();
                for (int i = 0; i < CHECK_COUNT * keys.size(); i++) {
                    expectedMethods.add("getNumIdle");
                    expectedMethods.add("addObject");
                }
                assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
            } catch (final AssertionFailedError e) {
                afe = e;
            }
        } while (--triesLeft > 0 && afe != null);
        if (afe != null) {
            throw afe;
        }
    }

    @Test
    public void testPrefillObjectPool() throws Exception {
        try {
            PoolUtils.prefill(null, 1);
            fail("PoolUtils.prefill(ObjectPool,int) must not allow null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
            final ObjectPool<Object> pool = createProxy(ObjectPool.class, calledMethods)) {

            PoolUtils.prefill(pool, 0);
            final List<String> expectedMethods = new ArrayList<>();
            expectedMethods.add("addObjects");
            assertEquals(expectedMethods, calledMethods);

            calledMethods.clear();
            PoolUtils.prefill(pool, 3);
            assertEquals(expectedMethods, calledMethods);
        }
    }

    @Test
    public void testPrefillKeyedObjectPool() throws Exception {
        try {
            PoolUtils.prefill(null, new Object(), 1);
            fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }
        try (@SuppressWarnings("unchecked")
        final KeyedObjectPool<Object, String> pool = new GenericKeyedObjectPool<>(new TestGenericKeyedObjectPool.SimpleFactory<>())) {
            PoolUtils.prefill(pool, (Object) null, 1);
            fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object, Object> pool = createProxy(KeyedObjectPool.class, calledMethods)) {

            PoolUtils.prefill(pool, new Object(), 0);
            final List<String> expectedMethods = new ArrayList<>();
            expectedMethods.add("addObjects");
            assertEquals(expectedMethods, calledMethods);

            calledMethods.clear();
            PoolUtils.prefill(pool, new Object(), 3);
            assertEquals(expectedMethods, calledMethods);
        }
    }

    @Test
    public void testPrefillKeyedObjectPoolCollection() throws Exception {
        try (@SuppressWarnings("unchecked")
        final KeyedObjectPool<String, String> pool = createProxy(KeyedObjectPool.class, (List<String>) null)) {
            PoolUtils.prefill(pool, (Collection<String>) null, 1);
            fail("PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<String, Object> pool = createProxy(KeyedObjectPool.class, calledMethods)) {

            final Set<String> keys = new HashSet<>();
            PoolUtils.prefill(pool, keys, 0);
            final List<String> expectedMethods = new ArrayList<>();
            assertEquals(expectedMethods, calledMethods);

            calledMethods.clear();
            keys.add("one");
            keys.add("two");
            keys.add("three");
            final int count = 3;
            PoolUtils.prefill(pool, keys, count);
            for (int i = 0; i < count; i++) {
                expectedMethods.add("addObjects");
            }
            assertEquals(expectedMethods, calledMethods);
        }
    }

    @Test
    public void testSynchronizedPoolObjectPool() throws Exception {
        try {
            PoolUtils.synchronizedPool((ObjectPool<Object>) null);
            fail("PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
            final ObjectPool<Object> op = createProxy(ObjectPool.class, calledMethods)) {

            final ObjectPool<Object> sop = PoolUtils.synchronizedPool(op);
            final List<String> expectedMethods = invokeEveryMethod(sop);
            assertEquals(expectedMethods, calledMethods);

            // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
        }
    }

    @Test
    public void testSynchronizedPoolKeyedObjectPool() throws Exception {
        try {
            PoolUtils.synchronizedPool((KeyedObjectPool<Object, Object>) null);
            fail("PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
            final KeyedObjectPool<Object, Object> kop = createProxy(KeyedObjectPool.class, calledMethods)) {

            final KeyedObjectPool<Object, Object> skop = PoolUtils.synchronizedPool(kop);
            final List<String> expectedMethods = invokeEveryMethod(skop);
            assertEquals(expectedMethods, calledMethods);
        }

        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
    }

    @Test
    public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception {
        try {
            PoolUtils.synchronizedPooledFactory((PooledObjectFactory<Object>)null);
            fail("PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory.");
        } catch(final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        @SuppressWarnings("unchecked")
        final PooledObjectFactory<Object> pof =
                createProxy(PooledObjectFactory.class, calledMethods);

        final PooledObjectFactory<Object> spof = PoolUtils.synchronizedPooledFactory(pof);
        final List<String> expectedMethods = invokeEveryMethod(spof);
        assertEquals(expectedMethods, calledMethods);

        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
    }

    @Test
    public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() throws Exception {
        try {
            PoolUtils.synchronizedKeyedPooledFactory((KeyedPooledObjectFactory<Object,Object>)null);
            fail("PoolUtils.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not allow a null factory.");
        } catch(final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        @SuppressWarnings("unchecked")
        final KeyedPooledObjectFactory<Object,Object> kpof =
                createProxy(KeyedPooledObjectFactory.class, calledMethods);

        final KeyedPooledObjectFactory<Object,Object> skpof = PoolUtils.synchronizedKeyedPooledFactory(kpof);
        final List<String> expectedMethods = invokeEveryMethod(skpof);
        assertEquals(expectedMethods, calledMethods);

        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
    }

    @Test
    public void testErodingPoolObjectPool() throws Exception {
        try {
            PoolUtils.erodingPool((ObjectPool<Object>) null);
            fail("PoolUtils.erodingPool(ObjectPool) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try {
            PoolUtils.erodingPool((ObjectPool<Object>) null, 1f);
            fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        final InvocationHandler handler = new MethodCallLogger(calledMethods) {
            @Override
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                Object o = super.invoke(proxy, method, args);
                if (o instanceof Integer) {
                    // so getNumActive/getNumIdle are not zero.
                    o = Integer.valueOf(1);
                }
                return o;
            }
        };

        try (@SuppressWarnings({ "unchecked" })
            final ObjectPool<?> o = PoolUtils.erodingPool(createProxy(ObjectPool.class, handler), -1f)) {
            fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked.
        final float factor = 0.01f; // about ~9 seconds until first discard
        final List<String> expectedMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
        final ObjectPool<Object> pool = PoolUtils.erodingPool(createProxy(ObjectPool.class, handler), factor)) {

            assertEquals(expectedMethods, calledMethods);

            pool.addObject();
            expectedMethods.add("addObject");

            Object o = pool.borrowObject();
            expectedMethods.add("borrowObject");

            assertEquals(expectedMethods, calledMethods);

            pool.returnObject(o);
            expectedMethods.add("returnObject");
            assertEquals(expectedMethods, calledMethods);

            // the invocation handler always returns 1
            assertEquals(1, pool.getNumActive());
            expectedMethods.add("getNumActive");
            assertEquals(1, pool.getNumIdle());
            expectedMethods.add("getNumIdle");

            for (int i = 0; i < 5; i++) {
                o = pool.borrowObject();
                expectedMethods.add("borrowObject");

                Thread.sleep(50);

                pool.returnObject(o);
                expectedMethods.add("returnObject");

                assertEquals(expectedMethods, calledMethods);

                expectedMethods.clear();
                calledMethods.clear();
            }

            Thread.sleep(10000); // 10 seconds

            o = pool.borrowObject();
            expectedMethods.add("borrowObject");
            pool.returnObject(o);
            expectedMethods.add("getNumIdle");
            expectedMethods.add("invalidateObject");
            pool.clear();
        }
        expectedMethods.add("clear");
        expectedMethods.add("close");
        assertEquals(expectedMethods, calledMethods);
    }

    @Test
    public void testErodingObjectPoolDefaultFactor() {
        try (@SuppressWarnings("unchecked")
            final ObjectPool<Object> internalPool = createProxy(ObjectPool.class, (arg0, arg1, arg2) -> null)) {
            final ObjectPool<Object> pool = PoolUtils.erodingPool(internalPool);
            final String expectedToString = "ErodingObjectPool{factor=ErodingFactor{factor=1.0, idleHighWaterMark=1}, pool="
                    + internalPool + "}";
            // The factor is not exposed, but will be printed in the toString() method
            // In this case since we didn't pass one, the default 1.0f will be printed
            assertEquals(expectedToString, pool.toString());
        }
    }

    @Test
    public void testErodingPoolKeyedObjectPool() throws Exception {
        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null);
            fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null, 1f);
            fail("PoolUtils.erodingPool(KeyedObjectPool, float) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null, 1f, true);
            fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        final InvocationHandler handler = new MethodCallLogger(calledMethods) {
            @Override
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                Object o = super.invoke(proxy, method, args);
                if (o instanceof Integer) {
                    // so getNumActive/getNumIdle are not zero.
                    o = Integer.valueOf(1);
                }
                return o;
            }
        };

        try (@SuppressWarnings({ "unchecked" })
            final KeyedObjectPool<?, ?> o = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), 0f)) {
            fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try (@SuppressWarnings({ "unchecked" })
            final KeyedObjectPool<?, ?> o = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), 0f, false)) {
            fail("PoolUtils.erodingPool(ObjectPool, float, boolean) must not allow a non-positive factor.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked.
        final float factor = 0.01f; // about ~9 seconds until first discard
        final List<String> expectedMethods = new ArrayList<>();
        try (@SuppressWarnings("unchecked")
        final KeyedObjectPool<Object, Object> pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler),
                factor)) {

            assertEquals(expectedMethods, calledMethods);

            final Object key = "key";

            pool.addObject(key);
            expectedMethods.add("addObject");

            Object o = pool.borrowObject(key);
            expectedMethods.add("borrowObject");

            assertEquals(expectedMethods, calledMethods);

            pool.returnObject(key, o);
            expectedMethods.add("returnObject");
            assertEquals(expectedMethods, calledMethods);

            // the invocation handler always returns 1
            assertEquals(1, pool.getNumActive());
            expectedMethods.add("getNumActive");
            assertEquals(1, pool.getNumIdle());
            expectedMethods.add("getNumIdle");

            for (int i = 0; i < 5; i++) {
                o = pool.borrowObject(key);
                expectedMethods.add("borrowObject");

                Thread.sleep(50);

                pool.returnObject(key, o);
                expectedMethods.add("returnObject");

                assertEquals(expectedMethods, calledMethods);

                expectedMethods.clear();
                calledMethods.clear();
            }

            Thread.sleep(10000); // 10 seconds

            o = pool.borrowObject(key);
            expectedMethods.add("borrowObject");
            pool.returnObject(key, o);
            expectedMethods.add("getNumIdle");
            expectedMethods.add("invalidateObject");
            pool.clear();
        }
        expectedMethods.add("clear");
        expectedMethods.add("close");
        assertEquals(expectedMethods, calledMethods);
    }

    @Test
    public void testErodingPoolKeyedObjectPoolDefaultFactor() {
        try (@SuppressWarnings("unchecked")
        final KeyedObjectPool<Object, Object> internalPool = createProxy(KeyedObjectPool.class,
                (arg0, arg1, arg2) -> null)) {
            final KeyedObjectPool<Object, Object> pool = PoolUtils.erodingPool(internalPool);
            final String expectedToString = "ErodingKeyedObjectPool{factor=ErodingFactor{factor=1.0, idleHighWaterMark=1}, keyedPool="
                    + internalPool + "}";
            // The factor is not exposed, but will be printed in the toString() method
            // In this case since we didn't pass one, the default 1.0f will be printed
            assertEquals(expectedToString, pool.toString());
        }
    }

    @Test
    public void testErodingPerKeyKeyedObjectPool() throws Exception {
        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null, 1f, true);
            fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null, 0f, true);
            fail("PoolUtils.erodingPool(ObjectPool, float, boolean) must not allow a non-positive factor.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        try {
            PoolUtils.erodingPool((KeyedObjectPool<Object, Object>) null, 1f, true);
            fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool.");
        } catch (final IllegalArgumentException iae) {
            // expected
        }

        final List<String> calledMethods = new ArrayList<>();
        final InvocationHandler handler = new MethodCallLogger(calledMethods) {
            @Override
            public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                Object o = super.invoke(proxy, method, args);
                if (o instanceof Integer) {
                    // so getNumActive/getNumIdle are not zero.
                    o = Integer.valueOf(1);
                }
                return o;
            }
        };

        // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked.
        final float factor = 0.01f; // about ~9 seconds until first discard
        try (@SuppressWarnings("unchecked")
        final KeyedObjectPool<Object, Object> pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler),
                factor, true)) {

            final List<String> expectedMethods = new ArrayList<>();
            assertEquals(expectedMethods, calledMethods);

            final Object key = "key";

            Object o = pool.borrowObject(key);
            expectedMethods.add("borrowObject");

            assertEquals(expectedMethods, calledMethods);

            pool.returnObject(key, o);
            expectedMethods.add("returnObject");
            assertEquals(expectedMethods, calledMethods);

            for (int i = 0; i < 5; i++) {
                o = pool.borrowObject(key);
                expectedMethods.add("borrowObject");

                Thread.sleep(50);

                pool.returnObject(key, o);
                expectedMethods.add("returnObject");

                assertEquals(expectedMethods, calledMethods);

                expectedMethods.clear();
                calledMethods.clear();
            }

            Thread.sleep(10000); // 10 seconds

            o = pool.borrowObject(key);
            expectedMethods.add("borrowObject");
            pool.returnObject(key, o);
            expectedMethods.add("getNumIdle");
            expectedMethods.add("invalidateObject");
            assertEquals(expectedMethods, calledMethods);

            final String expectedToString = "ErodingPerKeyKeyedObjectPool{factor=" + factor + ", keyedPool=null}";
            assertEquals(expectedToString, pool.toString());
        }
    }

    /**
     * Tests the {@link PoolUtils} timer holder.
     */
    @Test
    public void testTimerHolder() {
        final PoolUtils.TimerHolder h = new PoolUtils.TimerHolder();
        assertNotNull(h);
        assertNotNull(PoolUtils.TimerHolder.MIN_IDLE_TIMER);
    }

    private static List<String> invokeEveryMethod(final ObjectPool<Object> op) throws Exception {
        op.addObject();
        op.borrowObject();
        op.clear();
        op.close();
        op.getNumActive();
        op.getNumIdle();
        op.invalidateObject(new Object());
        op.returnObject(new Object());
        op.toString();

        final List<String> expectedMethods = Arrays.asList(new String[] {
                "addObject", "borrowObject", "clear", "close",
                "getNumActive", "getNumIdle", "invalidateObject",
                "returnObject", "toString"
        });
        return expectedMethods;
    }

    private static List<String> invokeEveryMethod(final KeyedObjectPool<Object,Object> kop) throws Exception {
        kop.addObject(null);
        kop.borrowObject(null);
        kop.clear();
        kop.clear(null);
        kop.close();
        kop.getNumActive();
        kop.getNumActive(null);
        kop.getNumIdle();
        kop.getNumIdle(null);
        kop.invalidateObject(null, new Object());
        kop.returnObject(null, new Object());
        kop.toString();

        final List<String> expectedMethods = Arrays.asList(new String[] {
                "addObject", "borrowObject", "clear", "clear", "close",
                "getNumActive", "getNumActive", "getNumIdle", "getNumIdle", "invalidateObject",
                "returnObject", "toString"
        });
        return expectedMethods;
    }

    private static <T> List<String> invokeEveryMethod(final PooledObjectFactory<T> pof) throws Exception {
        pof.activateObject(null);
        pof.destroyObject(null);
        pof.makeObject();
        pof.passivateObject(null);
        pof.validateObject(null);
        pof.toString();

        final List<String> expectedMethods = Arrays.asList(new String[] {
                "activateObject", "destroyObject", "makeObject",
                "passivateObject", "validateObject", "toString",
        });
        return expectedMethods;
    }

    private static <K, V> List<String> invokeEveryMethod(final KeyedPooledObjectFactory<K, V> kpof) throws Exception {
        kpof.activateObject(null, null);
        kpof.destroyObject(null, null);
        kpof.makeObject(null);
        kpof.passivateObject(null, null);
        kpof.validateObject(null, null);
        kpof.toString();

        final List<String> expectedMethods = Arrays.asList(new String[] {
                "activateObject", "destroyObject", "makeObject",
                "passivateObject", "validateObject", "toString",
        });
        return expectedMethods;
    }

    private static <T> T createProxy(final Class<T> clazz, final List<String> logger) {
        return createProxy(clazz, new MethodCallLogger(logger));
    }

    private static <T> T createProxy(final Class<T> clazz, final InvocationHandler handler) {
        @SuppressWarnings("unchecked")
        final
        T ret = (T) Proxy.newProxyInstance(
                clazz.getClassLoader(), new Class[] { clazz }, handler);
        return ret;
    }

    private static class MethodCallLogger implements InvocationHandler {
        private final List<String> calledMethods;

        MethodCallLogger(final List<String> calledMethods) {
            this.calledMethods = calledMethods;
        }

        @Override
        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
            if (calledMethods == null) {
                return null;
            }
            calledMethods.add(method.getName());
            if (boolean.class.equals(method.getReturnType())) {
                return Boolean.FALSE;
            } else if (int.class.equals(method.getReturnType())) {
                return Integer.valueOf(0);
            } else if (long.class.equals(method.getReturnType())) {
                return Long.valueOf(0);
            } else if (Object.class.equals(method.getReturnType())) {
                return new Object();
            } else if (PooledObject.class.equals(method.getReturnType())) {
                return new DefaultPooledObject<>(new Object());
            } else {
                return null;
            }
        }
    }
}
