Added: 
jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/TestCompositeObjectPool.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/TestCompositeObjectPool.java?rev=387630&view=auto
==============================================================================
--- 
jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/TestCompositeObjectPool.java
 (added)
+++ 
jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/TestCompositeObjectPool.java
 Tue Mar 21 13:41:53 2006
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import junit.framework.TestCase;
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+import java.util.NoSuchElementException;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * Test [EMAIL PROTECTED] CompositeObjectPool} and it's components.
+ *
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+public class TestCompositeObjectPool extends TestCase {
+    private CompositeObjectPool pool = null;
+
+    protected void setUp() throws Exception {
+    }
+
+    protected void tearDown() throws Exception {
+        if (pool != null) {
+            pool.close();
+            pool = null;
+        }
+    }
+
+    // Test Managers --------------------------------------
+
+    /**
+     * Make sure [EMAIL PROTECTED] FailManager} throws an exception.
+     */
+    public void testFailManager() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
FailManager(), new FifoLender(), new DebugTracker(), false);
+        try {
+            pool.borrowObject();
+            fail("Should have thrown a NoSuchElementException");
+        } catch (NoSuchElementException nsee) {
+            // correct
+        }
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] GrowManager} makes a new object.
+     */
+    public void testGrowManager() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new FifoLender(), new DebugTracker(), false);
+        Object obj = null;
+        obj = pool.borrowObject();
+        assertEquals(new Integer(0), obj);
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] IdleLimitManager} prevents the idle pool 
from getting too large.
+     */
+    public void testIdleLimitManager() throws Exception {
+        final IdleLimitManager manager = new IdleLimitManager(new 
GrowManager());
+        manager.setMaxIdle(2);
+        pool = new CompositeObjectPool(new IntegerFactory(), manager, new 
FifoLender(), new DebugTracker(), false);
+
+        assertEquals(0, pool.getNumIdle());
+
+        pool.addObject();
+        assertEquals(1, pool.getNumIdle());
+
+        pool.addObject();
+        assertEquals(2, pool.getNumIdle());
+
+        pool.addObject();
+        assertEquals(2, pool.getNumIdle());
+
+        pool.clear();
+        assertEquals(0, pool.getNumIdle());
+
+        final Integer a = (Integer)pool.borrowObject();
+        final Integer b = (Integer)pool.borrowObject();
+        final Integer c = (Integer)pool.borrowObject();
+
+        pool.returnObject(a);
+        assertEquals(1, pool.getNumIdle());
+
+        pool.returnObject(b);
+        assertEquals(2, pool.getNumIdle());
+
+        pool.returnObject(c);
+        assertEquals(2, pool.getNumIdle());
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] IdleLimitManager} discards the "most idle" 
object when discarding objects because the pool
+     * is full.
+     */
+    public void testIdleLimitManagerDiscardsMostIdle() throws Exception {
+        // FIFO test - the oldest object would be the next one returned.
+        {   // create some scope
+            final IdleLimitManager manager = new IdleLimitManager(new 
GrowManager());
+            manager.setMaxIdle(2);
+            pool = new CompositeObjectPool(new IntegerFactory(), manager, new 
FifoLender(), new DebugTracker(), false);
+            pool.addObject();
+            pool.addObject();
+            pool.addObject();
+
+            final Integer one = (Integer)pool.borrowObject();
+            final Integer two = (Integer)pool.borrowObject();
+            final Integer three = (Integer)pool.borrowObject();
+
+            assertEquals(1, one.intValue());
+            assertEquals(2, two.intValue());
+            assertEquals(3, three.intValue());
+        }
+
+        // LIFO test - the oldest object would be the last one returned.
+        {   // create some scope
+            final IdleLimitManager manager = new IdleLimitManager(new 
GrowManager());
+            manager.setMaxIdle(2);
+            pool = new CompositeObjectPool(new IntegerFactory(), manager, new 
LifoLender(), new DebugTracker(), false);
+            pool.addObject();
+            pool.addObject();
+            pool.addObject();
+
+            final Integer two = (Integer)pool.borrowObject();
+            final Integer one = (Integer)pool.borrowObject();
+            final Integer three = (Integer)pool.borrowObject();
+
+            assertEquals(2, two.intValue());
+            assertEquals(1, one.intValue());
+            assertEquals(3, three.intValue());
+        }
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] FailLimitManager} actually limits the 
number of active objects.
+     */
+    public void testFailLimitManager() throws Exception {
+        final ActiveLimitManager manager = new FailLimitManager(new 
GrowManager());
+        manager.setMaxActive(2);
+        pool = new CompositeObjectPool(new IntegerFactory(), manager, new 
FifoLender(), new DebugTracker(), false);
+
+        assertEquals(0, pool.getNumActive());
+
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        Integer one = (Integer)pool.borrowObject();
+        assertEquals(2, pool.getNumActive());
+
+        try {
+            pool.borrowObject();
+            fail("Should have thrown a NoSuchElementException");
+        } catch(NoSuchElementException nsee) {
+            // expected
+        }
+        assertEquals(2, pool.getNumActive());
+
+        pool.returnObject(zero);
+        assertEquals(1, pool.getNumActive());
+
+        zero = (Integer)pool.borrowObject();
+        assertEquals(2, pool.getNumActive());
+
+        try {
+            pool.borrowObject();
+            fail("Should have thrown a NoSuchElementException");
+        } catch(NoSuchElementException nsee) {
+            // expected
+        }
+        assertEquals(2, pool.getNumActive());
+    }
+
+    /**
+     * Make sure that [EMAIL PROTECTED] WaitLimitManager} both times out and 
returns an object once one is available.
+     */
+    public void testWaitLimitManager() throws Exception {
+        final WaitLimitManager manager = new WaitLimitManager(new 
GrowManager());
+        manager.setMaxActive(1);
+        manager.setMaxWaitMillis(100);
+        pool = new CompositeObjectPool(new IntegerFactory(), manager, new 
FifoLender(), new DebugTracker(), false);
+
+        assertEquals(0, pool.getNumActive());
+
+        final Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        // Test that the max wait
+        try {
+            pool.borrowObject();
+            fail("Should have thrown a NoSuchElementException");
+        } catch(NoSuchElementException nsee) {
+            // expected
+        }
+
+        // test that if an object is returned while waiting it works.
+        // What happens is:
+        // this thread locks pool.pool and starts Thread t.
+        // this thread will get wait for an object to become available and 
relase the lock on pool.pool
+        // Thread t will then be able to lock on pool.pool and return an object
+        // this thread will then be able to borrow an object and should reutrn.
+        final List actualOrder = new ArrayList();
+        final Runnable r = new Runnable() {
+            public void run() {
+                try {
+                    synchronized(pool.getPool()) {
+                        pool.returnObject(zero);
+                        actualOrder.add("returned");
+                    }
+                } catch (Exception e) {
+                    waitFailed = true;
+                }
+            }
+        };
+        final Thread t = new Thread(r);
+
+        synchronized (pool.getPool()) {
+            t.start();
+
+            actualOrder.add("waiting");
+            assertEquals(zero, pool.borrowObject());
+            actualOrder.add("borrowed");
+        }
+
+        assertEquals("Wait failed", false, waitFailed);
+
+        List expectedOrder = new ArrayList();
+        expectedOrder.add("waiting");
+        expectedOrder.add("returned");
+        expectedOrder.add("borrowed");
+
+        assertEquals(expectedOrder, actualOrder);
+    }
+    private boolean waitFailed = false;
+
+    // Test Trackers --------------------------------------
+
+    /**
+     * Make sure the [EMAIL PROTECTED] NullTracker} doesn't do anything and 
throws an [EMAIL PROTECTED] UnsupportedOperationException}.
+     */
+    public void testNullTracker() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new FifoLender(), new NullTracker(), false);
+        try {
+            pool.getNumActive();
+            fail("Should have thrown an UnsupportedOperationException.");
+        } catch(UnsupportedOperationException usoee) {
+            // expected
+        }
+
+        Integer zero = (Integer)pool.borrowObject();
+
+        try {
+            pool.getNumActive();
+            fail("Should have thrown an UnsupportedOperationException.");
+        } catch(UnsupportedOperationException usoee) {
+            // expected
+        }
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] SimpleTracker} counts the number of 
borrowed and returned objects and that an
+     * [EMAIL PROTECTED] IllegalStateException} is thrown when more objects 
are returned than were borrowed.
+     */
+    public void testSimpleTracker() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new FifoLender(), new SimpleTracker(), false);
+
+        assertEquals(0, pool.getNumActive());
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+        Integer one = (Integer)pool.borrowObject();
+        assertEquals(2, pool.getNumActive());
+        pool.returnObject(zero);
+        assertEquals(1, pool.getNumActive());
+        pool.returnObject(one);
+        assertEquals(0, pool.getNumActive());
+
+        try {
+            pool.returnObject(new Object());
+            fail("Should have thrown an IllegalStateException.");
+        } catch(IllegalStateException ise) {
+            // expected
+        }
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] ReferenceTracker} detects when an active 
object is "lost". Make sure an
+     * [EMAIL PROTECTED] IllegalStateException} is thrown with an object that 
wasn't borrowed is returned.
+     * This covers the core funtionality of [EMAIL PROTECTED] DebugTracker} 
too; it's unique features aren't easily testable.
+     */
+    public void testReferenceTracker() throws Exception {
+        // setup
+        final SortedSet borrowedIds = new TreeSet();
+        final SortedSet removedIds = new TreeSet();
+        final Tracker tracker = new ReferenceTracker() {
+            protected void referenceToBeRemoved(final IdentityReference ref) {
+                removedIds.add(new Integer(ref.getKey().hashCode()));
+            }
+        };
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new FifoLender(), tracker, false);
+
+        // borrow some objects
+        List objs = new ArrayList(10);
+        for (int i=0; i < 10 ; i++) {
+            Object obj = pool.borrowObject();
+            borrowedIds.add(new Integer(System.identityHashCode(obj)));
+            objs.add(obj);
+            obj = null; // prevent leak
+        }
+        assertEquals(10, pool.getNumActive());
+        objs.clear();
+
+
+        // garbage collect it
+        while (!removedIds.containsAll(borrowedIds)) {
+            new Object(); // create garbage
+            System.gc();
+            pool.getNumActive(); // works the reference queue
+        }
+        assertEquals(10, removedIds.size());
+        assertEquals(0, pool.getNumActive());
+
+        // make sure we didn't pick up anything extra
+        assertEquals(borrowedIds, removedIds);
+
+        try {
+            pool.returnObject(new Object());
+            fail("Should have thrown an IllegalStateException. Cannot reutrn 
an object that wasn't borrowed.");
+        } catch(IllegalStateException ise) {
+            // expected
+        }
+
+        // Make sure we don't accept the same object returned twice
+        final Object obj = pool.borrowObject();
+        pool.returnObject(obj);
+        try {
+            pool.returnObject(obj);
+            fail("Should have thrown an IllegalStateException. Cannot return 
the same object twice.");
+        } catch(IllegalStateException ise) {
+            // expected
+        }
+    }
+
+    // Test Lenders ---------------------------------------
+
+    /**
+     * Make sure [EMAIL PROTECTED] FifoLender} is a FIFO.
+     */
+    public void testFifoLender() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new FifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        Integer one = (Integer)pool.borrowObject();
+        Integer two = (Integer)pool.borrowObject();
+
+        pool.returnObject(zero);
+        pool.returnObject(one);
+        pool.returnObject(two);
+
+        assertEquals(zero, pool.borrowObject());
+        assertEquals(one, pool.borrowObject());
+        assertEquals(two, pool.borrowObject());
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] LifoLender} is a LIFO.
+     */
+    public void testLifoLender() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new LifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        Integer one = (Integer)pool.borrowObject();
+        Integer two = (Integer)pool.borrowObject();
+
+        pool.returnObject(two);
+        pool.returnObject(one);
+        pool.returnObject(zero);
+
+        assertEquals(zero, pool.borrowObject());
+        assertEquals(one, pool.borrowObject());
+        assertEquals(two, pool.borrowObject());
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] SoftLender} responds to memory pressure.
+     * <p>Note: this test is not completely deterministic and could fail 
erroneously.
+     */
+    public void testSoftLender() throws Exception {
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), new SoftLender(new FifoLender()), new SimpleTracker(), false);
+
+        Object zero = pool.borrowObject();
+        Object one = pool.borrowObject();
+
+        pool.returnObject(zero);
+        zero = null;
+        pool.returnObject(one);
+        one = null;
+
+        /* This requires a bit of memory pressure to reliablly force a [EMAIL 
PROTECTED] SoftReference} to break. */
+        List garbage = new LinkedList();
+        Runtime runtime = Runtime.getRuntime();
+        while (pool.getNumIdle() > 0) {
+            garbage.add(new byte[Math.min(1024 * 1024, 
(int)runtime.freeMemory())]);
+            System.gc();
+        }
+        garbage.clear();
+        System.gc();
+
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(0, pool.getNumActive());
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] IdleEvictorLender} waits at least the 
minimum amount of time before evicting objects.
+     * <p>Note: this test is not completely deterministic and could fail 
erroneously.
+     */
+    public void testIdleEvictorLender() throws Exception {
+        final IdleEvictorLender lender = new IdleEvictorLender(new 
FifoLender());
+        lender.setIdleTimeoutMillis(20L);
+        pool = new CompositeObjectPool(new IntegerFactory(), new 
GrowManager(), lender, new SimpleTracker(), false);
+
+        pool.addObject();
+        assertEquals(1, pool.getNumIdle());
+        Thread.sleep(100L);
+        assertEquals(0, pool.getNumIdle());
+
+        // XXX This could be more extensive
+    }
+
+    /**
+     * Make sure [EMAIL PROTECTED] InvalidEvictorLender} only evicts objects 
that are no longer valid.
+     * <p>Note: this test is not completely deterministic and could fail 
erroneously.
+     */
+    public void testInvalidEvictorLender() throws Exception {
+        final InvalidEvictorLender lender = new InvalidEvictorLender(new 
FifoLender());
+        lender.setValidationFrequencyMillis(20L);
+        final IntegerFactory factory = new IntegerFactory();
+        pool = new CompositeObjectPool(factory, new GrowManager(), lender, new 
SimpleTracker(), false);
+
+        pool.addObject();
+        pool.addObject();
+        assertEquals(2, pool.getNumIdle());
+        Thread.sleep(100L);
+        assertEquals(2, pool.getNumIdle());
+
+        factory.setEvenValid(false);
+        Thread.sleep(100L);
+        assertEquals(1, pool.getNumIdle());
+
+        factory.setOddValid(false);
+        Thread.sleep(100L);
+        assertEquals(0, pool.getNumIdle());
+    }
+
+    // Test exceptions from PoolableObjectFactory ---------
+
+    /**
+     * Make sure [EMAIL PROTECTED] CompositeObjectPool#borrowObject()} doesn't 
mask exceptions from
+     * [EMAIL PROTECTED] PoolableObjectFactory#makeObject()}.
+     */
+    public void testExceptionOnNewObject() throws Exception {
+        PoolableObjectFactory pof = new BasePoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                throw new PrivateException("Cannot make new objects.");
+            }
+        };
+        pool = new CompositeObjectPool(pof, new GrowManager(), new 
SoftLender(new FifoLender()), new SimpleTracker(), false);
+
+        try {
+            pool.borrowObject();
+            fail("Should have thrown a PrivateException");
+        } catch (PrivateException pe) {
+            // expected
+        }
+
+        try {
+            pool.addObject();
+            fail("Should have thrown a PrivateException");
+        } catch (PrivateException pe) {
+            // expected
+        }
+    }
+
+    public void testExceptionOnActivateObject() throws Exception {
+        PoolableObjectFactory pof = new IntegerFactory() {
+            public void activateObject(Object obj) throws Exception {
+                throw new PrivateException("Cannot activate objects.");
+            }
+        };
+        pool = new CompositeObjectPool(pof, new GrowManager(), new 
FifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        pool.returnObject(zero);
+
+        assertEquals(1, pool.getNumIdle());
+        assertEquals(0, pool.getNumActive());
+
+        // Should successed even though activation failed by discarding zero 
and making one.
+        final Integer one = (Integer)pool.borrowObject();
+        assertEquals(new Integer(1), one);
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(1, pool.getNumActive());
+    }
+
+    public void testExceptionOnValidateObject() throws Exception {
+        PoolableObjectFactory pof = new IntegerFactory() {
+            public boolean validateObject(final Object obj) {
+                throw new PrivateException("Cannot validate objects.");
+            }
+        };
+        pool = new CompositeObjectPool(pof, new GrowManager(), new 
FifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        pool.returnObject(zero);
+
+        assertEquals(1, pool.getNumIdle());
+        assertEquals(0, pool.getNumActive());
+
+        assertEquals(new Integer(1), pool.borrowObject());
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(1, pool.getNumActive());
+    }
+
+    public void testExceptionOnPasivateObject() throws Exception {
+        PoolableObjectFactory pof = new IntegerFactory() {
+            public void passivateObject(final Object obj) throws Exception {
+                throw new PrivateException("Cannot passivate objects.");
+            }
+        };
+        pool = new CompositeObjectPool(pof, new GrowManager(), new 
FifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        pool.returnObject(zero);
+
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(0, pool.getNumActive());
+    }
+
+    public void testExceptionOnDestroyObject() throws Exception {
+        PoolableObjectFactory pof = new IntegerFactory() {
+            public void destroyObject(final Object obj) throws Exception {
+                throw new PrivateException("Cannot destroy objects.");
+            }
+        };
+        pool = new CompositeObjectPool(pof, new GrowManager(), new 
FifoLender(), new SimpleTracker(), false);
+
+        Integer zero = (Integer)pool.borrowObject();
+        assertEquals(1, pool.getNumActive());
+
+        pool.invalidateObject(zero);
+
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(0, pool.getNumActive());
+    }
+
+    // Utility classes ------------------------------------
+
+    private static class IntegerFactory extends BasePoolableObjectFactory {
+        private int count = 0;
+        private boolean oddValid = true;
+        private boolean evenValid = true;
+
+        public Object makeObject() throws Exception {
+            return new Integer(count++);
+        }
+
+        public boolean validateObject(final Object obj) {
+            final Integer num = (Integer)obj;
+            if (num.intValue() % 2 == 0) {
+                return evenValid;
+            } else {
+                return oddValid;
+            }
+        }
+
+        public void setValid(final boolean valid) {
+            setEvenValid(valid);
+            setOddValid(valid);
+        }
+
+        public void setOddValid(final boolean oddValid) {
+            this.oddValid = oddValid;
+        }
+
+        public void setEvenValid(final boolean evenValid) {
+            this.evenValid = evenValid;
+        }
+    }
+
+    /**
+     * An exception that only is thrown by this test.
+     */
+    private static class PrivateException extends RuntimeException {
+        PrivateException(final String message) {
+            super(message);
+        }
+    }
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to