You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ps...@apache.org on 2013/11/24 21:08:25 UTC

svn commit: r1545063 - /commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java

Author: psteitz
Date: Sun Nov 24 20:08:25 2013
New Revision: 1545063

URL: http://svn.apache.org/r1545063
Log:
Added (disabled) test to demonstrate POOL-240.
Contributed by Dan McNulty
JIRA: POOL-240

Modified:
    commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java

Modified: commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java?rev=1545063&r1=1545062&r2=1545063&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java Sun Nov 24 20:08:25 2013
@@ -32,7 +32,14 @@ import java.util.ArrayList;
 import java.util.NoSuchElementException;
 import java.util.Random;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.management.MBeanServer;
@@ -1767,7 +1774,82 @@ public class TestGenericKeyedObjectPool 
         Set<ObjectName> result = mbs.queryNames(oname, null);
         Assert.assertEquals(1, result.size());
     }
+    
+    /**
+     * Verify that threads blocked waiting on a depleted pool get served when a checked out instance
+     * is invalidated.
+     * 
+     * JIRA: POOL-240
+     */
+    //@Test
+    public void testInvalidateWaiting()
+        throws Exception {
+
+        GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
+        config.setMaxTotal(2);
+        config.setBlockWhenExhausted(true);
+        config.setMinIdlePerKey(0);
+        config.setMaxWaitMillis(-1);
+        config.setNumTestsPerEvictionRun(Integer.MAX_VALUE); // always test all idle objects
+        config.setTestOnBorrow(true);
+        config.setTestOnReturn(false);
+        config.setTestWhileIdle(true);
+        config.setTimeBetweenEvictionRunsMillis(-1);
+
+        final GenericKeyedObjectPool<Integer, Object> pool = new GenericKeyedObjectPool<Integer, Object>(
+                                                                                                         new ObjectFactory(),
+                                                                                                         config);
+
+        // Allocate both objects with this thread
+        Object object1 = pool.borrowObject(1);
+        Object object2 = pool.borrowObject(1);
+
+        // Cause a thread to block waiting for an object
+        ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
+
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(r);
+                t.setDaemon(true);
+                return t;
+            }
+        });
 
+        final Semaphore signal = new Semaphore(0);
+        Future<Exception> result = executorService.submit(new Callable<Exception>() {
+
+            @Override
+            public Exception call() {
+                try {
+                    signal.release();
+                    Object object3 = pool.borrowObject(1);
+                    pool.returnObject(1, object3);
+                    signal.release();
+                } catch (Exception e) {
+                    return e;
+                } catch (Throwable e) {
+                    return new Exception(e);
+                }
+
+                return null;
+            }
+        });
+
+        // Wait for the thread to start
+        assertTrue(signal.tryAcquire(5, TimeUnit.SECONDS));
+
+        // Attempt to ensure that test thread is blocked waiting for an object
+        Thread.sleep(500);
+
+        pool.invalidateObject(1, object2);
+
+        assertTrue("Call to invalidateObject did not unblock pool waiters.",
+                   signal.tryAcquire(2, TimeUnit.SECONDS));
+
+        if (result.get() != null) {
+            throw new AssertionError(result.get());
+        }
+    }
 
     private static class DummyFactory
             extends BaseKeyedPooledObjectFactory<Object,Object> {
@@ -1781,7 +1863,6 @@ public class TestGenericKeyedObjectPool 
         }
     }
 
-
     private static class SimplePerKeyFactory
             extends BaseKeyedPooledObjectFactory<Object,Object> {
         ConcurrentHashMap<Object,AtomicInteger> map =
@@ -1803,6 +1884,21 @@ public class TestGenericKeyedObjectPool 
             return new DefaultPooledObject<Object>(value);
         }
     }
+    
+    private static class ObjectFactory
+        extends BaseKeyedPooledObjectFactory<Integer, Object> {
+
+        @Override
+        public Object create(Integer key)
+            throws Exception {
+            return new Object();
+        }
+
+        @Override
+        public PooledObject<Object> wrap(Object value) {
+            return new DefaultPooledObject<Object>(value);
+        }
+    }
 }