This is an automated email from the ASF dual-hosted git repository. psteitz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-pool.git
The following commit(s) were added to refs/heads/master by this push: new 6da6cef7 Javadoc fixes, improvements to tests * Make it clear that nulls from factory makeObject -> NPE * Disable tests that don't test anything but dump stack traces * Fix and re-enable preparePool GOP test * Add a test factory that simulates resource provider outage * Add a (disabled) test showing remaining liveness problem 6da6cef7 is described below commit 6da6cef73075ff3ce54a8fb246410031d2f6bec7 Author: psteitz <phil.ste...@gmail.com> AuthorDate: Wed Jul 12 11:05:36 2023 -0700 Javadoc fixes, improvements to tests * Make it clear that nulls from factory makeObject -> NPE * Disable tests that don't test anything but dump stack traces * Fix and re-enable preparePool GOP test * Add a test factory that simulates resource provider outage * Add a (disabled) test showing remaining liveness problem --- .../commons/pool2/impl/GenericKeyedObjectPool.java | 19 +- .../commons/pool2/impl/GenericObjectPool.java | 17 +- .../pool2/impl/DisconnectingWaiterFactory.java | 229 +++++++++++++++++++++ .../pool2/impl/TestGenericKeyedObjectPool.java | 39 ++++ .../commons/pool2/impl/TestGenericObjectPool.java | 89 +++++++- .../commons/pool2/pool407/KeyedPool407Test.java | 6 + .../apache/commons/pool2/pool407/Pool407Test.java | 6 + 7 files changed, 400 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java b/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java index fbb5cabb..f468795b 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java +++ b/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java @@ -320,6 +320,13 @@ public class GenericKeyedObjectPool<K, T, E extends Exception> extends BaseGener * factory}, passivate it, and then place it in the idle object pool. * {@code addObject} is useful for "pre-loading" a pool with idle * objects. + * <p> + * If there is no capacity available to add to the pool under the given key, + * this is a no-op (no exception, no impact to the pool). </p> + * <p> + * If the factory returns null when creating an instance, + * a {@code NullPointerException} is thrown. + * </p> * * @param key the key a new instance should be added to * @@ -372,7 +379,8 @@ public class GenericKeyedObjectPool<K, T, E extends Exception> extends BaseGener * circulation (under all keys) is less than {@code maxTotal}, a new * instance is created, activated and (if applicable) validated and returned * to the caller. If validation fails, a {@code NoSuchElementException} - * will be thrown. + * will be thrown. If the factory returns null when creating an instance, + * a {@code NullPointerException} is thrown. * </p> * <p> * If the associated sub-pool is exhausted (no available idle instances and @@ -918,8 +926,15 @@ public class GenericKeyedObjectPool<K, T, E extends Exception> extends BaseGener } /** - * Ensure that the configured number of minimum idle objects is available in + * Try to ensure that the configured number of minimum idle objects is available in * the pool for the given key. + * <p> + * If there is no capacity available to add to the pool, this is a no-op + * (no exception, no impact to the pool). </p> + * <p> + * If the factory returns null when creating an object, a {@code NullPointerException} + * is thrown. + * </p> * * @param key The key to check for idle objects * diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java index dfd8fd52..e23c5ae5 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java +++ b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java @@ -206,6 +206,11 @@ public class GenericObjectPool<T, E extends Exception> extends BaseGenericObject * <p> * If there is no capacity available to add to the pool, this is a no-op * (no exception, no impact to the pool). </p> + * <p> + * If the factory returns null when creating an object, a {@code NullPointerException} + * is thrown. If there is no factory set (factory == null), an {@code IllegalStateException} + * is thrown. </p> + * */ @Override public void addObject() throws E { @@ -247,7 +252,8 @@ public class GenericObjectPool<T, E extends Exception> extends BaseGenericObject * checked out from the pool is less than {@code maxTotal,} a new * instance is created, activated and (if applicable) validated and returned * to the caller. If validation fails, a {@code NoSuchElementException} - * is thrown. + * is thrown. If the factory returns null when creating an instance, + * a {@code NullPointerException} is thrown. * </p> * <p> * If the pool is exhausted (no available idle instances and no capacity to @@ -391,7 +397,8 @@ public class GenericObjectPool<T, E extends Exception> extends BaseGenericObject * checked out from the pool is less than {@code maxTotal,} a new * instance is created, activated and (if applicable) validated and returned * to the caller. If validation fails, a {@code NoSuchElementException} - * is thrown. + * is thrown. If the factory returns null when creating an instance, + * a {@code NullPointerException} is thrown. * </p> * <p> * If the pool is exhausted (no available idle instances and no capacity to @@ -497,6 +504,9 @@ public class GenericObjectPool<T, E extends Exception> extends BaseGenericObject * If there are {@link #getMaxTotal()} objects already in circulation or in process of being created, this method * returns null. * </p> + * <p> + * If the factory makeObject returns null, this method throws a NullPointerException. + * </p> * * @return The new wrapped pooled object or null. * @throws E if the object factory's {@code makeObject} fails @@ -621,6 +631,9 @@ public class GenericObjectPool<T, E extends Exception> extends BaseGenericObject * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless * there are threads waiting to check out instances from the pool. * </p> + * <p> + * If the factory returns null when creating an instance, a {@code NullPointerException} + * is thrown. </p> * * @param idleCount the number of idle instances desired * @param always true means create instances even if the pool has no threads waiting diff --git a/src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java b/src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java new file mode 100644 index 00000000..f0a35c97 --- /dev/null +++ b/src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java @@ -0,0 +1,229 @@ +/* + * 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.impl; + +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.Waiter; +import org.apache.commons.pool2.WaiterFactory; + +public class DisconnectingWaiterFactory<K> extends WaiterFactory<K> { + /** + * + * A WaiterFactory that simulates a resource required by factory methods going down (and coming back). + * When the factory is not connected, factory methods behave according to + * timeBetweenConnectionChecks time units. Validate returns false immediately if the factory + * is disconnected; otherwise does super.validate(). Destroy does super.destroy() + * regardless of connect status. + * + * Blocking vs throwing immediately is controlled by blockWhenDisconnected. + * Time to wait for reconnect is controlled by maxWait. + */ + private final AtomicBoolean connected = new AtomicBoolean(true); + + private static final Duration DEFAULT_TIME_BETWEEN_CONNECTION_CHECKS = Duration.ofMillis(100); + + private static final Duration DEFAULT_MAX_WAIT = Duration.ofSeconds(10); + + /** Default function to perform for activate, passivate, destroy in disconnected mode - no-op */ + protected static final Consumer<PooledObject<Waiter>> DEFAULT_DISCONNECTED_LIFECYCLE_ACTION = w -> {}; + + /** + * Default supplier determining makeObject action when invoked in disconnected mode. + * Default behavior is to block until reconnected for up to DEFAULT_MAX_WAIT duration. + * If DEFAULT_MAX_WAIT is exceeded, throw ISE; if reconnect happens in time, invoke super.makeObject(). + */ + protected static final Supplier<PooledObject<Waiter>> DEFAULT_DISCONNECTED_CREATE_ACTION = () -> { + waitForConnection(null, DEFAULT_TIME_BETWEEN_CONNECTION_CHECKS, DEFAULT_MAX_WAIT); + return new DefaultPooledObject<Waiter>(new Waiter(true, true, 0)); + }; + + /** Default predicate determining what validate does in disconnected state - always return false */ + protected static final Predicate<PooledObject<Waiter>> DEFAULT_DISCONNECTED_VALIDATION_ACTION = w -> false; + + /** Time between reconnection checks */ + final Duration timeBetweenConnectionChecks; + + /** Maximum amount of time a factory method will wait for reconnect before throwing TimeOutException */ + final Duration maxWait; + + /** Function to perform when makeObject is executed in disconnected mode */ + final Supplier<PooledObject<Waiter>> disconnectedCreateAction; + + /** Function to perform for activate, passsivate and destroy when invoked in disconnected mode */ + final Consumer<PooledObject<Waiter>> disconnectedLifcycleAction; + + /** Function to perform for validate when invoked in disconnected mode */ + final Predicate<PooledObject<Waiter>> disconnectedValidationAction; + + public DisconnectingWaiterFactory(final long activateLatency, final long destroyLatency, + final long makeLatency, final long passivateLatency, final long validateLatency, + final long waiterLatency) { + this(activateLatency, destroyLatency, makeLatency, passivateLatency, + validateLatency, waiterLatency, Long.MAX_VALUE, Long.MAX_VALUE, 0); + } + + public DisconnectingWaiterFactory(final long activateLatency, final long destroyLatency, + final long makeLatency, final long passivateLatency, final long validateLatency, + final long waiterLatency,final long maxActive) { + this(activateLatency, destroyLatency, makeLatency, passivateLatency, + validateLatency, waiterLatency, maxActive, + Long.MAX_VALUE, 0); + } + + public DisconnectingWaiterFactory(final long activateLatency, final long destroyLatency, + final long makeLatency, final long passivateLatency, final long validateLatency, + final long waiterLatency, final long maxActive, final long maxActivePerKey, + final double passivateInvalidationProbability) { + super(activateLatency, destroyLatency, makeLatency, passivateLatency, + validateLatency, waiterLatency, maxActive, maxActivePerKey, + passivateInvalidationProbability); + this.timeBetweenConnectionChecks = DEFAULT_TIME_BETWEEN_CONNECTION_CHECKS; + this.maxWait = DEFAULT_MAX_WAIT; + this.disconnectedCreateAction = DEFAULT_DISCONNECTED_CREATE_ACTION; + this.disconnectedLifcycleAction = DEFAULT_DISCONNECTED_LIFECYCLE_ACTION; + this.disconnectedValidationAction = DEFAULT_DISCONNECTED_VALIDATION_ACTION; + } + + public DisconnectingWaiterFactory(final Supplier<PooledObject<Waiter>> disconnectedCreateAction, + final Consumer<PooledObject<Waiter>> disconnectedLifcycleAction, + final Predicate<PooledObject<Waiter>> disconnectedValidationAction) { + super(0,0,0, + 0,0,0, + Integer.MAX_VALUE, + Integer.MAX_VALUE, + 0); + this.timeBetweenConnectionChecks = DEFAULT_TIME_BETWEEN_CONNECTION_CHECKS; + this.maxWait = DEFAULT_MAX_WAIT; + this.disconnectedCreateAction = disconnectedCreateAction; + this.disconnectedLifcycleAction = disconnectedLifcycleAction; + this.disconnectedValidationAction = disconnectedValidationAction; + } + + public DisconnectingWaiterFactory() { + this(DEFAULT_DISCONNECTED_CREATE_ACTION, DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + DEFAULT_DISCONNECTED_VALIDATION_ACTION); + } + + private boolean validate(final PooledObject<Waiter> obj) { + if (connected.get()) { + return super.validateObject(obj); + } else { + return disconnectedValidationAction.test(obj); + } + } + + @Override + public boolean validateObject(final K key, final PooledObject<Waiter> obj) { + return validate(obj); + } + + @Override + public boolean validateObject(final PooledObject<Waiter> obj) { + return validate(obj); + } + + private void activate(final PooledObject<Waiter> obj) { + if (!connected.get()) { + disconnectedLifcycleAction.accept(obj); + } else { + super.activateObject(obj); + } + } + + private void passivate(final PooledObject<Waiter> obj) { + if (!connected.get()) { + disconnectedLifcycleAction.accept(obj); + } else { + super.passivateObject(obj); + } + } + + @Override + public void passivateObject(final K key, final PooledObject<Waiter> obj) { + passivate(obj); + } + + @Override + public void passivateObject(final PooledObject<Waiter> obj) { + passivate(obj); + } + + @Override + public void activateObject(final K key, final PooledObject<Waiter> obj) { + activate(obj); + } + + @Override + public void activateObject(final PooledObject<Waiter> obj) { + activate(obj); + } + + @Override + public PooledObject<Waiter> makeObject(final K key) { + return make(); + } + + @Override + public PooledObject<Waiter> makeObject() { + return make(); + } + + private PooledObject<Waiter> make() { + if (!connected.get()) { + return disconnectedCreateAction.get(); + } else { + return super.makeObject(); + } + } + + /** + * Blocks until connected is true or maxWait is exceeded. + * + * @throws TimeoutException if maxWait is exceeded. + */ + private static void waitForConnection(final AtomicBoolean connected, + final Duration timeBetweenConnectionChecks, final Duration maxWait) { + final Instant start = Instant.now(); + while (!connected.get()) { + try { + Thread.sleep(timeBetweenConnectionChecks.toMillis()); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + if (Duration.between(start, Instant.now()).compareTo(maxWait) > 0) { + throw new IllegalStateException(new TimeoutException("Timed out waiting for connection")); + } + } + } + + public void disconnect() { + connected.set(false); + } + + public void connect() { + connected.set(true); + } +} + diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java b/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java index 94542faf..cb6712b5 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java +++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java @@ -2439,6 +2439,45 @@ public class TestGenericKeyedObjectPool extends TestKeyedObjectPool { gkoPool.returnObject("",obj); } + /** + * Verify that when a factory returns a null object, pool methods throw NPE. + */ + @Test + @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) + public void testNPEOnFactoryNull() throws InterruptedException { + final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>( + () -> null, // Override default to always return null from makeObject + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION + ); + final GenericKeyedObjectPool<String,Waiter,RuntimeException> pool = new GenericKeyedObjectPool<>(factory); + final String key = "one"; + pool.setTestOnBorrow(true); + pool.setMaxTotal(-1); + pool.setMinIdlePerKey(1); + // Disconnect the factory - will always return null in this state + factory.disconnect(); + try { + pool.borrowObject(key); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex) { + // expected + } + try { + pool.addObject(key); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex2) { + // expected + } + try { + pool.ensureMinIdle(); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex3) { + // expected + } + pool.close(); + } + @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) public void testNumActiveNumIdle2() throws Exception { diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java index c2ffde1f..e0cc113d 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java +++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java @@ -45,6 +45,7 @@ import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import javax.management.MBeanServer; @@ -64,6 +65,7 @@ import org.apache.commons.pool2.Waiter; import org.apache.commons.pool2.WaiterFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -2038,6 +2040,51 @@ public class TestGenericObjectPool extends TestBaseObjectPool { assertEquals( "4", genericObjectPool.borrowObject(),"new-4"); } + /** + * Simplest example of recovery from factory outage. + * A thread gets into parked wait on the deque when there is capacity to create, but + * creates are failing due to factory outage. Verify that the borrower is served + * once the factory is back online. + */ + @Test + @Disabled + @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) + public void testLivenessOnTransientFactoryFailure() throws InterruptedException { + final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>( + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_CREATE_ACTION, + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + (obj) -> false // all instances fail validation + ); + final GenericObjectPool<Waiter, IllegalStateException> pool = new GenericObjectPool<>(factory); + pool.setMaxWait(Duration.ofMillis(100)); + pool.setTestOnReturn(true); + pool.setMaxTotal(1); + final Waiter w = pool.borrowObject(); + final AtomicBoolean failed = new AtomicBoolean(false); + final Thread t = new Thread(() -> { + try { + pool.borrowObject(); + } catch (final NoSuchElementException e) { + failed.set(true); + } + }); + Thread.sleep(10); + t.start(); + // t is blocked waiting on the deque + Thread.sleep(10); + factory.disconnect(); + pool.returnObject(w); // validation fails, so no return + Thread.sleep(10); + factory.connect(); + // Borrower should be able to be served now + t.join(); + pool.close(); + if (failed.get()) { + fail("Borrower timed out waiting for an instance"); + } + } + + /** * Test the following scenario: * Thread 1 borrows an instance @@ -2537,6 +2584,46 @@ public class TestGenericObjectPool extends TestBaseObjectPool { simpleFactory.setValid(true); } + /** + * Verify that when a factory returns a null object, pool methods throw NPE. + * @throws InterruptedException + */ + @Test + @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) + public void testNPEOnFactoryNull() throws InterruptedException { + final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>( + () -> null, // Override default to always return null from makeObject + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION + ); + final GenericObjectPool<Waiter, IllegalStateException> pool = new GenericObjectPool<>(factory); + pool.setTestOnBorrow(true); + pool.setMaxTotal(-1); + pool.setMinIdle(1); + // Disconnect the factory - will always return null in this state + factory.disconnect(); + try { + pool.borrowObject(); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex) { + // expected + } + try { + pool.addObject(); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex2) { + // expected + } + try { + pool.ensureMinIdle(); + fail("Expecting NullPointerException"); + } catch (final NullPointerException ex3) { + // expected + } + pool.close(); + } + + @Test public void testPreparePool() throws Exception { genericObjectPool.setMinIdle(1); genericObjectPool.setMaxTotal(1); @@ -2548,7 +2635,7 @@ public class TestGenericObjectPool extends TestBaseObjectPool { genericObjectPool.setMinIdle(0); genericObjectPool.returnObject(obj); genericObjectPool.preparePool(); - assertEquals(0, genericObjectPool.getNumIdle()); + assertEquals(1, genericObjectPool.getNumIdle()); } @Test/* maxWaitMillis x2 + padding */ diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java b/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java index 356bc005..deb2f001 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java +++ b/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java @@ -23,6 +23,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.commons.pool2.PooledObject; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** @@ -86,26 +87,31 @@ public class KeyedPool407Test extends AbstractPool407Test { test(new KeyedPool407NormalFactory(new KeyedPool407Fixture()), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } + @Disabled @Test public void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { test(new KeyedPool407NormalFactory(null), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } + @Disabled @Test public void testNullObjectFactoryWaitMax() throws InterruptedException { test(new KeyedPool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } + @Disabled @Test public void testNullObjectFactoryWaitShort() throws InterruptedException { test(new KeyedPool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } + @Disabled @Test public void testNullPoolableFactoryWaitMax() throws InterruptedException { test(new KeyedPool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } + @Disabled @Test public void testNullPoolableFactoryWaitShort() throws InterruptedException { test(new KeyedPool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java b/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java index 09255d8a..9e79b92d 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java +++ b/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java @@ -23,6 +23,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.commons.pool2.PooledObject; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** @@ -84,26 +85,31 @@ public class Pool407Test extends AbstractPool407Test { } @Test + @Disabled public void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { test(new Pool407NormalFactory(null), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } + @Disabled @Test public void testNullObjectFactoryWaitMax() throws InterruptedException { test(new Pool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Test + @Disabled public void testNullObjectFactoryWaitShort() throws InterruptedException { test(new Pool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } @Test + @Disabled public void testNullPoolableFactoryWaitMax() throws InterruptedException { test(new Pool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Test + @Disabled public void testNullPoolableFactoryWaitShort() throws InterruptedException { test(new Pool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); }