|
43 | 43 | import java.util.Set; |
44 | 44 | import java.util.Timer; |
45 | 45 | import java.util.TimerTask; |
| 46 | +import java.util.concurrent.CountDownLatch; |
| 47 | +import java.util.concurrent.ExecutorService; |
| 48 | +import java.util.concurrent.Executors; |
46 | 49 | import java.util.concurrent.Semaphore; |
47 | 50 | import java.util.concurrent.TimeUnit; |
48 | 51 | import java.util.concurrent.atomic.AtomicBoolean; |
@@ -1012,6 +1015,71 @@ void testAddObject() throws Exception { |
1012 | 1015 | assertEquals(0, genericObjectPool.getNumActive(), "should be zero active"); |
1013 | 1016 | } |
1014 | 1017 |
|
| 1018 | + |
| 1019 | + /*https://issues.apache.org/jira/browse/POOL-425*/ |
| 1020 | + @Test |
| 1021 | + @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) |
| 1022 | + void testAddObjectRespectsMaxIdleLimit() throws Exception { |
| 1023 | + genericObjectPool.setMaxIdle(1); |
| 1024 | + genericObjectPool.addObject(); |
| 1025 | + genericObjectPool.addObject(); |
| 1026 | + assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle"); |
| 1027 | + |
| 1028 | + genericObjectPool.setMaxIdle(-1); |
| 1029 | + genericObjectPool.addObject(); |
| 1030 | + genericObjectPool.addObject(); |
| 1031 | + genericObjectPool.addObject(); |
| 1032 | + assertEquals(4, genericObjectPool.getNumIdle(), "should be four idle"); |
| 1033 | + } |
| 1034 | + |
| 1035 | + @Test |
| 1036 | + @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) |
| 1037 | + void testAddObjectConcurrentCallsRespectsMaxIdle() throws Exception { |
| 1038 | + final int maxIdleLimit = 5; |
| 1039 | + final int numThreads = 10; |
| 1040 | + genericObjectPool.setMaxIdle(maxIdleLimit); |
| 1041 | + |
| 1042 | + final CountDownLatch startLatch = new CountDownLatch(1); |
| 1043 | + final CountDownLatch doneLatch = new CountDownLatch(numThreads); |
| 1044 | + |
| 1045 | + List<Runnable> tasks = getRunnables(numThreads, startLatch, doneLatch); |
| 1046 | + |
| 1047 | + ExecutorService executorService = Executors.newFixedThreadPool(numThreads); |
| 1048 | + tasks.forEach(executorService::submit); |
| 1049 | + try { |
| 1050 | + startLatch.countDown(); // Start all threads simultaneously |
| 1051 | + doneLatch.await(); // Wait for all threads to complete |
| 1052 | + } finally { |
| 1053 | + executorService.shutdown(); |
| 1054 | + assertTrue(executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)); |
| 1055 | + } |
| 1056 | + |
| 1057 | + assertTrue(genericObjectPool.getNumIdle() <= maxIdleLimit, |
| 1058 | + "Concurrent addObject() calls should not exceed maxIdle limit of " + maxIdleLimit + |
| 1059 | + ", but found " + genericObjectPool.getNumIdle() + " idle objects"); |
| 1060 | + } |
| 1061 | + |
| 1062 | + private List<Runnable> getRunnables(final int numThreads, |
| 1063 | + final CountDownLatch startLatch, |
| 1064 | + final CountDownLatch doneLatch) { |
| 1065 | + List<Runnable> tasks = new ArrayList<>(); |
| 1066 | + |
| 1067 | + for(int i = 0; i < numThreads; i++) { |
| 1068 | + tasks.add(() -> { |
| 1069 | + try { |
| 1070 | + startLatch.await(); // Wait for all threads to be ready |
| 1071 | + genericObjectPool.addObject(); |
| 1072 | + } catch (Exception e) { |
| 1073 | + Thread.currentThread().interrupt(); // Restore interrupt status |
| 1074 | + } finally { |
| 1075 | + doneLatch.countDown(); |
| 1076 | + } |
| 1077 | + }); |
| 1078 | + } |
| 1079 | + return tasks; |
| 1080 | + } |
| 1081 | + |
| 1082 | + |
1015 | 1083 | @Test |
1016 | 1084 | void testAppendStats() { |
1017 | 1085 | assertFalse(genericObjectPool.getMessageStatistics()); |
|
0 commit comments