1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.pool2.impl;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
23 import static org.junit.jupiter.api.Assertions.assertNotEquals;
24 import static org.junit.jupiter.api.Assertions.assertNotNull;
25 import static org.junit.jupiter.api.Assertions.assertNull;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.jupiter.api.Assertions.fail;
29
30 import java.lang.management.ManagementFactory;
31 import java.lang.ref.WeakReference;
32 import java.nio.charset.UnsupportedCharsetException;
33 import java.time.Duration;
34 import java.time.Instant;
35 import java.util.ArrayList;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.NoSuchElementException;
39 import java.util.Objects;
40 import java.util.Random;
41 import java.util.Set;
42 import java.util.Timer;
43 import java.util.TimerTask;
44 import java.util.concurrent.Semaphore;
45 import java.util.concurrent.TimeUnit;
46 import java.util.concurrent.atomic.AtomicBoolean;
47 import java.util.concurrent.atomic.AtomicInteger;
48
49 import javax.management.MBeanServer;
50 import javax.management.ObjectName;
51
52 import org.apache.commons.lang3.ThreadUtils;
53 import org.apache.commons.lang3.time.DurationUtils;
54 import org.apache.commons.pool2.BasePooledObjectFactory;
55 import org.apache.commons.pool2.ObjectPool;
56 import org.apache.commons.pool2.PoolUtils;
57 import org.apache.commons.pool2.PooledObject;
58 import org.apache.commons.pool2.PooledObjectFactory;
59 import org.apache.commons.pool2.SwallowedExceptionListener;
60 import org.apache.commons.pool2.TestBaseObjectPool;
61 import org.apache.commons.pool2.VisitTracker;
62 import org.apache.commons.pool2.VisitTrackerFactory;
63 import org.apache.commons.pool2.Waiter;
64 import org.apache.commons.pool2.WaiterFactory;
65 import org.junit.jupiter.api.AfterEach;
66 import org.junit.jupiter.api.BeforeEach;
67 import org.junit.jupiter.api.Disabled;
68 import org.junit.jupiter.api.Test;
69 import org.junit.jupiter.api.Timeout;
70
71
72
73 public class TestGenericObjectPool extends TestBaseObjectPool {
74
75 private final class ConcurrentBorrowAndEvictThread extends Thread {
76 private final boolean borrow;
77 public String obj;
78
79 public ConcurrentBorrowAndEvictThread(final boolean borrow) {
80 this.borrow = borrow;
81 }
82
83 @Override
84 public void run() {
85 try {
86 if (borrow) {
87 obj = genericObjectPool.borrowObject();
88 } else {
89 genericObjectPool.evict();
90 }
91 } catch (final Exception e) {
92
93 }
94 }
95 }
96
97 private static final class CreateErrorFactory extends BasePooledObjectFactory<String> {
98
99 private final Semaphore semaphore = new Semaphore(0);
100
101 @Override
102 public String create() throws InterruptedException {
103 semaphore.acquire();
104 throw new UnknownError("wiggle");
105 }
106
107 public boolean hasQueuedThreads() {
108 return semaphore.hasQueuedThreads();
109 }
110
111 public void release() {
112 semaphore.release();
113 }
114
115 @Override
116 public PooledObject<String> wrap(final String obj) {
117 return new DefaultPooledObject<>(obj);
118 }
119 }
120
121 private static final class CreateFailFactory extends BasePooledObjectFactory<String> {
122
123 private final Semaphore semaphore = new Semaphore(0);
124
125 @Override
126 public String create() throws InterruptedException {
127 semaphore.acquire();
128 throw new UnsupportedCharsetException("wibble");
129 }
130
131 public boolean hasQueuedThreads() {
132 return semaphore.hasQueuedThreads();
133 }
134
135 public void release() {
136 semaphore.release();
137 }
138
139 @Override
140 public PooledObject<String> wrap(final String obj) {
141 return new DefaultPooledObject<>(obj);
142 }
143 }
144
145 private static final class DummyFactory
146 extends BasePooledObjectFactory<Object> {
147 @Override
148 public Object create() {
149 return null;
150 }
151 @Override
152 public PooledObject<Object> wrap(final Object value) {
153 return new DefaultPooledObject<>(value);
154 }
155 }
156
157 private static final class EvictionThread<T> extends Thread {
158
159 private final GenericObjectPool<T> pool;
160
161 public EvictionThread(final GenericObjectPool<T> pool) {
162 this.pool = pool;
163 }
164
165 @Override
166 public void run() {
167 try {
168 pool.evict();
169 } catch (final Exception e) {
170
171 }
172 }
173 }
174
175
176
177
178
179
180 private static final class HashSetFactory
181 extends BasePooledObjectFactory<HashSet<String>> {
182 @Override
183 public HashSet<String> create() {
184 return new HashSet<>();
185 }
186 @Override
187 public PooledObject<HashSet<String>> wrap(final HashSet<String> value) {
188 return new DefaultPooledObject<>(value);
189 }
190 }
191
192
193
194
195 static class InvalidateThread implements Runnable {
196 private final String obj;
197 private final ObjectPool<String> pool;
198 private boolean done;
199 public InvalidateThread(final ObjectPool<String> pool, final String obj) {
200 this.obj = obj;
201 this.pool = pool;
202 }
203 public boolean complete() {
204 return done;
205 }
206 @Override
207 public void run() {
208 try {
209 pool.invalidateObject(obj);
210 } catch (final IllegalStateException ex) {
211
212 } catch (final Exception ex) {
213 fail("Unexpected exception " + ex.toString());
214 } finally {
215 done = true;
216 }
217 }
218 }
219
220 private static final class InvalidFactory
221 extends BasePooledObjectFactory<Object> {
222
223 @Override
224 public Object create() {
225 return new Object();
226 }
227 @Override
228 public boolean validateObject(final PooledObject<Object> obj) {
229 Waiter.sleepQuietly(1000);
230 return false;
231 }
232
233 @Override
234 public PooledObject<Object> wrap(final Object value) {
235 return new DefaultPooledObject<>(value);
236 }
237 }
238
239 public static class SimpleFactory implements PooledObjectFactory<String> {
240 int makeCounter;
241
242 int activationCounter;
243
244 int validateCounter;
245
246 int activeCount;
247
248 boolean evenValid = true;
249
250 boolean oddValid = true;
251
252 boolean exceptionOnPassivate;
253
254 boolean exceptionOnActivate;
255
256 boolean exceptionOnDestroy;
257
258 boolean exceptionOnValidate;
259
260 boolean enableValidation = true;
261
262 long destroyLatency;
263
264 long makeLatency;
265
266 long validateLatency;
267
268 int maxTotal = Integer.MAX_VALUE;
269
270 public SimpleFactory() {
271 this(true);
272 }
273
274 public SimpleFactory(final boolean valid) {
275 this(valid, valid);
276 }
277
278 public SimpleFactory(final boolean evalid, final boolean ovalid) {
279 evenValid = evalid;
280 oddValid = ovalid;
281 }
282
283 @Override
284 public void activateObject(final PooledObject<String> obj) throws Exception {
285 final boolean hurl;
286 final boolean evenTest;
287 final boolean oddTest;
288 final int counter;
289 synchronized (this) {
290 hurl = exceptionOnActivate;
291 evenTest = evenValid;
292 oddTest = oddValid;
293 counter = activationCounter++;
294 }
295 if (hurl && !(counter % 2 == 0 ? evenTest : oddTest)) {
296 throw new Exception();
297 }
298 }
299
300 @Override
301 public void destroyObject(final PooledObject<String> obj) throws Exception {
302 final long waitLatency;
303 final boolean hurl;
304 synchronized (this) {
305 waitLatency = destroyLatency;
306 hurl = exceptionOnDestroy;
307 }
308 if (waitLatency > 0) {
309 doWait(waitLatency);
310 }
311 synchronized (this) {
312 activeCount--;
313 }
314 if (hurl) {
315 throw new Exception();
316 }
317 }
318
319 private void doWait(final long latency) {
320 Waiter.sleepQuietly(latency);
321 }
322
323 public synchronized int getMakeCounter() {
324 return makeCounter;
325 }
326
327 public synchronized boolean isThrowExceptionOnActivate() {
328 return exceptionOnActivate;
329 }
330
331 public synchronized boolean isValidationEnabled() {
332 return enableValidation;
333 }
334
335 @Override
336 public PooledObject<String> makeObject() {
337 final long waitLatency;
338 synchronized (this) {
339 activeCount++;
340 if (activeCount > maxTotal) {
341 throw new IllegalStateException(
342 "Too many active instances: " + activeCount);
343 }
344 waitLatency = makeLatency;
345 }
346 if (waitLatency > 0) {
347 doWait(waitLatency);
348 }
349 final int counter;
350 synchronized (this) {
351 counter = makeCounter++;
352 }
353 return new DefaultPooledObject<>(String.valueOf(counter));
354 }
355
356 @Override
357 public void passivateObject(final PooledObject<String> obj) throws Exception {
358 final boolean hurl;
359 synchronized (this) {
360 hurl = exceptionOnPassivate;
361 }
362 if (hurl) {
363 throw new Exception();
364 }
365 }
366
367 public synchronized void setDestroyLatency(final long destroyLatency) {
368 this.destroyLatency = destroyLatency;
369 }
370
371 public synchronized void setEvenValid(final boolean valid) {
372 evenValid = valid;
373 }
374
375 public synchronized void setMakeLatency(final long makeLatency) {
376 this.makeLatency = makeLatency;
377 }
378
379 public synchronized void setMaxTotal(final int maxTotal) {
380 this.maxTotal = maxTotal;
381 }
382
383 public synchronized void setOddValid(final boolean valid) {
384 oddValid = valid;
385 }
386
387 public synchronized void setThrowExceptionOnActivate(final boolean b) {
388 exceptionOnActivate = b;
389 }
390
391 public synchronized void setThrowExceptionOnDestroy(final boolean b) {
392 exceptionOnDestroy = b;
393 }
394
395 public synchronized void setThrowExceptionOnPassivate(final boolean bool) {
396 exceptionOnPassivate = bool;
397 }
398
399 public synchronized void setThrowExceptionOnValidate(final boolean bool) {
400 exceptionOnValidate = bool;
401 }
402
403 public synchronized void setValid(final boolean valid) {
404 setEvenValid(valid);
405 setOddValid(valid);
406 }
407
408 public synchronized void setValidateLatency(final long validateLatency) {
409 this.validateLatency = validateLatency;
410 }
411
412 public synchronized void setValidationEnabled(final boolean b) {
413 enableValidation = b;
414 }
415
416 @Override
417 public boolean validateObject(final PooledObject<String> obj) {
418 final boolean validate;
419 final boolean throwException;
420 final boolean evenTest;
421 final boolean oddTest;
422 final long waitLatency;
423 final int counter;
424 synchronized (this) {
425 validate = enableValidation;
426 throwException = exceptionOnValidate;
427 evenTest = evenValid;
428 oddTest = oddValid;
429 counter = validateCounter++;
430 waitLatency = validateLatency;
431 }
432 if (waitLatency > 0) {
433 doWait(waitLatency);
434 }
435 if (throwException) {
436 throw new RuntimeException("validation failed");
437 }
438 if (validate) {
439 return counter%2 == 0 ? evenTest : oddTest;
440 }
441 return true;
442 }
443 }
444
445 public static class TestEvictionPolicy<T> implements EvictionPolicy<T> {
446
447 private final AtomicInteger callCount = new AtomicInteger();
448
449 @Override
450 public boolean evict(final EvictionConfig config, final PooledObject<T> underTest,
451 final int idleCount) {
452 return callCount.incrementAndGet() > 1500;
453 }
454 }
455
456 static class TestThread<T> implements Runnable {
457
458
459 private final Random random;
460
461
462 private final ObjectPool<T> pool;
463
464
465 private final int iter;
466
467
468 private final int startDelay;
469
470
471 private final int holdTime;
472
473
474 private final boolean randomDelay;
475
476
477 private final Object expectedObject;
478
479 private volatile boolean complete;
480 private volatile boolean failed;
481 private volatile Throwable error;
482
483 public TestThread(final ObjectPool<T> pool) {
484 this(pool, 100, 50, true, null);
485 }
486
487 public TestThread(final ObjectPool<T> pool, final int iter) {
488 this(pool, iter, 50, true, null);
489 }
490
491 public TestThread(final ObjectPool<T> pool, final int iter, final int delay) {
492 this(pool, iter, delay, true, null);
493 }
494
495 public TestThread(final ObjectPool<T> pool, final int iter, final int delay,
496 final boolean randomDelay) {
497 this(pool, iter, delay, randomDelay, null);
498 }
499
500 public TestThread(final ObjectPool<T> pool, final int iter, final int delay,
501 final boolean randomDelay, final Object obj) {
502 this(pool, iter, delay, delay, randomDelay, obj);
503 }
504
505 public TestThread(final ObjectPool<T> pool, final int iter, final int startDelay,
506 final int holdTime, final boolean randomDelay, final Object obj) {
507 this.pool = pool;
508 this.iter = iter;
509 this.startDelay = startDelay;
510 this.holdTime = holdTime;
511 this.randomDelay = randomDelay;
512 this.random = this.randomDelay ? new Random() : null;
513 this.expectedObject = obj;
514 }
515
516 public boolean complete() {
517 return complete;
518 }
519
520 public boolean failed() {
521 return failed;
522 }
523
524 @Override
525 public void run() {
526 for (int i = 0; i < iter; i++) {
527 final long actualStartDelay = randomDelay ? (long) random.nextInt(startDelay) : startDelay;
528 final long actualHoldTime = randomDelay ? (long) random.nextInt(holdTime) : holdTime;
529 Waiter.sleepQuietly(actualStartDelay);
530 T obj = null;
531 try {
532 obj = pool.borrowObject();
533 } catch (final Exception e) {
534 error = e;
535 failed = true;
536 complete = true;
537 break;
538 }
539
540 if (expectedObject != null && !expectedObject.equals(obj)) {
541 error = new Throwable("Expected: " + expectedObject + " found: " + obj);
542 failed = true;
543 complete = true;
544 break;
545 }
546
547 Waiter.sleepQuietly(actualHoldTime);
548 try {
549 pool.returnObject(obj);
550 } catch (final Exception e) {
551 error = e;
552 failed = true;
553 complete = true;
554 break;
555 }
556 }
557 complete = true;
558 }
559 }
560
561
562
563
564
565 static class WaitingTestThread extends Thread {
566 private final GenericObjectPool<String> pool;
567 private final long pause;
568 private Throwable thrown;
569
570 private long preBorrowMillis;
571 private long postBorrowMillis;
572 private long postReturnMillis;
573 private long endedMillis;
574 private String objectId;
575
576 public WaitingTestThread(final GenericObjectPool<String> pool, final long pause) {
577 this.pool = pool;
578 this.pause = pause;
579 this.thrown = null;
580 }
581
582 @Override
583 public void run() {
584 try {
585 preBorrowMillis = System.currentTimeMillis();
586 final String obj = pool.borrowObject();
587 objectId = obj;
588 postBorrowMillis = System.currentTimeMillis();
589 Thread.sleep(pause);
590 pool.returnObject(obj);
591 postReturnMillis = System.currentTimeMillis();
592 } catch (final Throwable e) {
593 thrown = e;
594 } finally{
595 endedMillis = System.currentTimeMillis();
596 }
597 }
598 }
599
600 private static final boolean DISPLAY_THREAD_DETAILS=
601 Boolean.getBoolean("TestGenericObjectPool.display.thread.details");
602
603
604
605
606 protected GenericObjectPool<String> genericObjectPool;
607
608 private SimpleFactory simpleFactory;
609
610 @SuppressWarnings("deprecation")
611 private void assertConfiguration(final GenericObjectPoolConfig<?> expected, final GenericObjectPool<?> actual) {
612 assertEquals(Boolean.valueOf(expected.getTestOnCreate()), Boolean.valueOf(actual.getTestOnCreate()),
613 "testOnCreate");
614 assertEquals(Boolean.valueOf(expected.getTestOnBorrow()), Boolean.valueOf(actual.getTestOnBorrow()),
615 "testOnBorrow");
616 assertEquals(Boolean.valueOf(expected.getTestOnReturn()), Boolean.valueOf(actual.getTestOnReturn()),
617 "testOnReturn");
618 assertEquals(Boolean.valueOf(expected.getTestWhileIdle()), Boolean.valueOf(actual.getTestWhileIdle()),
619 "testWhileIdle");
620 assertEquals(Boolean.valueOf(expected.getBlockWhenExhausted()), Boolean.valueOf(actual.getBlockWhenExhausted()),
621 "whenExhaustedAction");
622 assertEquals(expected.getMaxTotal(), actual.getMaxTotal(), "maxTotal");
623 assertEquals(expected.getMaxIdle(), actual.getMaxIdle(), "maxIdle");
624 assertEquals(expected.getMaxWaitMillis(), actual.getMaxWaitMillis(), "maxWaitDuration");
625 assertEquals(expected.getMaxWaitDuration(), actual.getMaxWaitDuration(), "maxWaitDuration");
626 assertEquals(expected.getMinEvictableIdleTimeMillis(), actual.getMinEvictableIdleTimeMillis(),
627 "minEvictableIdleTimeMillis");
628 assertEquals(expected.getMinEvictableIdleTime(), actual.getMinEvictableIdleTime(),
629 "minEvictableIdleTime");
630 assertEquals(expected.getMinEvictableIdleDuration(), actual.getMinEvictableIdleDuration(),
631 "minEvictableIdleDuration");
632 assertEquals(expected.getNumTestsPerEvictionRun(), actual.getNumTestsPerEvictionRun(),
633 "numTestsPerEvictionRun");
634 assertEquals(expected.getEvictorShutdownTimeoutDuration(), actual.getEvictorShutdownTimeoutDuration(),
635 "evictorShutdownTimeoutDuration");
636 assertEquals(expected.getEvictorShutdownTimeoutMillis(), actual.getEvictorShutdownTimeoutMillis(),
637 "evictorShutdownTimeoutMillis");
638 assertEquals(expected.getEvictorShutdownTimeout(), actual.getEvictorShutdownTimeout(),
639 "evictorShutdownTimeout");
640 assertEquals(expected.getTimeBetweenEvictionRunsMillis(), actual.getTimeBetweenEvictionRunsMillis(),
641 "timeBetweenEvictionRunsMillis");
642 assertEquals(expected.getDurationBetweenEvictionRuns(), actual.getTimeBetweenEvictionRuns(),
643 "timeBetweenEvictionRuns");
644 assertEquals(expected.getTimeBetweenEvictionRuns(), actual.getTimeBetweenEvictionRuns(),
645 "timeBetweenEvictionRuns");
646 }
647
648 private void checkEvict(final boolean lifo) throws Exception {
649
650 genericObjectPool.setSoftMinEvictableIdleDuration(Duration.ofMillis(10));
651 genericObjectPool.setSoftMinEvictableIdle(Duration.ofMillis(10));
652 genericObjectPool.setSoftMinEvictableIdleTime(Duration.ofMillis(10));
653 genericObjectPool.setMinIdle(2);
654 genericObjectPool.setTestWhileIdle(true);
655 genericObjectPool.setLifo(lifo);
656 genericObjectPool.addObjects(5);
657 genericObjectPool.evict();
658 simpleFactory.setEvenValid(false);
659 simpleFactory.setOddValid(false);
660 simpleFactory.setThrowExceptionOnActivate(true);
661 genericObjectPool.evict();
662 genericObjectPool.addObjects(5);
663 simpleFactory.setThrowExceptionOnActivate(false);
664 simpleFactory.setThrowExceptionOnPassivate(true);
665 genericObjectPool.evict();
666 simpleFactory.setThrowExceptionOnPassivate(false);
667 simpleFactory.setEvenValid(true);
668 simpleFactory.setOddValid(true);
669 Thread.sleep(125);
670 genericObjectPool.evict();
671 assertEquals(2, genericObjectPool.getNumIdle());
672 }
673
674 private void checkEvictionOrder(final boolean lifo) throws Exception {
675 checkEvictionOrderPart1(lifo);
676 tearDown();
677 setUp();
678 checkEvictionOrderPart2(lifo);
679 }
680
681 private void checkEvictionOrderPart1(final boolean lifo) throws Exception {
682 genericObjectPool.setNumTestsPerEvictionRun(2);
683 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100));
684 genericObjectPool.setLifo(lifo);
685 for (int i = 0; i < 5; i++) {
686 genericObjectPool.addObject();
687 Thread.sleep(100);
688 }
689
690 genericObjectPool.evict();
691 final Object obj = genericObjectPool.borrowObject();
692 assertNotEquals("0", obj, "oldest not evicted");
693 assertNotEquals("1", obj, "second oldest not evicted");
694
695 assertEquals(lifo ? "4" : "2", obj, "Wrong instance returned");
696 }
697
698 private void checkEvictionOrderPart2(final boolean lifo) throws Exception {
699
700 genericObjectPool.setNumTestsPerEvictionRun(2);
701 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100));
702 genericObjectPool.setLifo(lifo);
703 for (int i = 0; i < 5; i++) {
704 genericObjectPool.addObject();
705 Thread.sleep(100);
706 }
707 genericObjectPool.evict();
708 genericObjectPool.evict();
709 final Object obj = genericObjectPool.borrowObject();
710 assertEquals("4", obj, "Wrong instance remaining in pool");
711 }
712
713 private void checkEvictorVisiting(final boolean lifo) throws Exception {
714 VisitTracker<Object> obj;
715 VisitTrackerFactory<Object> trackerFactory = new VisitTrackerFactory<>();
716 try (GenericObjectPool<VisitTracker<Object>> trackerPool = new GenericObjectPool<>(trackerFactory)) {
717 trackerPool.setNumTestsPerEvictionRun(2);
718 trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1));
719 trackerPool.setTestWhileIdle(true);
720 trackerPool.setLifo(lifo);
721 trackerPool.setTestOnReturn(false);
722 trackerPool.setTestOnBorrow(false);
723 for (int i = 0; i < 8; i++) {
724 trackerPool.addObject();
725 }
726 trackerPool.evict();
727 obj = trackerPool.borrowObject();
728 trackerPool.returnObject(obj);
729 obj = trackerPool.borrowObject();
730 trackerPool.returnObject(obj);
731
732
733
734 trackerPool.evict();
735 for (int i = 0; i < 8; i++) {
736 final VisitTracker<Object> tracker = trackerPool.borrowObject();
737 if (tracker.getId() >= 4) {
738 assertEquals(0, tracker.getValidateCount(), "Unexpected instance visited " + tracker.getId());
739 } else {
740 assertEquals(1, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times.");
741 }
742 }
743 }
744
745 trackerFactory = new VisitTrackerFactory<>();
746 try (GenericObjectPool<VisitTracker<Object>> trackerPool = new GenericObjectPool<>(trackerFactory)) {
747 trackerPool.setNumTestsPerEvictionRun(3);
748 trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1));
749 trackerPool.setTestWhileIdle(true);
750 trackerPool.setLifo(lifo);
751 trackerPool.setTestOnReturn(false);
752 trackerPool.setTestOnBorrow(false);
753 for (int i = 0; i < 8; i++) {
754 trackerPool.addObject();
755 }
756 trackerPool.evict();
757 trackerPool.evict();
758 obj = trackerPool.borrowObject();
759 trackerPool.returnObject(obj);
760 obj = trackerPool.borrowObject();
761 trackerPool.returnObject(obj);
762 obj = trackerPool.borrowObject();
763 trackerPool.returnObject(obj);
764
765
766
767
768 trackerPool.evict();
769
770 for (int i = 0; i < 8; i++) {
771 final VisitTracker<Object> tracker = trackerPool.borrowObject();
772 if (tracker.getId() != 0) {
773 assertEquals(1, tracker.getValidateCount(),
774 "Instance " + tracker.getId() + " visited wrong number of times.");
775 } else {
776 assertEquals(2, tracker.getValidateCount(),
777 "Instance " + tracker.getId() + " visited wrong number of times.");
778 }
779 }
780 }
781
782
783
784 final int[] smallPrimes = { 2, 3, 5, 7 };
785 final Random random = new Random();
786 random.setSeed(System.currentTimeMillis());
787 for (int i = 0; i < 4; i++) {
788 for (int j = 0; j < 5; j++) {
789 try (GenericObjectPool<VisitTracker<Object>> trackerPool = new GenericObjectPool<>(trackerFactory)) {
790 trackerPool.setNumTestsPerEvictionRun(smallPrimes[i]);
791 trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1));
792 trackerPool.setTestWhileIdle(true);
793 trackerPool.setLifo(lifo);
794 trackerPool.setTestOnReturn(false);
795 trackerPool.setTestOnBorrow(false);
796 trackerPool.setMaxIdle(-1);
797 final int instanceCount = 10 + random.nextInt(20);
798 trackerPool.setMaxTotal(instanceCount);
799 for (int k = 0; k < instanceCount; k++) {
800 trackerPool.addObject();
801 }
802
803
804 final int runs = 10 + random.nextInt(50);
805 for (int k = 0; k < runs; k++) {
806 trackerPool.evict();
807 }
808
809
810 final int cycleCount = runs * trackerPool.getNumTestsPerEvictionRun() / instanceCount;
811
812
813
814 VisitTracker<Object> tracker = null;
815 int visitCount = 0;
816 for (int k = 0; k < instanceCount; k++) {
817 tracker = trackerPool.borrowObject();
818 assertTrue(trackerPool.getNumActive() <= trackerPool.getMaxTotal());
819 visitCount = tracker.getValidateCount();
820 assertTrue(visitCount >= cycleCount && visitCount <= cycleCount + 1);
821 }
822 }
823 }
824 }
825 }
826
827 private BasePooledObjectFactory<String> createDefaultPooledObjectFactory() {
828 return new BasePooledObjectFactory<String>() {
829 @Override
830 public String create() {
831
832 return null;
833 }
834
835 @Override
836 public PooledObject<String> wrap(final String obj) {
837
838 return new DefaultPooledObject<>(obj);
839 }
840 };
841 }
842
843 private BasePooledObjectFactory<String> createNullPooledObjectFactory() {
844 return new BasePooledObjectFactory<String>() {
845 @Override
846 public String create() {
847
848 return null;
849 }
850
851 @Override
852 public PooledObject<String> wrap(final String obj) {
853
854 return null;
855 }
856 };
857 }
858
859 private BasePooledObjectFactory<String> createSlowObjectFactory(final Duration sleepDuration) {
860 return new BasePooledObjectFactory<String>() {
861 @Override
862 public String create() throws InterruptedException {
863 ThreadUtils.sleep(sleepDuration);
864 return "created";
865 }
866
867 @Override
868 public PooledObject<String> wrap(final String obj) {
869
870 return new DefaultPooledObject<>(obj);
871 }
872 };
873 }
874
875 @Override
876 protected Object getNthObject(final int n) {
877 return String.valueOf(n);
878 }
879
880 @Override
881 protected boolean isFifo() {
882 return false;
883 }
884
885 @Override
886 protected boolean isLifo() {
887 return true;
888 }
889
890 @Override
891 protected ObjectPool<String> makeEmptyPool(final int minCap) {
892 final GenericObjectPool<String> mtPool = new GenericObjectPool<>(new SimpleFactory());
893 mtPool.setMaxTotal(minCap);
894 mtPool.setMaxIdle(minCap);
895 return mtPool;
896 }
897
898 @Override
899 protected <E extends Exception> ObjectPool<Object> makeEmptyPool(final PooledObjectFactory<Object> fac) {
900 return new GenericObjectPool<>(fac);
901 }
902
903
904
905
906
907
908 private <T> void runTestThreads(final int numThreads, final int iterations, final int delay, final GenericObjectPool<T> testPool) {
909 final TestThread<T>[] threads = new TestThread[numThreads];
910 for (int i = 0; i < numThreads; i++) {
911 threads[i] = new TestThread<>(testPool, iterations, delay);
912 final Thread t = new Thread(threads[i]);
913 t.start();
914 }
915 for (int i = 0; i < numThreads; i++) {
916 while (!threads[i].complete()) {
917 Waiter.sleepQuietly(500L);
918 }
919 if (threads[i].failed()) {
920 fail("Thread " + i + " failed: " + threads[i].error.toString());
921 }
922 }
923 }
924
925 @BeforeEach
926 public void setUp() {
927 simpleFactory = new SimpleFactory();
928 genericObjectPool = new GenericObjectPool<>(simpleFactory);
929 }
930
931 @AfterEach
932 public void tearDown() throws Exception {
933 final ObjectName jmxName = genericObjectPool.getJmxName();
934 final String poolName = Objects.toString(jmxName, null);
935
936 genericObjectPool.clear();
937 genericObjectPool.close();
938 genericObjectPool = null;
939 simpleFactory = null;
940
941 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
942 final Set<ObjectName> result = mbs.queryNames(new ObjectName("org.apache.commoms.pool2:type=GenericObjectPool,*"), null);
943
944 final int registeredPoolCount = result.size();
945 final StringBuilder msg = new StringBuilder("Current pool is: ");
946 msg.append(poolName);
947 msg.append(" Still open pools are: ");
948 for (final ObjectName name : result) {
949
950 msg.append(name.toString());
951 msg.append(" created via\n");
952 msg.append(mbs.getAttribute(name, "CreationStackTrace"));
953 msg.append('\n');
954 mbs.unregisterMBean(name);
955 }
956 assertEquals(0, registeredPoolCount, msg.toString());
957
958
959 Thread.yield();
960 if (EvictionTimer.getExecutor() != null) {
961 Thread.sleep(1000);
962 }
963 assertNull(EvictionTimer.getExecutor(), "EvictionTimer.getExecutor()");
964 }
965
966
967
968
969
970
971
972
973
974 @SuppressWarnings("deprecation")
975 @Test
976 public void testAbandonedPool() throws Exception {
977 final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
978 config.setJmxEnabled(false);
979 GenericObjectPool<String> abandoned = new GenericObjectPool<>(simpleFactory, config);
980 abandoned.setDurationBetweenEvictionRuns(Duration.ofMillis(100));
981 assertEquals(abandoned.getRemoveAbandonedTimeout(), abandoned.getRemoveAbandonedTimeoutDuration().getSeconds());
982
983
984 final WeakReference<GenericObjectPool<String>> ref = new WeakReference<>(abandoned);
985 abandoned = null;
986 while (ref.get() != null) {
987 System.gc();
988 Thread.sleep(100);
989 }
990 }
991
992 @Test
993 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
994 public void testAddObject() throws Exception {
995 assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle");
996 genericObjectPool.addObject();
997 assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle");
998 assertEquals(0, genericObjectPool.getNumActive(), "should be zero active");
999 final String obj = genericObjectPool.borrowObject();
1000 assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle");
1001 assertEquals(1, genericObjectPool.getNumActive(), "should be one active");
1002 genericObjectPool.returnObject(obj);
1003 assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle");
1004 assertEquals(0, genericObjectPool.getNumActive(), "should be zero active");
1005 }
1006
1007 @Test
1008 public void testAppendStats() {
1009 assertFalse(genericObjectPool.getMessageStatistics());
1010 assertEquals("foo", genericObjectPool.appendStats("foo"));
1011 try (final GenericObjectPool<?> pool = new GenericObjectPool<>(new SimpleFactory())) {
1012 pool.setMessagesStatistics(true);
1013 assertNotEquals("foo", pool.appendStats("foo"));
1014 pool.setMessagesStatistics(false);
1015 assertEquals("foo", pool.appendStats("foo"));
1016 }
1017 }
1018
1019
1020
1021
1022
1023
1024 @SuppressWarnings({
1025 "rawtypes", "unchecked"
1026 })
1027 @Test
1028 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1029 public void testBorrowObjectFairness() throws Exception {
1030
1031 final int numThreads = 40;
1032 final int maxTotal = 40;
1033
1034 final GenericObjectPoolConfig config = new GenericObjectPoolConfig();
1035 config.setMaxTotal(maxTotal);
1036 config.setMaxIdle(maxTotal);
1037 config.setFairness(true);
1038 config.setLifo(false);
1039
1040 genericObjectPool = new GenericObjectPool(simpleFactory, config);
1041
1042
1043 final String[] objects = new String[maxTotal];
1044 for (int i = 0; i < maxTotal; i++) {
1045 objects[i] = genericObjectPool.borrowObject();
1046 }
1047
1048
1049 final TestThread[] threads = new TestThread[numThreads];
1050 for(int i=0;i<numThreads;i++) {
1051 threads[i] = new TestThread(genericObjectPool, 1, 0, 2000, false, String.valueOf(i % maxTotal));
1052 final Thread t = new Thread(threads[i]);
1053 t.start();
1054
1055 try {
1056 Thread.sleep(10);
1057 } catch (final InterruptedException e) {
1058 fail(e.toString());
1059 }
1060 }
1061
1062
1063 for (int i = 0; i < maxTotal; i++) {
1064 genericObjectPool.returnObject(objects[i]);
1065 }
1066
1067
1068 for (int i = 0; i < numThreads; i++) {
1069 while (!threads[i].complete()) {
1070 Waiter.sleepQuietly(500L);
1071 }
1072 if (threads[i].failed()) {
1073 fail("Thread " + i + " failed: " + threads[i].error.toString());
1074 }
1075 }
1076 }
1077
1078 @Test
1079 @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS)
1080 public void testBorrowObjectOverrideMaxWaitLarge() throws Exception {
1081 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) {
1082 pool.setMaxTotal(1);
1083 pool.setMaxWait(Duration.ofMillis(1_000));
1084 pool.setBlockWhenExhausted(false);
1085
1086 final WaitingTestThread thread1 = new WaitingTestThread(pool, 0);
1087 thread1.start();
1088
1089 Thread.sleep(100);
1090
1091 final Duration d = DurationUtils.of(() -> assertThrows(NoSuchElementException.class, () -> pool.borrowObject(Duration.ofMillis(1)),
1092 "borrowObject must fail quickly due to timeout parameter"));
1093 final long millis = d.toMillis();
1094 final long nanos = d.toNanos();
1095 assertTrue(nanos >= 0, () -> "borrowObject(Duration) argument not respected: " + nanos);
1096 assertTrue(millis >= 0, () -> "borrowObject(Duration) argument not respected: " + millis);
1097 assertTrue(millis < 50, () -> "borrowObject(Duration) argument not respected: " + millis);
1098 }
1099 }
1100
1101 @Test
1102 @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS)
1103 public void testBorrowObjectOverrideMaxWaitSmall() throws Exception {
1104 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) {
1105 pool.setMaxTotal(1);
1106 pool.setMaxWait(Duration.ofMillis(1));
1107 pool.setBlockWhenExhausted(false);
1108
1109 final WaitingTestThread thread1 = new WaitingTestThread(pool, 0);
1110 thread1.start();
1111
1112 Thread.sleep(100);
1113
1114 final Duration d = DurationUtils.of(() -> assertThrows(NoSuchElementException.class, () -> pool.borrowObject(Duration.ofMillis(500)),
1115 "borrowObject must fail slowly due to timeout parameter"));
1116 final long millis = d.toMillis();
1117 final long nanos = d.toNanos();
1118 assertTrue(nanos >= 0, () -> "borrowObject(Duration) argument not respected: " + nanos);
1119 assertTrue(millis >= 0, () -> "borrowObject(Duration) argument not respected: " + millis);
1120 assertTrue(millis < 600, () -> "borrowObject(Duration) argument not respected: " + millis);
1121 assertTrue(millis > 490, () -> "borrowObject(Duration) argument not respected: " + millis);
1122 }
1123 }
1124
1125 @Test
1126 public void testBorrowTimings() throws Exception {
1127
1128 final String object = genericObjectPool.borrowObject();
1129 final PooledObject<String> po = genericObjectPool.getPooledObject(object);
1130
1131
1132
1133
1134
1135 final Instant lastBorrowInstant1 = po.getLastBorrowInstant();
1136 final Instant lastReturnInstant1 = po.getLastReturnInstant();
1137 final Instant lastUsedInstant1 = po.getLastUsedInstant();
1138
1139 assertTrue(po.getCreateInstant().compareTo(lastBorrowInstant1) <= 0);
1140 assertTrue(po.getCreateInstant().compareTo(lastReturnInstant1) <= 0);
1141 assertTrue(po.getCreateInstant().compareTo(lastUsedInstant1) <= 0);
1142
1143 assertTrue(po.getCreateTime() <= lastBorrowInstant1.toEpochMilli());
1144 assertTrue(po.getCreateTime() <= lastReturnInstant1.toEpochMilli());
1145 assertTrue(po.getCreateTime() <= lastUsedInstant1.toEpochMilli());
1146
1147
1148
1149 Thread.sleep(200);
1150
1151 assertFalse(po.getActiveDuration().isNegative());
1152 assertFalse(po.getActiveDuration().isZero());
1153
1154 assertTrue(Duration.ZERO.compareTo(Duration.ZERO.plusNanos(1)) <= 0);
1155 assertTrue(po.getActiveDuration().compareTo(po.getIdleDuration()) <= 0);
1156
1157 assertTrue(po.getActiveDuration().toMillis() <= po.getActiveTimeMillis());
1158 assertTrue(po.getActiveDuration().compareTo(po.getIdleDuration()) <= 0);
1159
1160
1161 assertTrue(po.getActiveDuration().compareTo(po.getIdleTime()) <= 0);
1162 assertTrue(po.getActiveDuration().toMillis() <= po.getIdleTimeMillis());
1163
1164 assertTrue(po.getCreateInstant().compareTo(po.getLastBorrowInstant()) <= 0);
1165 assertTrue(po.getCreateInstant().compareTo(po.getLastReturnInstant()) <= 0);
1166 assertTrue(po.getCreateInstant().compareTo(po.getLastUsedInstant()) <= 0);
1167
1168 assertTrue(lastBorrowInstant1.compareTo(po.getLastBorrowInstant()) <= 0);
1169 assertTrue(lastReturnInstant1.compareTo(po.getLastReturnInstant()) <= 0);
1170 assertTrue(lastUsedInstant1.compareTo(po.getLastUsedInstant()) <= 0);
1171
1172 genericObjectPool.returnObject(object);
1173
1174 assertFalse(po.getActiveDuration().isNegative());
1175 assertFalse(po.getActiveDuration().isZero());
1176 assertTrue(po.getActiveDuration().toMillis() <= po.getActiveTimeMillis());
1177 assertTrue(po.getActiveDuration().compareTo(po.getActiveTime()) <= 0);
1178
1179 assertTrue(lastBorrowInstant1.compareTo(po.getLastBorrowInstant()) <= 0);
1180 assertTrue(lastReturnInstant1.compareTo(po.getLastReturnInstant()) <= 0);
1181 assertTrue(lastUsedInstant1.compareTo(po.getLastUsedInstant()) <= 0);
1182 }
1183
1184
1185
1186
1187
1188
1189 @Test
1190 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1191 public void testBrokenFactoryShouldNotBlockPool() throws Exception {
1192 final int maxTotal = 1;
1193
1194 simpleFactory.setMaxTotal(maxTotal);
1195 genericObjectPool.setMaxTotal(maxTotal);
1196 genericObjectPool.setBlockWhenExhausted(true);
1197 genericObjectPool.setTestOnBorrow(true);
1198
1199
1200
1201 String obj = null;
1202 Exception ex = null;
1203 simpleFactory.setValid(false);
1204 try {
1205 obj = genericObjectPool.borrowObject();
1206 } catch (final Exception e) {
1207 ex = e;
1208 }
1209
1210 assertNotNull(ex);
1211 assertInstanceOf(NoSuchElementException.class, ex);
1212 assertNull(obj);
1213
1214
1215 simpleFactory.setValid(true);
1216
1217
1218 obj = genericObjectPool.borrowObject();
1219 assertNotNull(obj);
1220 genericObjectPool.returnObject(obj);
1221 }
1222
1223
1224 @Test
1225 public void testClientWaitStats() throws Exception {
1226 final SimpleFactory factory = new SimpleFactory();
1227
1228 factory.setMakeLatency(200);
1229 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory, new GenericObjectPoolConfig<>())) {
1230 final String s = pool.borrowObject();
1231
1232
1233 assertTrue(pool.getMaxBorrowWaitTimeMillis() >= 100);
1234 assertTrue(pool.getMeanBorrowWaitTimeMillis() >= 100);
1235 pool.returnObject(s);
1236 pool.borrowObject();
1237
1238 assertTrue(pool.getMaxBorrowWaitTimeMillis() > 100);
1239 assertTrue(pool.getMeanBorrowWaitTimeMillis() < 200);
1240 assertTrue(pool.getMeanBorrowWaitTimeMillis() > 20);
1241 }
1242 }
1243
1244 @Test
1245 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1246 public void testCloseMultiplePools1() {
1247 try (final GenericObjectPool<String> genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) {
1248 genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1249 genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1250 }
1251 genericObjectPool.close();
1252 }
1253
1254 @Test
1255 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1256 public void testCloseMultiplePools2() throws Exception {
1257 try (final GenericObjectPool<String> genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) {
1258
1259 simpleFactory.setDestroyLatency(1000L);
1260
1261 genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1262 genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1263 genericObjectPool.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION);
1264 genericObjectPool2.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION);
1265 genericObjectPool.addObject();
1266 genericObjectPool2.addObject();
1267
1268 }
1269 genericObjectPool.close();
1270 }
1271
1272 @Test
1273 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1274 public void testConcurrentBorrowAndEvict() throws Exception {
1275
1276 genericObjectPool.setMaxTotal(1);
1277 genericObjectPool.addObject();
1278
1279 for (int i = 0; i < 5000; i++) {
1280 final ConcurrentBorrowAndEvictThread one =
1281 new ConcurrentBorrowAndEvictThread(true);
1282 final ConcurrentBorrowAndEvictThread two =
1283 new ConcurrentBorrowAndEvictThread(false);
1284
1285 one.start();
1286 two.start();
1287 one.join();
1288 two.join();
1289
1290 genericObjectPool.returnObject(one.obj);
1291
1292
1293
1294
1295
1296
1297 }
1298 }
1299
1300
1301
1302
1303
1304
1305
1306 @Test
1307 public void testConcurrentInvalidate() throws Exception {
1308
1309 final int nObjects = 1000;
1310 genericObjectPool.setMaxTotal(nObjects);
1311 genericObjectPool.setMaxIdle(nObjects);
1312 final String[] obj = new String[nObjects];
1313 for (int i = 0; i < nObjects; i++) {
1314 obj[i] = genericObjectPool.borrowObject();
1315 }
1316 for (int i = 0; i < nObjects; i++) {
1317 if (i % 2 == 0) {
1318 genericObjectPool.returnObject(obj[i]);
1319 }
1320 }
1321 final int nThreads = 20;
1322 final int nIterations = 60;
1323 final InvalidateThread[] threads = new InvalidateThread[nThreads];
1324
1325 final ArrayList<Integer> targets = new ArrayList<>();
1326 final Random random = new Random();
1327 for (int j = 0; j < nIterations; j++) {
1328
1329 Integer targ = Integer.valueOf(random.nextInt(nObjects));
1330 while (targets.contains(targ)) {
1331 targ = Integer.valueOf(random.nextInt(nObjects));
1332 }
1333 targets.add(targ);
1334
1335 for (int i = 0; i < nThreads; i++) {
1336 threads[i] = new InvalidateThread(genericObjectPool, obj[targ.intValue()]);
1337 }
1338 for (int i = 0; i < nThreads; i++) {
1339 new Thread(threads[i]).start();
1340 }
1341 boolean done = false;
1342 while (!done) {
1343 done = true;
1344 for (int i = 0; i < nThreads; i++) {
1345 done = done && threads[i].complete();
1346 }
1347 Thread.sleep(100);
1348 }
1349 }
1350 assertEquals(nIterations, genericObjectPool.getDestroyedCount());
1351 }
1352
1353 @Test
1354 public void testConstructorNullFactory() {
1355
1356 assertThrows(IllegalArgumentException.class,
1357 () -> new GenericObjectPool<>(null));
1358 }
1359
1360 @Test
1361 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1362 public void testConstructors() {
1363
1364
1365 final int minIdle = 2;
1366 final Duration maxWaitDuration = Duration.ofMillis(3);
1367 final long maxWaitMillis = maxWaitDuration.toMillis();
1368 final int maxIdle = 4;
1369 final int maxTotal = 5;
1370 final Duration minEvictableIdleDuration = Duration.ofMillis(6);
1371 final long minEvictableIdleMillis = minEvictableIdleDuration.toMillis();
1372 final int numTestsPerEvictionRun = 7;
1373 final boolean testOnBorrow = true;
1374 final boolean testOnReturn = true;
1375 final boolean testWhileIdle = true;
1376 final long timeBetweenEvictionRunsMillis = 8;
1377 final boolean blockWhenExhausted = false;
1378 final boolean lifo = false;
1379 final PooledObjectFactory<Object> dummyFactory = new DummyFactory();
1380 try (GenericObjectPool<Object> dummyPool = new GenericObjectPool<>(dummyFactory)) {
1381 assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_IDLE, dummyPool.getMaxIdle());
1382 assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, dummyPool.getMaxWaitMillis());
1383 assertEquals(GenericObjectPoolConfig.DEFAULT_MIN_IDLE, dummyPool.getMinIdle());
1384 assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL, dummyPool.getMaxTotal());
1385 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
1386 dummyPool.getMinEvictableIdleTimeMillis());
1387 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME,
1388 dummyPool.getMinEvictableIdleTime());
1389 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME,
1390 dummyPool.getMinEvictableIdleDuration());
1391 assertEquals(BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
1392 dummyPool.getNumTestsPerEvictionRun());
1393 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW),
1394 Boolean.valueOf(dummyPool.getTestOnBorrow()));
1395 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN),
1396 Boolean.valueOf(dummyPool.getTestOnReturn()));
1397 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE),
1398 Boolean.valueOf(dummyPool.getTestWhileIdle()));
1399 assertEquals(BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS,
1400 dummyPool.getDurationBetweenEvictionRuns());
1401 assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
1402 dummyPool.getTimeBetweenEvictionRunsMillis());
1403 assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS,
1404 dummyPool.getTimeBetweenEvictionRuns());
1405 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED),
1406 Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
1407 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_LIFO), Boolean.valueOf(dummyPool.getLifo()));
1408 }
1409
1410 final GenericObjectPoolConfig<Object> config = new GenericObjectPoolConfig<>();
1411 config.setLifo(lifo);
1412 config.setMaxIdle(maxIdle);
1413 config.setMinIdle(minIdle);
1414 config.setMaxTotal(maxTotal);
1415 config.setMaxWait(maxWaitDuration);
1416 config.setMinEvictableIdleTimeMillis(minEvictableIdleMillis);
1417 assertEquals(minEvictableIdleMillis, config.getMinEvictableIdleTime().toMillis());
1418 config.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
1419 config.setTestOnBorrow(testOnBorrow);
1420 config.setTestOnReturn(testOnReturn);
1421 config.setTestWhileIdle(testWhileIdle);
1422 config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
1423 assertEquals(timeBetweenEvictionRunsMillis, config.getTimeBetweenEvictionRuns().toMillis());
1424 config.setBlockWhenExhausted(blockWhenExhausted);
1425 try (GenericObjectPool<Object> dummyPool = new GenericObjectPool<>(dummyFactory, config)) {
1426 assertEquals(maxIdle, dummyPool.getMaxIdle());
1427 assertEquals(maxWaitDuration, dummyPool.getMaxWaitDuration());
1428 assertEquals(maxWaitMillis, dummyPool.getMaxWaitMillis());
1429 assertEquals(minIdle, dummyPool.getMinIdle());
1430 assertEquals(maxTotal, dummyPool.getMaxTotal());
1431 assertEquals(minEvictableIdleMillis, dummyPool.getMinEvictableIdleTimeMillis());
1432 assertEquals(numTestsPerEvictionRun, dummyPool.getNumTestsPerEvictionRun());
1433 assertEquals(Boolean.valueOf(testOnBorrow), Boolean.valueOf(dummyPool.getTestOnBorrow()));
1434 assertEquals(Boolean.valueOf(testOnReturn), Boolean.valueOf(dummyPool.getTestOnReturn()));
1435 assertEquals(Boolean.valueOf(testWhileIdle), Boolean.valueOf(dummyPool.getTestWhileIdle()));
1436 assertEquals(timeBetweenEvictionRunsMillis, dummyPool.getTimeBetweenEvictionRunsMillis());
1437 assertEquals(Boolean.valueOf(blockWhenExhausted), Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
1438 assertEquals(Boolean.valueOf(lifo), Boolean.valueOf(dummyPool.getLifo()));
1439 }
1440 }
1441
1442 @Test
1443 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1444 public void testDefaultConfiguration() {
1445 assertConfiguration(new GenericObjectPoolConfig<>(),genericObjectPool);
1446 }
1447
1448
1449
1450
1451
1452
1453
1454 @Test
1455 public void testEqualsIndiscernible() throws Exception {
1456 final HashSetFactory factory = new HashSetFactory();
1457 try (final GenericObjectPool<HashSet<String>> pool = new GenericObjectPool<>(factory,
1458 new GenericObjectPoolConfig<>())) {
1459 final HashSet<String> s1 = pool.borrowObject();
1460 final HashSet<String> s2 = pool.borrowObject();
1461 pool.returnObject(s1);
1462 pool.returnObject(s2);
1463 }
1464 }
1465
1466 @Test
1467 public void testErrorFactoryDoesNotBlockThreads() throws Exception {
1468
1469 final CreateErrorFactory factory = new CreateErrorFactory();
1470 try (final GenericObjectPool<String> createFailFactoryPool = new GenericObjectPool<>(factory)) {
1471
1472 createFailFactoryPool.setMaxTotal(1);
1473
1474
1475 final WaitingTestThread thread1 = new WaitingTestThread(createFailFactoryPool, 0);
1476 thread1.start();
1477
1478
1479 while (!factory.hasQueuedThreads()) {
1480 Thread.sleep(200);
1481 }
1482
1483
1484 final WaitingTestThread thread2 = new WaitingTestThread(createFailFactoryPool, 0);
1485 thread2.start();
1486
1487
1488
1489
1490
1491 Thread.sleep(1000);
1492
1493
1494 factory.release();
1495
1496 factory.release();
1497
1498
1499 boolean threadRunning = true;
1500 int count = 0;
1501 while (threadRunning && count < 15) {
1502 threadRunning = thread1.isAlive();
1503 threadRunning = thread2.isAlive();
1504 Thread.sleep(200);
1505 count++;
1506 }
1507 assertFalse(thread1.isAlive());
1508 assertFalse(thread2.isAlive());
1509
1510 assertTrue(thread1.thrown instanceof UnknownError);
1511 assertTrue(thread2.thrown instanceof UnknownError);
1512 }
1513 }
1514
1515
1516
1517
1518
1519
1520
1521 @Test
1522 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1523 public void testEvictAddObjects() throws Exception {
1524 simpleFactory.setMakeLatency(300);
1525 simpleFactory.setMaxTotal(2);
1526 genericObjectPool.setMaxTotal(2);
1527 genericObjectPool.setMinIdle(1);
1528 genericObjectPool.borrowObject();
1529
1530
1531 final TestThread<String> borrower = new TestThread<>(genericObjectPool, 1, 150, false);
1532 final Thread borrowerThread = new Thread(borrower);
1533
1534 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
1535 borrowerThread.start();
1536 borrowerThread.join();
1537 assertFalse(borrower.failed());
1538 }
1539
1540 @Test
1541 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1542 public void testEvictFIFO() throws Exception {
1543 checkEvict(false);
1544 }
1545
1546 @Test
1547 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1548 public void testEviction() throws Exception {
1549 genericObjectPool.setMaxIdle(500);
1550 genericObjectPool.setMaxTotal(500);
1551 genericObjectPool.setNumTestsPerEvictionRun(100);
1552 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250));
1553 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500));
1554 genericObjectPool.setTestWhileIdle(true);
1555
1556 final String[] active = new String[500];
1557 for (int i = 0; i < 500; i++) {
1558 active[i] = genericObjectPool.borrowObject();
1559 }
1560 for (int i = 0; i < 500; i++) {
1561 genericObjectPool.returnObject(active[i]);
1562 }
1563
1564 Waiter.sleepQuietly(1000L);
1565 assertTrue(genericObjectPool.getNumIdle() < 500, "Should be less than 500 idle, found " + genericObjectPool.getNumIdle());
1566 Waiter.sleepQuietly(600L);
1567 assertTrue(genericObjectPool.getNumIdle() < 400, "Should be less than 400 idle, found " + genericObjectPool.getNumIdle());
1568 Waiter.sleepQuietly(600L);
1569 assertTrue(genericObjectPool.getNumIdle() < 300, "Should be less than 300 idle, found " + genericObjectPool.getNumIdle());
1570 Waiter.sleepQuietly(600L);
1571 assertTrue(genericObjectPool.getNumIdle() < 200, "Should be less than 200 idle, found " + genericObjectPool.getNumIdle());
1572 Waiter.sleepQuietly(600L);
1573 assertTrue(genericObjectPool.getNumIdle() < 100, "Should be less than 100 idle, found " + genericObjectPool.getNumIdle());
1574 Waiter.sleepQuietly(600L);
1575 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1576
1577 for (int i = 0; i < 500; i++) {
1578 active[i] = genericObjectPool.borrowObject();
1579 }
1580 for (int i = 0; i < 500; i++) {
1581 genericObjectPool.returnObject(active[i]);
1582 }
1583
1584 Waiter.sleepQuietly(1000L);
1585 assertTrue(genericObjectPool.getNumIdle() < 500, "Should be less than 500 idle, found " + genericObjectPool.getNumIdle());
1586 Waiter.sleepQuietly(600L);
1587 assertTrue(genericObjectPool.getNumIdle() < 400, "Should be less than 400 idle, found " + genericObjectPool.getNumIdle());
1588 Waiter.sleepQuietly(600L);
1589 assertTrue(genericObjectPool.getNumIdle() < 300, "Should be less than 300 idle, found " + genericObjectPool.getNumIdle());
1590 Waiter.sleepQuietly(600L);
1591 assertTrue(genericObjectPool.getNumIdle() < 200, "Should be less than 200 idle, found " + genericObjectPool.getNumIdle());
1592 Waiter.sleepQuietly(600L);
1593 assertTrue(genericObjectPool.getNumIdle() < 100, "Should be less than 100 idle, found " + genericObjectPool.getNumIdle());
1594 Waiter.sleepQuietly(600L);
1595 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1596 }
1597
1598 @Test
1599 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1600 public void testEvictionInvalid() throws Exception {
1601
1602 try (final GenericObjectPool<Object> invalidFactoryPool = new GenericObjectPool<>(new InvalidFactory())) {
1603
1604 invalidFactoryPool.setMaxIdle(1);
1605 invalidFactoryPool.setMaxTotal(1);
1606 invalidFactoryPool.setTestOnBorrow(false);
1607 invalidFactoryPool.setTestOnReturn(false);
1608 invalidFactoryPool.setTestWhileIdle(true);
1609 invalidFactoryPool.setMinEvictableIdleTime(Duration.ofSeconds(100));
1610 invalidFactoryPool.setNumTestsPerEvictionRun(1);
1611
1612 final Object p = invalidFactoryPool.borrowObject();
1613 invalidFactoryPool.returnObject(p);
1614
1615
1616 final Thread t = new EvictionThread<>(invalidFactoryPool);
1617 t.start();
1618
1619
1620 Thread.sleep(300);
1621
1622 try {
1623 invalidFactoryPool.borrowObject(1);
1624 } catch (final NoSuchElementException nsee) {
1625
1626 }
1627
1628
1629 Thread.sleep(1000);
1630
1631
1632 assertEquals(0, invalidFactoryPool.getNumIdle(), "Idle count different than expected.");
1633 assertEquals(0, invalidFactoryPool.getNumActive(), "Total count different than expected.");
1634 }
1635 }
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645 @Test
1646 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1647 public void testEvictionOrder() throws Exception {
1648 checkEvictionOrder(false);
1649 tearDown();
1650 setUp();
1651 checkEvictionOrder(true);
1652 }
1653
1654 @Test
1655 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1656 public void testEvictionPolicy() throws Exception {
1657 genericObjectPool.setMaxIdle(500);
1658 genericObjectPool.setMaxTotal(500);
1659 genericObjectPool.setNumTestsPerEvictionRun(500);
1660 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250));
1661 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500));
1662 genericObjectPool.setTestWhileIdle(true);
1663
1664
1665 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(Long.toString(System.currentTimeMillis())),
1666 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1667
1668
1669 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.io.Serializable.class.getName()),
1670 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1671
1672
1673 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.util.Collections.class.getName()),
1674 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1675
1676 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.lang.String.class.getName()),
1677 () -> "setEvictionPolicyClassName must throw an error if a class that does not implement EvictionPolicy is specified.");
1678
1679 genericObjectPool.setEvictionPolicy(new TestEvictionPolicy<>());
1680 assertEquals(TestEvictionPolicy.class.getName(), genericObjectPool.getEvictionPolicyClassName());
1681
1682 genericObjectPool.setEvictionPolicyClassName(TestEvictionPolicy.class.getName());
1683 assertEquals(TestEvictionPolicy.class.getName(), genericObjectPool.getEvictionPolicyClassName());
1684
1685 final String[] active = new String[500];
1686 for (int i = 0; i < 500; i++) {
1687 active[i] = genericObjectPool.borrowObject();
1688 }
1689 for (int i = 0; i < 500; i++) {
1690 genericObjectPool.returnObject(active[i]);
1691 }
1692
1693
1694
1695
1696 Waiter.sleepQuietly(1000L);
1697 assertEquals(500, genericObjectPool.getNumIdle(), "Should be 500 idle");
1698
1699
1700 Waiter.sleepQuietly(2000L);
1701 assertEquals(0, genericObjectPool.getNumIdle(), "Should be 0 idle");
1702 }
1703
1704 @Test
1705 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1706 public void testEvictionSoftMinIdle() throws Exception {
1707 final class TimeTest extends BasePooledObjectFactory<TimeTest> {
1708 private final long createTimeMillis;
1709
1710 public TimeTest() {
1711 createTimeMillis = System.currentTimeMillis();
1712 }
1713
1714 @Override
1715 public TimeTest create() {
1716 return new TimeTest();
1717 }
1718
1719 public long getCreateTimeMillis() {
1720 return createTimeMillis;
1721 }
1722
1723 @Override
1724 public PooledObject<TimeTest> wrap(final TimeTest value) {
1725 return new DefaultPooledObject<>(value);
1726 }
1727 }
1728
1729 try (final GenericObjectPool<TimeTest> timePool = new GenericObjectPool<>(new TimeTest())) {
1730
1731 timePool.setMaxIdle(5);
1732 timePool.setMaxTotal(5);
1733 timePool.setNumTestsPerEvictionRun(5);
1734 timePool.setMinEvictableIdleDuration(Duration.ofSeconds(3));
1735 timePool.setMinEvictableIdle(Duration.ofSeconds(3));
1736 timePool.setMinEvictableIdleTime(Duration.ofSeconds(3));
1737 timePool.setSoftMinEvictableIdleTime(TestConstants.ONE_SECOND_DURATION);
1738 timePool.setMinIdle(2);
1739
1740 final TimeTest[] active = new TimeTest[5];
1741 final Long[] creationTime = new Long[5];
1742 for (int i = 0; i < 5; i++) {
1743 active[i] = timePool.borrowObject();
1744 creationTime[i] = Long.valueOf(active[i].getCreateTimeMillis());
1745 }
1746
1747 for (int i = 0; i < 5; i++) {
1748 timePool.returnObject(active[i]);
1749 }
1750
1751
1752 Thread.sleep(1500L);
1753 timePool.evict();
1754 assertEquals(2, timePool.getNumIdle(), "Idle count different than expected.");
1755
1756
1757 Thread.sleep(2000L);
1758 timePool.evict();
1759 assertEquals(0, timePool.getNumIdle(), "Idle count different than expected.");
1760 }
1761 }
1762
1763 @Test
1764 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1765 public void testEvictionWithNegativeNumTests() throws Exception {
1766
1767 genericObjectPool.setMaxIdle(6);
1768 genericObjectPool.setMaxTotal(6);
1769 genericObjectPool.setNumTestsPerEvictionRun(-2);
1770 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
1771 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
1772
1773 final String[] active = new String[6];
1774 for (int i = 0; i < 6; i++) {
1775 active[i] = genericObjectPool.borrowObject();
1776 }
1777 for (int i = 0; i < 6; i++) {
1778 genericObjectPool.returnObject(active[i]);
1779 }
1780
1781 Waiter.sleepQuietly(100L);
1782 assertTrue(genericObjectPool.getNumIdle() <= 6, "Should at most 6 idle, found " + genericObjectPool.getNumIdle());
1783 Waiter.sleepQuietly(100L);
1784 assertTrue(genericObjectPool.getNumIdle() <= 3, "Should at most 3 idle, found " + genericObjectPool.getNumIdle());
1785 Waiter.sleepQuietly(100L);
1786 assertTrue(genericObjectPool.getNumIdle() <= 2, "Should be at most 2 idle, found " + genericObjectPool.getNumIdle());
1787 Waiter.sleepQuietly(100L);
1788 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1789 }
1790
1791 @Test
1792 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1793 public void testEvictLIFO() throws Exception {
1794 checkEvict(true);
1795 }
1796
1797
1798
1799
1800
1801
1802
1803 @Test
1804 public void testEvictorVisiting() throws Exception {
1805 checkEvictorVisiting(true);
1806 checkEvictorVisiting(false);
1807 }
1808
1809 @Test
1810 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1811 public void testEvictWhileEmpty() throws Exception {
1812 genericObjectPool.evict();
1813 genericObjectPool.evict();
1814 genericObjectPool.close();
1815 }
1816
1817 @Test
1818 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1819 public void testExceptionInValidationDuringEviction() throws Exception {
1820 genericObjectPool.setMaxIdle(1);
1821 genericObjectPool.setMinEvictableIdleTime(Duration.ZERO);
1822 genericObjectPool.setTestWhileIdle(true);
1823
1824 final String active = genericObjectPool.borrowObject();
1825 genericObjectPool.returnObject(active);
1826
1827 simpleFactory.setThrowExceptionOnValidate(true);
1828
1829 assertThrows(RuntimeException.class, () -> genericObjectPool.evict());
1830 assertEquals(0, genericObjectPool.getNumActive());
1831 assertEquals(0, genericObjectPool.getNumIdle());
1832 }
1833
1834 @Test
1835 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1836 public void testExceptionOnActivateDuringBorrow() throws Exception {
1837 final String obj1 = genericObjectPool.borrowObject();
1838 final String obj2 = genericObjectPool.borrowObject();
1839 genericObjectPool.returnObject(obj1);
1840 genericObjectPool.returnObject(obj2);
1841 simpleFactory.setThrowExceptionOnActivate(true);
1842 simpleFactory.setEvenValid(false);
1843
1844
1845 final String obj = genericObjectPool.borrowObject();
1846 assertEquals(1, genericObjectPool.getNumActive());
1847 assertEquals(0, genericObjectPool.getNumIdle());
1848
1849 genericObjectPool.returnObject(obj);
1850 simpleFactory.setValid(false);
1851
1852
1853 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
1854 assertEquals(0, genericObjectPool.getNumActive());
1855 assertEquals(0, genericObjectPool.getNumIdle());
1856 }
1857
1858 @Test
1859 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1860 public void testExceptionOnDestroyDuringBorrow() throws Exception {
1861 simpleFactory.setThrowExceptionOnDestroy(true);
1862 genericObjectPool.setTestOnBorrow(true);
1863 genericObjectPool.borrowObject();
1864 simpleFactory.setValid(false);
1865 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
1866 assertEquals(1, genericObjectPool.getNumActive());
1867 assertEquals(0, genericObjectPool.getNumIdle());
1868 }
1869
1870 @Test
1871 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1872 public void testExceptionOnDestroyDuringReturn() throws Exception {
1873 simpleFactory.setThrowExceptionOnDestroy(true);
1874 genericObjectPool.setTestOnReturn(true);
1875 final String obj1 = genericObjectPool.borrowObject();
1876 genericObjectPool.borrowObject();
1877 simpleFactory.setValid(false);
1878 genericObjectPool.returnObject(obj1);
1879 assertEquals(1, genericObjectPool.getNumActive());
1880 assertEquals(0, genericObjectPool.getNumIdle());
1881 }
1882
1883 @Test
1884 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1885 public void testExceptionOnPassivateDuringReturn() throws Exception {
1886 final String obj = genericObjectPool.borrowObject();
1887 simpleFactory.setThrowExceptionOnPassivate(true);
1888 genericObjectPool.returnObject(obj);
1889 assertEquals(0,genericObjectPool.getNumIdle());
1890 }
1891
1892 @Test
1893 public void testFailingFactoryDoesNotBlockThreads() throws Exception {
1894
1895 final CreateFailFactory factory = new CreateFailFactory();
1896 try (final GenericObjectPool<String> createFailFactoryPool = new GenericObjectPool<>(factory)) {
1897
1898 createFailFactoryPool.setMaxTotal(1);
1899
1900
1901 final WaitingTestThread thread1 = new WaitingTestThread(createFailFactoryPool, 0);
1902 thread1.start();
1903
1904
1905 while (!factory.hasQueuedThreads()) {
1906 Thread.sleep(200);
1907 }
1908
1909
1910 final WaitingTestThread thread2 = new WaitingTestThread(createFailFactoryPool, 0);
1911 thread2.start();
1912
1913
1914
1915
1916
1917 Thread.sleep(1000);
1918
1919
1920 factory.release();
1921
1922 factory.release();
1923
1924
1925 boolean threadRunning = true;
1926 int count = 0;
1927 while (threadRunning && count < 15) {
1928 threadRunning = thread1.isAlive();
1929 threadRunning = thread2.isAlive();
1930 Thread.sleep(200);
1931 count++;
1932 }
1933 assertFalse(thread1.isAlive());
1934 assertFalse(thread2.isAlive());
1935
1936 assertTrue(thread1.thrown instanceof UnsupportedCharsetException);
1937 assertTrue(thread2.thrown instanceof UnsupportedCharsetException);
1938 }
1939 }
1940
1941 @Test
1942 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1943 public void testFIFO() throws Exception {
1944 genericObjectPool.setLifo(false);
1945 genericObjectPool.addObject();
1946 genericObjectPool.addObject();
1947 genericObjectPool.addObject();
1948 assertEquals("0", genericObjectPool.borrowObject(), "Oldest");
1949 assertEquals("1", genericObjectPool.borrowObject(), "Middle");
1950 assertEquals("2", genericObjectPool.borrowObject(), "Youngest");
1951 final String o = genericObjectPool.borrowObject();
1952 assertEquals("3", o, "new-3");
1953 genericObjectPool.returnObject(o);
1954 assertEquals(o, genericObjectPool.borrowObject(), "returned-3");
1955 assertEquals("4", genericObjectPool.borrowObject(), "new-4");
1956 }
1957
1958 @Test
1959 public void testGetFactoryType_DefaultPooledObjectFactory() {
1960 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createDefaultPooledObjectFactory())) {
1961 assertNotNull(pool.getFactoryType());
1962 }
1963 }
1964
1965 @Test
1966 public void testGetFactoryType_NullPooledObjectFactory() {
1967 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createNullPooledObjectFactory())) {
1968 assertNotNull(pool.getFactoryType());
1969 }
1970 }
1971
1972 @Test
1973 public void testGetFactoryType_PoolUtilsSynchronizedDefaultPooledFactory() {
1974 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1975 PoolUtils.synchronizedPooledFactory(createDefaultPooledObjectFactory()))) {
1976 assertNotNull(pool.getFactoryType());
1977 }
1978 }
1979
1980 @Test
1981 public void testGetFactoryType_PoolUtilsSynchronizedNullPooledFactory() {
1982 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1983 PoolUtils.synchronizedPooledFactory(createNullPooledObjectFactory()))) {
1984 assertNotNull(pool.getFactoryType());
1985 }
1986 }
1987
1988 @Test
1989 public void testGetFactoryType_SynchronizedDefaultPooledObjectFactory() {
1990 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1991 new TestSynchronizedPooledObjectFactory<>(createDefaultPooledObjectFactory()))) {
1992 assertNotNull(pool.getFactoryType());
1993 }
1994 }
1995
1996 @Test
1997 public void testGetFactoryType_SynchronizedNullPooledObjectFactory() {
1998 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1999 new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) {
2000 assertNotNull(pool.getFactoryType());
2001 }
2002 }
2003
2004 @Test
2005 public void testGetStatsString() {
2006 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
2007 new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) {
2008 assertNotNull(pool.getStatsString());
2009 }
2010 }
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020 @Test
2021 public void testInvalidateFreesCapacity() throws Exception {
2022 final SimpleFactory factory = new SimpleFactory();
2023 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory)) {
2024 pool.setMaxTotal(2);
2025 pool.setMaxWaitMillis(500);
2026
2027 final WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
2028 thread1.start();
2029
2030 final String obj = pool.borrowObject();
2031
2032 final WaitingTestThread thread2 = new WaitingTestThread(pool, 100);
2033 thread2.start();
2034
2035 Thread.sleep(20);
2036 pool.invalidateObject(obj);
2037 Thread.sleep(600);
2038 if (thread2.thrown != null) {
2039 fail(thread2.thrown.toString());
2040 }
2041 }
2042 }
2043
2044
2045
2046
2047 @Test
2048 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2049 public void testJmxRegistration() {
2050 final ObjectName oname = genericObjectPool.getJmxName();
2051 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
2052 final Set<ObjectName> result = mbs.queryNames(oname, null);
2053 assertEquals(1, result.size());
2054 genericObjectPool.jmxUnregister();
2055
2056 final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
2057 config.setJmxEnabled(false);
2058 try (final GenericObjectPool<String> poolWithoutJmx = new GenericObjectPool<>(simpleFactory, config)) {
2059 assertNull(poolWithoutJmx.getJmxName());
2060 config.setJmxEnabled(true);
2061 poolWithoutJmx.jmxUnregister();
2062 }
2063
2064 config.setJmxNameBase(null);
2065 try (final GenericObjectPool<String> poolWithDefaultJmxNameBase = new GenericObjectPool<>(simpleFactory, config)) {
2066 assertNotNull(poolWithDefaultJmxNameBase.getJmxName());
2067 }
2068 }
2069
2070 @Test
2071 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2072 public void testLIFO() throws Exception {
2073 final String o;
2074 genericObjectPool.setLifo(true);
2075 genericObjectPool.addObject();
2076 genericObjectPool.addObject();
2077 genericObjectPool.addObject();
2078 assertEquals("2", genericObjectPool.borrowObject(), "Youngest");
2079 assertEquals("1", genericObjectPool.borrowObject(), "Middle");
2080 assertEquals("0", genericObjectPool.borrowObject(), "Oldest");
2081 o = genericObjectPool.borrowObject();
2082 assertEquals("3", o, "new-3");
2083 genericObjectPool.returnObject(o);
2084 assertEquals(o, genericObjectPool.borrowObject(), "returned-3");
2085 assertEquals("4", genericObjectPool.borrowObject(), "new-4");
2086 }
2087
2088
2089
2090
2091
2092
2093
2094 @Test
2095 @Disabled
2096 @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
2097 public void testLivenessOnTransientFactoryFailure() throws Exception {
2098 final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>(
2099 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_CREATE_ACTION,
2100 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION,
2101 obj -> false
2102 );
2103 final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory);
2104 pool.setMaxWait(Duration.ofMillis(100));
2105 pool.setTestOnReturn(true);
2106 pool.setMaxTotal(1);
2107 final Waiter w = pool.borrowObject();
2108 final AtomicBoolean failed = new AtomicBoolean();
2109 final Thread t = new Thread(() -> {
2110 try {
2111 pool.borrowObject();
2112 } catch (final Exception e) {
2113 failed.set(true);
2114 }
2115 });
2116 Thread.sleep(10);
2117 t.start();
2118
2119 Thread.sleep(10);
2120 factory.disconnect();
2121 pool.returnObject(w);
2122 Thread.sleep(10);
2123 factory.connect();
2124
2125 t.join();
2126 pool.close();
2127 if (failed.get()) {
2128 fail("Borrower timed out waiting for an instance");
2129 }
2130 }
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141 @Test
2142 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2143 public void testMakeConcurrentWithReturn() throws Exception {
2144 genericObjectPool.setTestOnBorrow(true);
2145 simpleFactory.setValid(true);
2146
2147 final WaitingTestThread thread1 = new WaitingTestThread(genericObjectPool, 200);
2148 thread1.start();
2149 Thread.sleep(50);
2150
2151 simpleFactory.setValidateLatency(400);
2152 final String instance = genericObjectPool.borrowObject();
2153
2154 assertEquals(simpleFactory.getMakeCounter(), genericObjectPool.getNumIdle() + 1);
2155 genericObjectPool.returnObject(instance);
2156 assertEquals(simpleFactory.getMakeCounter(), genericObjectPool.getNumIdle());
2157 }
2158
2159 @Test
2160 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2161 public void testMaxIdle() throws Exception {
2162 genericObjectPool.setMaxTotal(100);
2163 genericObjectPool.setMaxIdle(8);
2164 final String[] active = new String[100];
2165 for (int i = 0; i < 100; i++) {
2166 active[i] = genericObjectPool.borrowObject();
2167 }
2168 assertEquals(100, genericObjectPool.getNumActive());
2169 assertEquals(0, genericObjectPool.getNumIdle());
2170 for (int i = 0; i < 100; i++) {
2171 genericObjectPool.returnObject(active[i]);
2172 assertEquals(99 - i, genericObjectPool.getNumActive());
2173 assertEquals(i < 8 ? i + 1 : 8, genericObjectPool.getNumIdle());
2174 }
2175 }
2176
2177 @Test
2178 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2179 public void testMaxIdleZero() throws Exception {
2180 genericObjectPool.setMaxTotal(100);
2181 genericObjectPool.setMaxIdle(0);
2182 final String[] active = new String[100];
2183 for (int i = 0; i < 100; i++) {
2184 active[i] = genericObjectPool.borrowObject();
2185 }
2186 assertEquals(100, genericObjectPool.getNumActive());
2187 assertEquals(0, genericObjectPool.getNumIdle());
2188 for (int i = 0; i < 100; i++) {
2189 genericObjectPool.returnObject(active[i]);
2190 assertEquals(99 - i, genericObjectPool.getNumActive());
2191 assertEquals(0, genericObjectPool.getNumIdle());
2192 }
2193 }
2194
2195
2196
2197
2198 @Test
2199 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2200 @SuppressWarnings("rawtypes")
2201 public void testMaxIdleZeroUnderLoad() {
2202
2203 final int numThreads = 199;
2204 final int numIter = 20;
2205 final int delay = 25;
2206 final int maxTotal = 10;
2207
2208 simpleFactory.setMaxTotal(maxTotal);
2209 genericObjectPool.setMaxTotal(maxTotal);
2210 genericObjectPool.setBlockWhenExhausted(true);
2211 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(-1));
2212
2213
2214 genericObjectPool.setMaxIdle(0);
2215
2216
2217 final TestThread[] threads = new TestThread[numThreads];
2218 for(int i=0;i<numThreads;i++) {
2219
2220
2221
2222 threads[i] = new TestThread<>(genericObjectPool, numIter * 2, delay * 2);
2223 final Thread t = new Thread(threads[i]);
2224 t.start();
2225 }
2226
2227 Waiter.sleepQuietly(100L);
2228
2229 for (int i = 0; i < numIter; i++) {
2230 String obj = null;
2231 try {
2232 Waiter.sleepQuietly(delay);
2233 obj = genericObjectPool.borrowObject();
2234
2235 if (genericObjectPool.getNumActive() > genericObjectPool.getMaxTotal()) {
2236 throw new IllegalStateException("Too many active objects");
2237 }
2238 Waiter.sleepQuietly(delay);
2239 } catch (final Exception e) {
2240
2241 e.printStackTrace();
2242 fail("Exception on borrow");
2243 } finally {
2244 if (obj != null) {
2245 try {
2246 genericObjectPool.returnObject(obj);
2247 } catch (final Exception e) {
2248
2249 }
2250 }
2251 }
2252 }
2253
2254 for (int i = 0; i < numThreads; i++) {
2255 while (!threads[i].complete()) {
2256 Waiter.sleepQuietly(500L);
2257 }
2258 if (threads[i].failed()) {
2259 threads[i].error.printStackTrace();
2260 fail("Thread " + i + " failed: " + threads[i].error.toString());
2261 }
2262 }
2263 }
2264
2265 @Test
2266 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2267 public void testMaxTotal() throws Exception {
2268 genericObjectPool.setMaxTotal(3);
2269 genericObjectPool.setBlockWhenExhausted(false);
2270
2271 genericObjectPool.borrowObject();
2272 genericObjectPool.borrowObject();
2273 genericObjectPool.borrowObject();
2274 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2275 }
2276
2277
2278
2279
2280
2281
2282 @Test
2283 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2284 public void testMaxTotalInvariant() {
2285 final int maxTotal = 15;
2286 simpleFactory.setEvenValid(false);
2287 simpleFactory.setDestroyLatency(100);
2288 simpleFactory.setMaxTotal(maxTotal);
2289 simpleFactory.setValidationEnabled(true);
2290 genericObjectPool.setMaxTotal(maxTotal);
2291 genericObjectPool.setMaxIdle(-1);
2292 genericObjectPool.setTestOnReturn(true);
2293 genericObjectPool.setMaxWaitMillis(1000L);
2294 runTestThreads(5, 10, 50, genericObjectPool);
2295 }
2296
2297 @Test
2298 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2299 @SuppressWarnings("rawtypes")
2300 public void testMaxTotalUnderLoad() {
2301
2302 final int numThreads = 199;
2303 final int numIter = 20;
2304 final int delay = 25;
2305 final int maxTotal = 10;
2306
2307 simpleFactory.setMaxTotal(maxTotal);
2308 genericObjectPool.setMaxTotal(maxTotal);
2309 genericObjectPool.setBlockWhenExhausted(true);
2310 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(-1));
2311
2312
2313 final TestThread[] threads = new TestThread[numThreads];
2314 for(int i=0;i<numThreads;i++) {
2315
2316
2317
2318 threads[i] = new TestThread<>(genericObjectPool, numIter * 2, delay * 2);
2319 final Thread t = new Thread(threads[i]);
2320 t.start();
2321 }
2322
2323 Waiter.sleepQuietly(5000);
2324
2325 for (int i = 0; i < numIter; i++) {
2326 String obj = null;
2327 try {
2328 Waiter.sleepQuietly(delay);
2329 obj = genericObjectPool.borrowObject();
2330
2331 if (genericObjectPool.getNumActive() > genericObjectPool.getMaxTotal()) {
2332 throw new IllegalStateException("Too many active objects");
2333 }
2334 Waiter.sleepQuietly(delay);
2335 } catch (final Exception e) {
2336
2337 e.printStackTrace();
2338 fail("Exception on borrow");
2339 } finally {
2340 if (obj != null) {
2341 try {
2342 genericObjectPool.returnObject(obj);
2343 } catch (final Exception e) {
2344
2345 }
2346 }
2347 }
2348 }
2349
2350 for (int i = 0; i < numThreads; i++) {
2351 while(!threads[i].complete()) {
2352 Waiter.sleepQuietly(500L);
2353 }
2354 if(threads[i].failed()) {
2355 fail("Thread " + i + " failed: " + threads[i].error.toString());
2356 }
2357 }
2358 }
2359
2360 @Test
2361 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2362 public void testMaxTotalZero() throws Exception {
2363 genericObjectPool.setMaxTotal(0);
2364 genericObjectPool.setBlockWhenExhausted(false);
2365 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2366 }
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376 @Test
2377 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2378 public void testMaxWaitMultiThreaded() throws Exception {
2379 final long maxWait = 500;
2380 final long holdTime = 2 * maxWait;
2381 final int threads = 10;
2382 genericObjectPool.setBlockWhenExhausted(true);
2383 genericObjectPool.setMaxWaitMillis(maxWait);
2384 genericObjectPool.setMaxTotal(threads);
2385
2386 final WaitingTestThread[] wtt = new WaitingTestThread[threads * 2];
2387 for (int i = 0; i < wtt.length; i++) {
2388 wtt[i] = new WaitingTestThread(genericObjectPool, holdTime);
2389 }
2390 final long originMillis = System.currentTimeMillis() - 1000;
2391 for (final WaitingTestThread element : wtt) {
2392 element.start();
2393 }
2394 int failed = 0;
2395 for (final WaitingTestThread element : wtt) {
2396 element.join();
2397 if (element.thrown != null){
2398 failed++;
2399 }
2400 }
2401 if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){
2402 System.out.println(
2403 "MaxWait: " + maxWait +
2404 " HoldTime: " + holdTime +
2405 " MaxTotal: " + threads +
2406 " Threads: " + wtt.length +
2407 " Failed: " + failed
2408 );
2409 for (final WaitingTestThread wt : wtt) {
2410 System.out.println(
2411 "PreBorrow: " + (wt.preBorrowMillis - originMillis) +
2412 " PostBorrow: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - originMillis : -1) +
2413 " BorrowTime: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - wt.preBorrowMillis : -1) +
2414 " PostReturn: " + (wt.postReturnMillis != 0 ? wt.postReturnMillis - originMillis : -1) +
2415 " Ended: " + (wt.endedMillis - originMillis) +
2416 " ObjId: " + wt.objectId
2417 );
2418 }
2419 }
2420 assertEquals(wtt.length / 2, failed, "Expected half the threads to fail");
2421 }
2422
2423 @Test
2424 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2425 public void testMinIdle() throws Exception {
2426 genericObjectPool.setMaxIdle(500);
2427 genericObjectPool.setMinIdle(5);
2428 genericObjectPool.setMaxTotal(10);
2429 genericObjectPool.setNumTestsPerEvictionRun(0);
2430 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
2431 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
2432 genericObjectPool.setTestWhileIdle(true);
2433
2434 Waiter.sleepQuietly(150L);
2435 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2436
2437 final String[] active = new String[5];
2438 active[0] = genericObjectPool.borrowObject();
2439
2440 Waiter.sleepQuietly(150L);
2441 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2442
2443 for (int i = 1; i < 5; i++) {
2444 active[i] = genericObjectPool.borrowObject();
2445 }
2446
2447 Waiter.sleepQuietly(150L);
2448 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2449
2450 for (int i = 0; i < 5; i++) {
2451 genericObjectPool.returnObject(active[i]);
2452 }
2453
2454 Waiter.sleepQuietly(150L);
2455 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2456 }
2457
2458 @Test
2459 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2460 public void testMinIdleMaxTotal() throws Exception {
2461 genericObjectPool.setMaxIdle(500);
2462 genericObjectPool.setMinIdle(5);
2463 genericObjectPool.setMaxTotal(10);
2464 genericObjectPool.setNumTestsPerEvictionRun(0);
2465 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
2466 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
2467 genericObjectPool.setTestWhileIdle(true);
2468
2469 Waiter.sleepQuietly(150L);
2470 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2471
2472 final String[] active = new String[10];
2473
2474 Waiter.sleepQuietly(150L);
2475 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2476
2477 for (int i = 0; i < 5; i++) {
2478 active[i] = genericObjectPool.borrowObject();
2479 }
2480
2481 Waiter.sleepQuietly(150L);
2482 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2483
2484 for(int i = 0 ; i < 5 ; i++) {
2485 genericObjectPool.returnObject(active[i]);
2486 }
2487
2488 Waiter.sleepQuietly(150L);
2489 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2490
2491 for (int i = 0; i < 10; i++) {
2492 active[i] = genericObjectPool.borrowObject();
2493 }
2494
2495 Waiter.sleepQuietly(150L);
2496 assertEquals(0, genericObjectPool.getNumIdle(), "Should be 0 idle, found " + genericObjectPool.getNumIdle());
2497
2498 for (int i = 0; i < 10; i++) {
2499 genericObjectPool.returnObject(active[i]);
2500 }
2501
2502 Waiter.sleepQuietly(150L);
2503 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2504 }
2505
2506
2507
2508
2509
2510
2511
2512 @Test
2513 public void testMultipleReturn() throws Exception {
2514 final WaiterFactory<String> factory = new WaiterFactory<>(0, 0, 0, 0, 0, 0);
2515 try (final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory)) {
2516 pool.setTestOnReturn(true);
2517 final Waiter waiter = pool.borrowObject();
2518 pool.returnObject(waiter);
2519 assertEquals(1, waiter.getValidationCount());
2520 assertEquals(1, waiter.getPassivationCount());
2521 try {
2522 pool.returnObject(waiter);
2523 fail("Expecting IllegalStateException from multiple return");
2524 } catch (final IllegalStateException ex) {
2525
2526 assertEquals(1, waiter.getValidationCount());
2527 assertEquals(1, waiter.getPassivationCount());
2528 }
2529 }
2530 }
2531
2532
2533 @Test
2534 public void testMultipleReturnOfSameObject() throws Exception {
2535 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(simpleFactory, new GenericObjectPoolConfig<>())) {
2536
2537 assertEquals(0, pool.getNumActive());
2538 assertEquals(0, pool.getNumIdle());
2539
2540 final String obj = pool.borrowObject();
2541
2542 assertEquals(1, pool.getNumActive());
2543 assertEquals(0, pool.getNumIdle());
2544
2545 pool.returnObject(obj);
2546
2547 assertEquals(0, pool.getNumActive());
2548 assertEquals(1, pool.getNumIdle());
2549
2550 assertThrows(IllegalStateException.class,
2551 () -> pool.returnObject(obj));
2552
2553 assertEquals(0, pool.getNumActive());
2554 assertEquals(1, pool.getNumIdle());
2555 }
2556 }
2557
2558
2559
2560
2561
2562
2563
2564 @Test
2565 public void testMutable() throws Exception {
2566 final HashSetFactory factory = new HashSetFactory();
2567 try (final GenericObjectPool<HashSet<String>> pool = new GenericObjectPool<>(factory,
2568 new GenericObjectPoolConfig<>())) {
2569 final HashSet<String> s1 = pool.borrowObject();
2570 final HashSet<String> s2 = pool.borrowObject();
2571 s1.add("One");
2572 s2.add("One");
2573 pool.returnObject(s1);
2574 pool.returnObject(s2);
2575 }
2576 }
2577
2578 @Test
2579 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2580 public void testNegativeMaxTotal() throws Exception {
2581 genericObjectPool.setMaxTotal(-1);
2582 genericObjectPool.setBlockWhenExhausted(false);
2583 final String obj = genericObjectPool.borrowObject();
2584 assertEquals(getNthObject(0), obj);
2585 genericObjectPool.returnObject(obj);
2586 }
2587
2588
2589
2590
2591 @Test
2592 public void testNoInstanceOverlap() {
2593 final int maxTotal = 5;
2594 final int numThreads = 100;
2595 final int delay = 1;
2596 final int iterations = 1000;
2597 final AtomicIntegerFactory factory = new AtomicIntegerFactory();
2598 try (final GenericObjectPool<AtomicInteger> pool = new GenericObjectPool<>(factory)) {
2599 pool.setMaxTotal(maxTotal);
2600 pool.setMaxIdle(maxTotal);
2601 pool.setTestOnBorrow(true);
2602 pool.setBlockWhenExhausted(true);
2603 pool.setMaxWaitMillis(-1);
2604 runTestThreads(numThreads, iterations, delay, pool);
2605 assertEquals(0, pool.getDestroyedByBorrowValidationCount());
2606 }
2607 }
2608
2609
2610
2611
2612 @Test
2613 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2614 public void testNoInvalidateNPE() throws Exception {
2615 genericObjectPool.setMaxTotal(1);
2616 genericObjectPool.setTestOnCreate(true);
2617 genericObjectPool.setMaxWaitMillis(-1);
2618 final String obj = genericObjectPool.borrowObject();
2619
2620 simpleFactory.setValid(false);
2621
2622 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200);
2623 wtt.start();
2624
2625 Thread.sleep(200);
2626 genericObjectPool.invalidateObject(obj);
2627
2628 simpleFactory.setValid(true);
2629 }
2630
2631
2632
2633
2634
2635 @Test
2636 @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
2637 public void testNPEOnFactoryNull() throws Exception {
2638 final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>(
2639 () -> null,
2640 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION,
2641 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION
2642 );
2643 final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory);
2644 pool.setTestOnBorrow(true);
2645 pool.setMaxTotal(-1);
2646 pool.setMinIdle(1);
2647
2648 factory.disconnect();
2649 try {
2650 pool.borrowObject();
2651 fail("Expecting NullPointerException");
2652 } catch (final NullPointerException ex) {
2653
2654 }
2655 try {
2656 pool.addObject();
2657 fail("Expecting NullPointerException");
2658 } catch (final NullPointerException ex2) {
2659
2660 }
2661 try {
2662 pool.ensureMinIdle();
2663 fail("Expecting NullPointerException");
2664 } catch (final NullPointerException ex3) {
2665
2666 }
2667 pool.close();
2668 }
2669
2670 @Test
2671 public void testPreparePool() throws Exception {
2672 genericObjectPool.setMinIdle(1);
2673 genericObjectPool.setMaxTotal(1);
2674 genericObjectPool.preparePool();
2675 assertEquals(1, genericObjectPool.getNumIdle());
2676 final String obj = genericObjectPool.borrowObject();
2677 genericObjectPool.preparePool();
2678 assertEquals(0, genericObjectPool.getNumIdle());
2679 genericObjectPool.setMinIdle(0);
2680 genericObjectPool.returnObject(obj);
2681 genericObjectPool.preparePool();
2682 assertEquals(1, genericObjectPool.getNumIdle());
2683 }
2684
2685 @Test
2686 @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS)
2687 public void testReturnBorrowObjectWithingMaxWaitDuration() throws Exception {
2688 final Duration maxWaitDuration = Duration.ofMillis(500);
2689 try (final GenericObjectPool<String> createSlowObjectFactoryPool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) {
2690 createSlowObjectFactoryPool.setMaxTotal(1);
2691 createSlowObjectFactoryPool.setMaxWait(maxWaitDuration);
2692
2693 final WaitingTestThread thread1 = new WaitingTestThread(createSlowObjectFactoryPool, 0);
2694 thread1.start();
2695
2696 Thread.sleep(100);
2697
2698 assertThrows(NoSuchElementException.class, () -> createSlowObjectFactoryPool.borrowObject(maxWaitDuration),
2699 "borrowObject must fail due to timeout by maxWait");
2700 assertTrue(thread1.isAlive());
2701 }
2702 }
2703
2704 @Test
2705 @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS)
2706 public void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception {
2707 final long maxWaitMillis = 500;
2708 try (final GenericObjectPool<String> createSlowObjectFactoryPool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) {
2709 createSlowObjectFactoryPool.setMaxTotal(1);
2710 createSlowObjectFactoryPool.setMaxWaitMillis(maxWaitMillis);
2711
2712 final WaitingTestThread thread1 = new WaitingTestThread(createSlowObjectFactoryPool, 0);
2713 thread1.start();
2714
2715 Thread.sleep(100);
2716
2717 assertThrows(NoSuchElementException.class, () -> createSlowObjectFactoryPool.borrowObject(maxWaitMillis),
2718 "borrowObject must fail due to timeout by maxWait");
2719 assertTrue(thread1.isAlive());
2720 }
2721 }
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2733 public void testReturnObject() throws Exception {
2734
2735 genericObjectPool.setMaxTotal(1);
2736 genericObjectPool.setMaxIdle(-1);
2737 final String active = genericObjectPool.borrowObject();
2738
2739 assertEquals(1, genericObjectPool.getNumActive());
2740 assertEquals(0, genericObjectPool.getNumIdle());
2741
2742 final Thread t = new Thread(() -> genericObjectPool.close());
2743 t.start();
2744
2745 genericObjectPool.returnObject(active);
2746
2747
2748 while (t.isAlive()) {
2749 Thread.sleep(50);
2750 }
2751
2752 assertEquals(0, genericObjectPool.getNumIdle());
2753 }
2754
2755 @Test
2756 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2757 public void testSetConfig() throws Exception {
2758 final GenericObjectPoolConfig<String> expected = new GenericObjectPoolConfig<>();
2759 assertConfiguration(expected, genericObjectPool);
2760 expected.setMaxTotal(2);
2761 expected.setMaxIdle(3);
2762 expected.setMaxWait(Duration.ofMillis(5));
2763 expected.setMinEvictableIdleDuration(Duration.ofMillis(7L));
2764 expected.setNumTestsPerEvictionRun(9);
2765 expected.setTestOnCreate(true);
2766 expected.setTestOnBorrow(true);
2767 expected.setTestOnReturn(true);
2768 expected.setTestWhileIdle(true);
2769 expected.setTimeBetweenEvictionRuns(Duration.ofMillis(11L));
2770 expected.setBlockWhenExhausted(false);
2771 genericObjectPool.setConfig(expected);
2772 assertConfiguration(expected, genericObjectPool);
2773 }
2774
2775 @Test
2776 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2777 public void testSettersAndGetters() throws Exception {
2778 {
2779
2780
2781 assertNotEquals("", genericObjectPool.getCreationStackTrace());
2782 }
2783 {
2784 assertEquals(0, genericObjectPool.getBorrowedCount());
2785 }
2786 {
2787 assertEquals(0, genericObjectPool.getReturnedCount());
2788 }
2789 {
2790 assertEquals(0, genericObjectPool.getCreatedCount());
2791 }
2792 {
2793 assertEquals(0, genericObjectPool.getDestroyedCount());
2794 }
2795 {
2796 assertEquals(0, genericObjectPool.getDestroyedByEvictorCount());
2797 }
2798 {
2799 assertEquals(0, genericObjectPool.getDestroyedByBorrowValidationCount());
2800 }
2801 {
2802 assertEquals(0, genericObjectPool.getMeanActiveTimeMillis());
2803 }
2804 {
2805 assertEquals(0, genericObjectPool.getMeanIdleTimeMillis());
2806 }
2807 {
2808 assertEquals(0, genericObjectPool.getMeanBorrowWaitTimeMillis());
2809 }
2810 {
2811 assertEquals(0, genericObjectPool.getMaxBorrowWaitTimeMillis());
2812 }
2813 {
2814 assertEquals(0, genericObjectPool.getNumIdle());
2815 }
2816 {
2817 genericObjectPool.setMaxTotal(123);
2818 assertEquals(123, genericObjectPool.getMaxTotal());
2819 }
2820 {
2821 genericObjectPool.setMaxIdle(12);
2822 assertEquals(12, genericObjectPool.getMaxIdle());
2823 }
2824 {
2825 genericObjectPool.setMaxWaitMillis(1234L);
2826 assertEquals(1234L, genericObjectPool.getMaxWaitMillis());
2827 }
2828 {
2829 genericObjectPool.setMinEvictableIdleTimeMillis(12345L);
2830 assertEquals(12345L, genericObjectPool.getMinEvictableIdleDuration().toMillis());
2831 assertEquals(12345L, genericObjectPool.getMinEvictableIdleTimeMillis());
2832 assertEquals(12345L, genericObjectPool.getMinEvictableIdleTime().toMillis());
2833 }
2834 {
2835 genericObjectPool.setNumTestsPerEvictionRun(11);
2836 assertEquals(11, genericObjectPool.getNumTestsPerEvictionRun());
2837 }
2838 {
2839 genericObjectPool.setTestOnBorrow(true);
2840 assertTrue(genericObjectPool.getTestOnBorrow());
2841 genericObjectPool.setTestOnBorrow(false);
2842 assertFalse(genericObjectPool.getTestOnBorrow());
2843 }
2844 {
2845 genericObjectPool.setTestOnReturn(true);
2846 assertTrue(genericObjectPool.getTestOnReturn());
2847 genericObjectPool.setTestOnReturn(false);
2848 assertFalse(genericObjectPool.getTestOnReturn());
2849 }
2850 {
2851 genericObjectPool.setTestWhileIdle(true);
2852 assertTrue(genericObjectPool.getTestWhileIdle());
2853 genericObjectPool.setTestWhileIdle(false);
2854 assertFalse(genericObjectPool.getTestWhileIdle());
2855 }
2856 {
2857 genericObjectPool.setTimeBetweenEvictionRunsMillis(11235L);
2858 assertEquals(11235L, genericObjectPool.getDurationBetweenEvictionRuns().toMillis());
2859 assertEquals(11235L, genericObjectPool.getTimeBetweenEvictionRunsMillis());
2860 assertEquals(11235L, genericObjectPool.getTimeBetweenEvictionRuns().toMillis());
2861 }
2862 {
2863 genericObjectPool.setSoftMinEvictableIdleTimeMillis(12135L);
2864 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleDuration().toMillis());
2865 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleTimeMillis());
2866 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleTime().toMillis());
2867 }
2868 {
2869 genericObjectPool.setBlockWhenExhausted(true);
2870 assertTrue(genericObjectPool.getBlockWhenExhausted());
2871 genericObjectPool.setBlockWhenExhausted(false);
2872 assertFalse(genericObjectPool.getBlockWhenExhausted());
2873 }
2874 }
2875
2876 @Test
2877 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2878 public void testStartAndStopEvictor() throws Exception {
2879
2880 genericObjectPool.setMaxIdle(6);
2881 genericObjectPool.setMaxTotal(6);
2882 genericObjectPool.setNumTestsPerEvictionRun(6);
2883 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100));
2884
2885 for (int j = 0; j < 2; j++) {
2886
2887 {
2888 final String[] active = new String[6];
2889 for (int i = 0; i < 6; i++) {
2890 active[i] = genericObjectPool.borrowObject();
2891 }
2892 for (int i = 0; i < 6; i++) {
2893 genericObjectPool.returnObject(active[i]);
2894 }
2895 }
2896
2897
2898 assertEquals(6, genericObjectPool.getNumIdle(), "Should have 6 idle");
2899
2900
2901 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(50));
2902
2903
2904 Waiter.sleepQuietly(200L);
2905
2906
2907 assertEquals(0, genericObjectPool.getNumIdle(), "Should have 0 idle");
2908
2909
2910 genericObjectPool.startEvictor(Duration.ZERO);
2911 }
2912 }
2913
2914 @Test
2915 public void testSwallowedExceptionListener() {
2916 genericObjectPool.setSwallowedExceptionListener(null);
2917 final List<Exception> swallowedExceptions = new ArrayList<>();
2918
2919
2920
2921 final SwallowedExceptionListener listener = e -> {
2922 if (swallowedExceptions.size() == 2) {
2923 throw new OutOfMemoryError();
2924 }
2925 swallowedExceptions.add(e);
2926 };
2927 genericObjectPool.setSwallowedExceptionListener(listener);
2928
2929 final Exception e1 = new Exception();
2930 final Exception e2 = new ArrayIndexOutOfBoundsException();
2931
2932 genericObjectPool.swallowException(e1);
2933 genericObjectPool.swallowException(e2);
2934
2935 assertThrows(OutOfMemoryError.class, () -> genericObjectPool.swallowException(e1));
2936
2937 assertEquals(2, swallowedExceptions.size());
2938 }
2939
2940 @Test
2941 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2942 public void testThreaded1() throws Exception {
2943 genericObjectPool.setMaxTotal(15);
2944 genericObjectPool.setMaxIdle(15);
2945 genericObjectPool.setMaxWaitMillis(1000L);
2946 runTestThreads(20, 100, 50, genericObjectPool);
2947 }
2948
2949 @Test
2950 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2951 public void testTimeoutNoLeak() throws Exception {
2952 genericObjectPool.setMaxTotal(2);
2953 genericObjectPool.setMaxWaitMillis(10);
2954 genericObjectPool.setBlockWhenExhausted(true);
2955 final String obj = genericObjectPool.borrowObject();
2956 final String obj2 = genericObjectPool.borrowObject();
2957 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2958 genericObjectPool.returnObject(obj2);
2959 genericObjectPool.returnObject(obj);
2960
2961 genericObjectPool.borrowObject();
2962 genericObjectPool.borrowObject();
2963 }
2964
2965
2966
2967
2968 @Test
2969 public void testValidateOnCreate() throws Exception {
2970 genericObjectPool.setTestOnCreate(true);
2971 genericObjectPool.addObject();
2972 assertEquals(1, simpleFactory.validateCounter);
2973 }
2974
2975
2976
2977
2978 @Test
2979 public void testValidateOnCreateFailure() throws Exception {
2980 genericObjectPool.setTestOnCreate(true);
2981 genericObjectPool.setTestOnBorrow(false);
2982 genericObjectPool.setMaxTotal(2);
2983 simpleFactory.setValid(false);
2984
2985 genericObjectPool.addObject();
2986 genericObjectPool.addObject();
2987 assertEquals(0, genericObjectPool.getNumIdle());
2988 assertEquals(0, genericObjectPool.getNumActive());
2989 simpleFactory.setValid(true);
2990 final String obj = genericObjectPool.borrowObject();
2991 assertNotNull(obj);
2992 genericObjectPool.addObject();
2993
2994 assertEquals(1, genericObjectPool.getNumIdle());
2995 assertEquals(1, genericObjectPool.getNumActive());
2996 }
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006 @Test
3007 public void testValidationFailureOnReturnFreesCapacity() throws Exception {
3008 final SimpleFactory factory = new SimpleFactory();
3009 factory.setValid(false);
3010 factory.setValidationEnabled(true);
3011 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory)) {
3012 pool.setMaxTotal(2);
3013 pool.setMaxWaitMillis(1500);
3014 pool.setTestOnReturn(true);
3015 pool.setTestOnBorrow(false);
3016
3017 final WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
3018 thread1.start();
3019
3020 final WaitingTestThread thread2 = new WaitingTestThread(pool, 500);
3021 thread2.start();
3022 Thread.sleep(50);
3023
3024 final String obj = pool.borrowObject();
3025 pool.returnObject(obj);
3026 }
3027 }
3028
3029
3030 @Test
3031 public void testValidationOnCreateOnly() throws Exception {
3032 genericObjectPool.setMaxTotal(1);
3033 genericObjectPool.setTestOnCreate(true);
3034 genericObjectPool.setTestOnBorrow(false);
3035 genericObjectPool.setTestOnReturn(false);
3036 genericObjectPool.setTestWhileIdle(false);
3037
3038 final String o1 = genericObjectPool.borrowObject();
3039 assertEquals("0", o1);
3040 final Timer t = new Timer();
3041 t.schedule(
3042 new TimerTask() {
3043 @Override
3044 public void run() {
3045 genericObjectPool.returnObject(o1);
3046 }
3047 }, 3000);
3048
3049 final String o2 = genericObjectPool.borrowObject();
3050 assertEquals("0", o2);
3051
3052 assertEquals(1, simpleFactory.validateCounter);
3053 }
3054
3055 @Test
3056 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3057 public void testWhenExhaustedBlock() throws Exception {
3058 genericObjectPool.setMaxTotal(1);
3059 genericObjectPool.setBlockWhenExhausted(true);
3060 genericObjectPool.setMaxWaitMillis(10L);
3061 final String obj1 = genericObjectPool.borrowObject();
3062 assertNotNull(obj1);
3063 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
3064 genericObjectPool.returnObject(obj1);
3065 genericObjectPool.close();
3066 }
3067
3068
3069
3070
3071
3072
3073 @Test
3074 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3075 public void testWhenExhaustedBlockClosePool() throws Exception {
3076 genericObjectPool.setMaxTotal(1);
3077 genericObjectPool.setBlockWhenExhausted(true);
3078 genericObjectPool.setMaxWaitMillis(-1);
3079 final Object obj1 = genericObjectPool.borrowObject();
3080
3081
3082 assertNotNull(obj1);
3083
3084
3085 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200);
3086 wtt.start();
3087
3088 Thread.sleep(200);
3089
3090
3091 genericObjectPool.close();
3092
3093
3094 Thread.sleep(200);
3095
3096
3097 assertTrue(wtt.thrown instanceof InterruptedException);
3098 }
3099
3100 @Test
3101 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3102 public void testWhenExhaustedBlockInterrupt() throws Exception {
3103 genericObjectPool.setMaxTotal(1);
3104 genericObjectPool.setBlockWhenExhausted(true);
3105 genericObjectPool.setMaxWaitMillis(-1);
3106 final String obj1 = genericObjectPool.borrowObject();
3107
3108
3109 assertNotNull(obj1);
3110
3111
3112 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200000);
3113 wtt.start();
3114
3115 Thread.sleep(200);
3116 wtt.interrupt();
3117
3118
3119 Thread.sleep(200);
3120
3121
3122 assertTrue(wtt.thrown instanceof InterruptedException);
3123
3124
3125 genericObjectPool.returnObject(obj1);
3126
3127
3128 genericObjectPool.setMaxWaitMillis(10L);
3129 String obj2 = null;
3130 try {
3131 obj2 = genericObjectPool.borrowObject();
3132 assertNotNull(obj2);
3133 } catch (final NoSuchElementException e) {
3134
3135 fail("NoSuchElementException not expected");
3136 }
3137 genericObjectPool.returnObject(obj2);
3138 genericObjectPool.close();
3139
3140 }
3141
3142 @Test
3143 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3144 public void testWhenExhaustedFail() throws Exception {
3145 genericObjectPool.setMaxTotal(1);
3146 genericObjectPool.setBlockWhenExhausted(false);
3147 final String obj1 = genericObjectPool.borrowObject();
3148 assertNotNull(obj1);
3149 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
3150 genericObjectPool.returnObject(obj1);
3151 assertEquals(1, genericObjectPool.getNumIdle());
3152 genericObjectPool.close();
3153 }
3154
3155 }