POOL-340 unit test contributed by Pavel Kolesov
Project: http://git-wip-us.apache.org/repos/asf/commons-pool/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-pool/commit/ad9a0d89 Tree: http://git-wip-us.apache.org/repos/asf/commons-pool/tree/ad9a0d89 Diff: http://git-wip-us.apache.org/repos/asf/commons-pool/diff/ad9a0d89 Branch: refs/heads/master Commit: ad9a0d89282ced132e9a2bde87629c5dcb2d8ab7 Parents: 016a1f6 Author: Mark Struberg <[email protected]> Authored: Sat Oct 27 20:41:08 2018 +0200 Committer: Mark Struberg <[email protected]> Committed: Sat Oct 27 20:41:08 2018 +0200 ---------------------------------------------------------------------- ...stGenericObjectPoolFactoryCreateFailure.java | 121 +++++++++++++++++++ 1 file changed, 121 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-pool/blob/ad9a0d89/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java new file mode 100644 index 0000000..ca5a454 --- /dev/null +++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java @@ -0,0 +1,121 @@ +package org.apache.commons.pool2.impl; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Pavel Kolesov as contributed in POOL-340 + */ +public class TestGenericObjectPoolFactoryCreateFailure { + + @Test(timeout = 10_000) + public void testBorrowObjectStuck() { + SingleObjectFactory factory = new SingleObjectFactory(); + GenericObjectPoolConfig config = new GenericObjectPoolConfig(); + config.setMaxIdle(1); + config.setMaxTotal(1); + config.setBlockWhenExhausted(true); + config.setMinIdle(0); + config.setTestOnBorrow(true); + config.setTestOnReturn(true); + config.setTestWhileIdle(false); + config.setTimeBetweenEvictionRunsMillis(-1); + config.setMinEvictableIdleTimeMillis(-1); + config.setSoftMinEvictableIdleTimeMillis(-1); + + config.setMaxWaitMillis(-1); + GenericObjectPool<Object> pool = new GenericObjectPool<>(factory, config); + + AtomicBoolean failed = new AtomicBoolean(); + CountDownLatch barrier = new CountDownLatch(1); + Thread thread1 = new Thread(new WinnerRunnable(pool, barrier, failed)); + thread1.start(); + + // wait for object to be created + while(!factory.created.get()) { + sleepIgnoreException(5); + } + + // now borrow + barrier.countDown(); + try { + pool.borrowObject(); + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertFalse(failed.get()); + + } + + private static class SingleObjectFactory extends BasePooledObjectFactory<Object> { + private final AtomicBoolean created = new AtomicBoolean(); + private final AtomicBoolean validated = new AtomicBoolean(); + @Override + public Object create() throws Exception { + if (!created.getAndSet(true)) { + return new Object(); + } + throw new Exception("Already created"); + } + + @Override + public PooledObject<Object> wrap(Object obj) { + return new DefaultPooledObject<>(new Object()); + } + + @Override + public boolean validateObject(PooledObject<Object> p) { + // return valid once + if (!validated.getAndSet(true)) { + return true; + } + System.out.println("invalid"); + return false; + } + } + + private static class WinnerRunnable implements Runnable { + private final GenericObjectPool<Object> pool; + private final AtomicBoolean failed; + private final CountDownLatch barrier; + private WinnerRunnable(GenericObjectPool<Object> pool, CountDownLatch barrier, AtomicBoolean failed) { + this.pool = pool; + this.failed = failed; + this.barrier = barrier; + } + @Override + public void run() { + try { + Object obj = pool.borrowObject(); + + // wait for another thread to start borrowObject + if (!barrier.await(5, TimeUnit.SECONDS)) { + System.out.println("Timeout waiting"); + failed.set(true); + } else { + // just to make sure, borrowObject has started waiting on queue + sleepIgnoreException(1000); + } + + pool.returnObject(obj); + } catch (Exception e) { + failed.set(true); + e.printStackTrace(); + } + } + } + + private static void sleepIgnoreException(long millis) { + try { + Thread.sleep(millis); + } catch(Throwable e) { + // ignore + } + } +} \ No newline at end of file
