Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,14 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.parallel.Isolated;

/**
*/
@Isolated
class TestGenericObjectPool extends TestBaseObjectPool {
private final class ConcurrentBorrowAndEvictThread extends Thread {
private final boolean borrow;
Expand Down Expand Up @@ -976,6 +979,124 @@ void testAddObject() throws Exception {
assertEquals(0, genericObjectPool.getNumActive(), "should be zero active");
}

/*https://issues.apache.org/jira/browse/POOL-425*/
@Test
@Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
void testAddObjectRespectsMaxIdleLimit() throws Exception {
final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
config.setJmxEnabled(false);
try (GenericObjectPool<String> pool = new GenericObjectPool<>(new SimpleFactory(), config)) {
assertEquals(0, pool.getNumIdle(), "should be zero idle");
pool.setMaxIdle(1);
pool.addObject();
pool.addObject();
assertEquals(1, pool.getNumIdle(), "should be one idle");

pool.setMaxIdle(-1);
pool.addObject();
pool.addObject();
pool.addObject();
assertEquals(4, pool.getNumIdle(), "should be four idle");
}
}

@RepeatedTest(10)
@Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
void testAddObjectConcurrentCallsRespectsMaxIdle() throws Exception {
final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
config.setJmxEnabled(false);
try (GenericObjectPool<String> pool = new GenericObjectPool<>(new SimpleFactory(), config)) {
assertEquals(0, pool.getNumIdle(), "should be zero idle");
final int maxIdleLimit = 5;
final int numThreads = 10;
pool.setMaxIdle(maxIdleLimit);
pool.setMaxTotal(-1);

final CountDownLatch startLatch = new CountDownLatch(1);
List<Runnable> tasks = getRunnables(numThreads, startLatch, pool);

ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
tasks.forEach(executorService::submit);
try {
startLatch.countDown(); // Start all threads simultaneously
} finally {
executorService.shutdown();
assertTrue(executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS));
}

assertTrue(pool.getNumIdle() <= maxIdleLimit,
"Concurrent addObject() calls should not exceed maxIdle limit of " + maxIdleLimit +
", but found " + pool.getNumIdle() + " idle objects");
}
}

@RepeatedTest(10)
@Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
void testReturnObjectRespectsMaxIdleLimit() throws Exception {
final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
config.setJmxEnabled(false);
try (final GenericObjectPool<String> pool = new GenericObjectPool<>(new SimpleFactory(), config)) {
assertEquals(0, pool.getNumIdle(), "should be zero idle");
final int maxIdleLimit = 5;
final int numThreads = 100;

pool.setMaxTotal(-1);
pool.setMaxIdle(maxIdleLimit);

final CountDownLatch startLatch = new CountDownLatch(1);
List<Runnable> tasks = getReturnRunnables(numThreads, startLatch, pool);

ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
tasks.forEach(executorService::submit);
try {
startLatch.countDown(); // Start all threads simultaneously
} finally {
executorService.shutdown();
assertTrue(executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS));
}

assertEquals(maxIdleLimit, pool.getNumIdle(),
" Should not be more than " + maxIdleLimit + " idle objects");
}
}

private List<Runnable> getRunnables(final int numThreads,
final CountDownLatch startLatch,
final GenericObjectPool<String> pool) {
List<Runnable> tasks = new ArrayList<>();

for(int i = 0; i < numThreads; i++) {
tasks.add(() -> {
try {
startLatch.await(); // Wait for all threads to be ready
pool.addObject();
} catch (Exception e) {
// do nothing
}
});
}
return tasks;
}

private List<Runnable> getReturnRunnables(final int numThreads,
final CountDownLatch startLatch,
final GenericObjectPool<String> pool) {
List<Runnable> tasks = new ArrayList<>();

for(int i = 0; i < numThreads; i++) {
tasks.add(() -> {
try {
String pooledObject = pool.borrowObject();
startLatch.await(); // Wait for all threads to be ready
pool.returnObject(pooledObject);
} catch (Exception e) {
// do nothing
}
});
}
return tasks;
}

@Test
void testAddObjectCanAddToMaxIdle() throws Exception {
genericObjectPool.setMaxTotal(5);
Expand Down