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
21 import static org.hamcrest.MatcherAssert.assertThat;
22 import static org.hamcrest.Matchers.lessThanOrEqualTo;
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertFalse;
25 import static org.junit.jupiter.api.Assertions.assertNotEquals;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertNull;
28 import static org.junit.jupiter.api.Assertions.assertThrows;
29 import static org.junit.jupiter.api.Assertions.assertTrue;
30 import static org.junit.jupiter.api.Assertions.fail;
31
32 import java.lang.management.ManagementFactory;
33 import java.lang.ref.WeakReference;
34 import java.nio.charset.UnsupportedCharsetException;
35 import java.time.Duration;
36 import java.time.Instant;
37 import java.util.ArrayList;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.NoSuchElementException;
41 import java.util.Objects;
42 import java.util.Random;
43 import java.util.Set;
44 import java.util.Timer;
45 import java.util.TimerTask;
46 import java.util.concurrent.Semaphore;
47 import java.util.concurrent.TimeUnit;
48 import java.util.concurrent.atomic.AtomicBoolean;
49 import java.util.concurrent.atomic.AtomicInteger;
50
51 import javax.management.MBeanServer;
52 import javax.management.ObjectName;
53
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 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 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 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 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 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(0);
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 java.util.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 long elapsedTimeMillis) {
860 return new BasePooledObjectFactory<String>() {
861 @Override
862 public String create() throws InterruptedException {
863 Thread.sleep(elapsedTimeMillis);
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
993 @Test
994 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
995 public void testAddObject() throws Exception {
996 assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle");
997 genericObjectPool.addObject();
998 assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle");
999 assertEquals(0, genericObjectPool.getNumActive(), "should be zero active");
1000 final String obj = genericObjectPool.borrowObject();
1001 assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle");
1002 assertEquals(1, genericObjectPool.getNumActive(), "should be one active");
1003 genericObjectPool.returnObject(obj);
1004 assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle");
1005 assertEquals(0, genericObjectPool.getNumActive(), "should be zero active");
1006 }
1007
1008 @Test
1009 public void testAppendStats() {
1010 assertFalse(genericObjectPool.getMessageStatistics());
1011 assertEquals("foo", genericObjectPool.appendStats("foo"));
1012 try (final GenericObjectPool<?> pool = new GenericObjectPool<>(new SimpleFactory())) {
1013 pool.setMessagesStatistics(true);
1014 assertNotEquals("foo", pool.appendStats("foo"));
1015 pool.setMessagesStatistics(false);
1016 assertEquals("foo", pool.appendStats("foo"));
1017 }
1018 }
1019
1020
1021
1022
1023
1024
1025 @SuppressWarnings({
1026 "rawtypes", "unchecked"
1027 })
1028 @Test
1029 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1030 public void testBorrowObjectFairness() throws Exception {
1031
1032 final int numThreads = 40;
1033 final int maxTotal = 40;
1034
1035 final GenericObjectPoolConfig config = new GenericObjectPoolConfig();
1036 config.setMaxTotal(maxTotal);
1037 config.setMaxIdle(maxTotal);
1038 config.setFairness(true);
1039 config.setLifo(false);
1040
1041 genericObjectPool = new GenericObjectPool(simpleFactory, config);
1042
1043
1044 final String[] objects = new String[maxTotal];
1045 for (int i = 0; i < maxTotal; i++) {
1046 objects[i] = genericObjectPool.borrowObject();
1047 }
1048
1049
1050 final TestThread[] threads = new TestThread[numThreads];
1051 for(int i=0;i<numThreads;i++) {
1052 threads[i] = new TestThread(genericObjectPool, 1, 0, 2000, false, String.valueOf(i % maxTotal));
1053 final Thread t = new Thread(threads[i]);
1054 t.start();
1055
1056 try {
1057 Thread.sleep(10);
1058 } catch (final InterruptedException e) {
1059 fail(e.toString());
1060 }
1061 }
1062
1063
1064 for (int i = 0; i < maxTotal; i++) {
1065 genericObjectPool.returnObject(objects[i]);
1066 }
1067
1068
1069 for (int i = 0; i < numThreads; i++) {
1070 while (!threads[i].complete()) {
1071 Waiter.sleepQuietly(500L);
1072 }
1073 if (threads[i].failed()) {
1074 fail("Thread " + i + " failed: " + threads[i].error.toString());
1075 }
1076 }
1077 }
1078
1079 @Test
1080 public void testBorrowTimings() throws Exception {
1081
1082 final String object = genericObjectPool.borrowObject();
1083 final PooledObject<String> po = genericObjectPool.getPooledObject(object);
1084
1085
1086
1087
1088
1089 final Instant lastBorrowInstant1 = po.getLastBorrowInstant();
1090 final Instant lastReturnInstant1 = po.getLastReturnInstant();
1091 final Instant lastUsedInstant1 = po.getLastUsedInstant();
1092
1093 assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastBorrowInstant1));
1094 assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastReturnInstant1));
1095 assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastUsedInstant1));
1096 assertThat(po.getCreateTime(), lessThanOrEqualTo(lastBorrowInstant1.toEpochMilli()));
1097 assertThat(po.getCreateTime(), lessThanOrEqualTo(lastReturnInstant1.toEpochMilli()));
1098 assertThat(po.getCreateTime(), lessThanOrEqualTo(lastUsedInstant1.toEpochMilli()));
1099
1100
1101
1102 Thread.sleep(200);
1103
1104 assertFalse(po.getActiveDuration().isNegative());
1105 assertFalse(po.getActiveDuration().isZero());
1106
1107 assertThat(1L, lessThanOrEqualTo(2L));
1108 assertThat(Duration.ZERO, lessThanOrEqualTo(Duration.ZERO.plusNanos(1)));
1109 assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getIdleDuration()));
1110
1111 assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getActiveTimeMillis()));
1112 assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getActiveTime()));
1113
1114
1115 assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getIdleTime()));
1116 assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getIdleTimeMillis()));
1117
1118 assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastBorrowInstant()));
1119 assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastReturnInstant()));
1120 assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastUsedInstant()));
1121
1122 assertThat(lastBorrowInstant1, lessThanOrEqualTo(po.getLastBorrowInstant()));
1123 assertThat(lastReturnInstant1, lessThanOrEqualTo(po.getLastReturnInstant()));
1124 assertThat(lastUsedInstant1, lessThanOrEqualTo(po.getLastUsedInstant()));
1125
1126 genericObjectPool.returnObject(object);
1127
1128 assertFalse(po.getActiveDuration().isNegative());
1129 assertFalse(po.getActiveDuration().isZero());
1130 assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getActiveTimeMillis()));
1131 assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getActiveTime()));
1132
1133 assertThat(lastBorrowInstant1, lessThanOrEqualTo(po.getLastBorrowInstant()));
1134 assertThat(lastReturnInstant1, lessThanOrEqualTo(po.getLastReturnInstant()));
1135 assertThat(lastUsedInstant1, lessThanOrEqualTo(po.getLastUsedInstant()));
1136 }
1137
1138
1139
1140
1141
1142
1143 @Test
1144 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1145 public void testBrokenFactoryShouldNotBlockPool() throws Exception {
1146 final int maxTotal = 1;
1147
1148 simpleFactory.setMaxTotal(maxTotal);
1149 genericObjectPool.setMaxTotal(maxTotal);
1150 genericObjectPool.setBlockWhenExhausted(true);
1151 genericObjectPool.setTestOnBorrow(true);
1152
1153
1154
1155 String obj = null;
1156 Exception ex = null;
1157 simpleFactory.setValid(false);
1158 try {
1159 obj = genericObjectPool.borrowObject();
1160 } catch (final Exception e) {
1161 ex = e;
1162 }
1163
1164 assertNotNull(ex);
1165 assertTrue(ex instanceof NoSuchElementException);
1166 assertNull(obj);
1167
1168
1169 simpleFactory.setValid(true);
1170
1171
1172 obj = genericObjectPool.borrowObject();
1173 assertNotNull(obj);
1174 genericObjectPool.returnObject(obj);
1175 }
1176
1177
1178 @Test
1179 public void testClientWaitStats() throws Exception {
1180 final SimpleFactory factory = new SimpleFactory();
1181
1182 factory.setMakeLatency(200);
1183 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory, new GenericObjectPoolConfig<>())) {
1184 final String s = pool.borrowObject();
1185
1186
1187 assertTrue(pool.getMaxBorrowWaitTimeMillis() >= 100);
1188 assertTrue(pool.getMeanBorrowWaitTimeMillis() >= 100);
1189 pool.returnObject(s);
1190 pool.borrowObject();
1191
1192 assertTrue(pool.getMaxBorrowWaitTimeMillis() > 100);
1193 assertTrue(pool.getMeanBorrowWaitTimeMillis() < 200);
1194 assertTrue(pool.getMeanBorrowWaitTimeMillis() > 20);
1195 }
1196 }
1197
1198 @Test
1199 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1200 public void testCloseMultiplePools1() {
1201 try (final GenericObjectPool<String> genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) {
1202 genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1203 genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1204 }
1205 genericObjectPool.close();
1206 }
1207
1208 @Test
1209 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1210 public void testCloseMultiplePools2() throws Exception {
1211 try (final GenericObjectPool<String> genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) {
1212
1213 simpleFactory.setDestroyLatency(1000L);
1214
1215 genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1216 genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION);
1217 genericObjectPool.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION);
1218 genericObjectPool2.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION);
1219 genericObjectPool.addObject();
1220 genericObjectPool2.addObject();
1221
1222 }
1223 genericObjectPool.close();
1224 }
1225
1226
1227 @Test
1228 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1229 public void testConcurrentBorrowAndEvict() throws Exception {
1230
1231 genericObjectPool.setMaxTotal(1);
1232 genericObjectPool.addObject();
1233
1234 for (int i = 0; i < 5000; i++) {
1235 final ConcurrentBorrowAndEvictThread one =
1236 new ConcurrentBorrowAndEvictThread(true);
1237 final ConcurrentBorrowAndEvictThread two =
1238 new ConcurrentBorrowAndEvictThread(false);
1239
1240 one.start();
1241 two.start();
1242 one.join();
1243 two.join();
1244
1245 genericObjectPool.returnObject(one.obj);
1246
1247
1248
1249
1250
1251
1252 }
1253 }
1254
1255
1256
1257
1258
1259
1260
1261 @Test
1262 public void testConcurrentInvalidate() throws Exception {
1263
1264 final int nObjects = 1000;
1265 genericObjectPool.setMaxTotal(nObjects);
1266 genericObjectPool.setMaxIdle(nObjects);
1267 final String[] obj = new String[nObjects];
1268 for (int i = 0; i < nObjects; i++) {
1269 obj[i] = genericObjectPool.borrowObject();
1270 }
1271 for (int i = 0; i < nObjects; i++) {
1272 if (i % 2 == 0) {
1273 genericObjectPool.returnObject(obj[i]);
1274 }
1275 }
1276 final int nThreads = 20;
1277 final int nIterations = 60;
1278 final InvalidateThread[] threads = new InvalidateThread[nThreads];
1279
1280 final ArrayList<Integer> targets = new ArrayList<>();
1281 final Random random = new Random();
1282 for (int j = 0; j < nIterations; j++) {
1283
1284 Integer targ = Integer.valueOf(random.nextInt(nObjects));
1285 while (targets.contains(targ)) {
1286 targ = Integer.valueOf(random.nextInt(nObjects));
1287 }
1288 targets.add(targ);
1289
1290 for (int i = 0; i < nThreads; i++) {
1291 threads[i] = new InvalidateThread(genericObjectPool, obj[targ.intValue()]);
1292 }
1293 for (int i = 0; i < nThreads; i++) {
1294 new Thread(threads[i]).start();
1295 }
1296 boolean done = false;
1297 while (!done) {
1298 done = true;
1299 for (int i = 0; i < nThreads; i++) {
1300 done = done && threads[i].complete();
1301 }
1302 Thread.sleep(100);
1303 }
1304 }
1305 assertEquals(nIterations, genericObjectPool.getDestroyedCount());
1306 }
1307
1308 @Test
1309 public void testConstructorNullFactory() {
1310
1311 assertThrows(IllegalArgumentException.class,
1312 () -> new GenericObjectPool<>(null));
1313 }
1314
1315 @Test
1316 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1317 public void testConstructors() {
1318
1319
1320 final int minIdle = 2;
1321 final Duration maxWaitDuration = Duration.ofMillis(3);
1322 final long maxWaitMillis = maxWaitDuration.toMillis();
1323 final int maxIdle = 4;
1324 final int maxTotal = 5;
1325 final Duration minEvictableIdleDuration = Duration.ofMillis(6);
1326 final long minEvictableIdleMillis = minEvictableIdleDuration.toMillis();
1327 final int numTestsPerEvictionRun = 7;
1328 final boolean testOnBorrow = true;
1329 final boolean testOnReturn = true;
1330 final boolean testWhileIdle = true;
1331 final long timeBetweenEvictionRunsMillis = 8;
1332 final boolean blockWhenExhausted = false;
1333 final boolean lifo = false;
1334 final PooledObjectFactory<Object> dummyFactory = new DummyFactory();
1335 try (GenericObjectPool<Object> dummyPool = new GenericObjectPool<>(dummyFactory)) {
1336 assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_IDLE, dummyPool.getMaxIdle());
1337 assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, dummyPool.getMaxWaitMillis());
1338 assertEquals(GenericObjectPoolConfig.DEFAULT_MIN_IDLE, dummyPool.getMinIdle());
1339 assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL, dummyPool.getMaxTotal());
1340 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
1341 dummyPool.getMinEvictableIdleTimeMillis());
1342 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME,
1343 dummyPool.getMinEvictableIdleTime());
1344 assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME,
1345 dummyPool.getMinEvictableIdleDuration());
1346 assertEquals(BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
1347 dummyPool.getNumTestsPerEvictionRun());
1348 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW),
1349 Boolean.valueOf(dummyPool.getTestOnBorrow()));
1350 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN),
1351 Boolean.valueOf(dummyPool.getTestOnReturn()));
1352 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE),
1353 Boolean.valueOf(dummyPool.getTestWhileIdle()));
1354 assertEquals(BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS,
1355 dummyPool.getDurationBetweenEvictionRuns());
1356 assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
1357 dummyPool.getTimeBetweenEvictionRunsMillis());
1358 assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS,
1359 dummyPool.getTimeBetweenEvictionRuns());
1360 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED),
1361 Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
1362 assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_LIFO), Boolean.valueOf(dummyPool.getLifo()));
1363 }
1364
1365 final GenericObjectPoolConfig<Object> config = new GenericObjectPoolConfig<>();
1366 config.setLifo(lifo);
1367 config.setMaxIdle(maxIdle);
1368 config.setMinIdle(minIdle);
1369 config.setMaxTotal(maxTotal);
1370 config.setMaxWait(maxWaitDuration);
1371 config.setMinEvictableIdleTimeMillis(minEvictableIdleMillis);
1372 assertEquals(minEvictableIdleMillis, config.getMinEvictableIdleTime().toMillis());
1373 config.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
1374 config.setTestOnBorrow(testOnBorrow);
1375 config.setTestOnReturn(testOnReturn);
1376 config.setTestWhileIdle(testWhileIdle);
1377 config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
1378 assertEquals(timeBetweenEvictionRunsMillis, config.getTimeBetweenEvictionRuns().toMillis());
1379 config.setBlockWhenExhausted(blockWhenExhausted);
1380 try (GenericObjectPool<Object> dummyPool = new GenericObjectPool<>(dummyFactory, config)) {
1381 assertEquals(maxIdle, dummyPool.getMaxIdle());
1382 assertEquals(maxWaitDuration, dummyPool.getMaxWaitDuration());
1383 assertEquals(maxWaitMillis, dummyPool.getMaxWaitMillis());
1384 assertEquals(minIdle, dummyPool.getMinIdle());
1385 assertEquals(maxTotal, dummyPool.getMaxTotal());
1386 assertEquals(minEvictableIdleMillis, dummyPool.getMinEvictableIdleTimeMillis());
1387 assertEquals(numTestsPerEvictionRun, dummyPool.getNumTestsPerEvictionRun());
1388 assertEquals(Boolean.valueOf(testOnBorrow), Boolean.valueOf(dummyPool.getTestOnBorrow()));
1389 assertEquals(Boolean.valueOf(testOnReturn), Boolean.valueOf(dummyPool.getTestOnReturn()));
1390 assertEquals(Boolean.valueOf(testWhileIdle), Boolean.valueOf(dummyPool.getTestWhileIdle()));
1391 assertEquals(timeBetweenEvictionRunsMillis, dummyPool.getTimeBetweenEvictionRunsMillis());
1392 assertEquals(Boolean.valueOf(blockWhenExhausted), Boolean.valueOf(dummyPool.getBlockWhenExhausted()));
1393 assertEquals(Boolean.valueOf(lifo), Boolean.valueOf(dummyPool.getLifo()));
1394 }
1395 }
1396
1397 @Test
1398 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1399 public void testDefaultConfiguration() {
1400 assertConfiguration(new GenericObjectPoolConfig<>(),genericObjectPool);
1401 }
1402
1403
1404
1405
1406
1407
1408
1409 @Test
1410 public void testEqualsIndiscernible() throws Exception {
1411 final HashSetFactory factory = new HashSetFactory();
1412 try (final GenericObjectPool<HashSet<String>> pool = new GenericObjectPool<>(factory,
1413 new GenericObjectPoolConfig<>())) {
1414 final HashSet<String> s1 = pool.borrowObject();
1415 final HashSet<String> s2 = pool.borrowObject();
1416 pool.returnObject(s1);
1417 pool.returnObject(s2);
1418 }
1419 }
1420
1421 @Test
1422 public void testErrorFactoryDoesNotBlockThreads() throws Exception {
1423
1424 final CreateErrorFactory factory = new CreateErrorFactory();
1425 try (final GenericObjectPool<String> createFailFactoryPool = new GenericObjectPool<>(factory)) {
1426
1427 createFailFactoryPool.setMaxTotal(1);
1428
1429
1430 final WaitingTestThread thread1 = new WaitingTestThread(createFailFactoryPool, 0);
1431 thread1.start();
1432
1433
1434 while (!factory.hasQueuedThreads()) {
1435 Thread.sleep(200);
1436 }
1437
1438
1439 final WaitingTestThread thread2 = new WaitingTestThread(createFailFactoryPool, 0);
1440 thread2.start();
1441
1442
1443
1444
1445
1446 Thread.sleep(1000);
1447
1448
1449 factory.release();
1450
1451 factory.release();
1452
1453
1454 boolean threadRunning = true;
1455 int count = 0;
1456 while (threadRunning && count < 15) {
1457 threadRunning = thread1.isAlive();
1458 threadRunning = thread2.isAlive();
1459 Thread.sleep(200);
1460 count++;
1461 }
1462 assertFalse(thread1.isAlive());
1463 assertFalse(thread2.isAlive());
1464
1465 assertTrue(thread1.thrown instanceof UnknownError);
1466 assertTrue(thread2.thrown instanceof UnknownError);
1467 }
1468 }
1469
1470
1471
1472
1473
1474
1475
1476 @Test
1477 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1478 public void testEvictAddObjects() throws Exception {
1479 simpleFactory.setMakeLatency(300);
1480 simpleFactory.setMaxTotal(2);
1481 genericObjectPool.setMaxTotal(2);
1482 genericObjectPool.setMinIdle(1);
1483 genericObjectPool.borrowObject();
1484
1485
1486 final TestThread<String> borrower = new TestThread<>(genericObjectPool, 1, 150, false);
1487 final Thread borrowerThread = new Thread(borrower);
1488
1489 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
1490 borrowerThread.start();
1491 borrowerThread.join();
1492 assertFalse(borrower.failed());
1493 }
1494
1495 @Test
1496 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1497 public void testEvictFIFO() throws Exception {
1498 checkEvict(false);
1499 }
1500
1501 @Test
1502 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1503 public void testEviction() throws Exception {
1504 genericObjectPool.setMaxIdle(500);
1505 genericObjectPool.setMaxTotal(500);
1506 genericObjectPool.setNumTestsPerEvictionRun(100);
1507 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250));
1508 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500));
1509 genericObjectPool.setTestWhileIdle(true);
1510
1511 final String[] active = new String[500];
1512 for (int i = 0; i < 500; i++) {
1513 active[i] = genericObjectPool.borrowObject();
1514 }
1515 for (int i = 0; i < 500; i++) {
1516 genericObjectPool.returnObject(active[i]);
1517 }
1518
1519 Waiter.sleepQuietly(1000L);
1520 assertTrue(genericObjectPool.getNumIdle() < 500, "Should be less than 500 idle, found " + genericObjectPool.getNumIdle());
1521 Waiter.sleepQuietly(600L);
1522 assertTrue(genericObjectPool.getNumIdle() < 400, "Should be less than 400 idle, found " + genericObjectPool.getNumIdle());
1523 Waiter.sleepQuietly(600L);
1524 assertTrue(genericObjectPool.getNumIdle() < 300, "Should be less than 300 idle, found " + genericObjectPool.getNumIdle());
1525 Waiter.sleepQuietly(600L);
1526 assertTrue(genericObjectPool.getNumIdle() < 200, "Should be less than 200 idle, found " + genericObjectPool.getNumIdle());
1527 Waiter.sleepQuietly(600L);
1528 assertTrue(genericObjectPool.getNumIdle() < 100, "Should be less than 100 idle, found " + genericObjectPool.getNumIdle());
1529 Waiter.sleepQuietly(600L);
1530 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1531
1532 for (int i = 0; i < 500; i++) {
1533 active[i] = genericObjectPool.borrowObject();
1534 }
1535 for (int i = 0; i < 500; i++) {
1536 genericObjectPool.returnObject(active[i]);
1537 }
1538
1539 Waiter.sleepQuietly(1000L);
1540 assertTrue(genericObjectPool.getNumIdle() < 500, "Should be less than 500 idle, found " + genericObjectPool.getNumIdle());
1541 Waiter.sleepQuietly(600L);
1542 assertTrue(genericObjectPool.getNumIdle() < 400, "Should be less than 400 idle, found " + genericObjectPool.getNumIdle());
1543 Waiter.sleepQuietly(600L);
1544 assertTrue(genericObjectPool.getNumIdle() < 300, "Should be less than 300 idle, found " + genericObjectPool.getNumIdle());
1545 Waiter.sleepQuietly(600L);
1546 assertTrue(genericObjectPool.getNumIdle() < 200, "Should be less than 200 idle, found " + genericObjectPool.getNumIdle());
1547 Waiter.sleepQuietly(600L);
1548 assertTrue(genericObjectPool.getNumIdle() < 100, "Should be less than 100 idle, found " + genericObjectPool.getNumIdle());
1549 Waiter.sleepQuietly(600L);
1550 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1551 }
1552
1553 @Test
1554 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1555 public void testEvictionInvalid() throws Exception {
1556
1557 try (final GenericObjectPool<Object> invalidFactoryPool = new GenericObjectPool<>(new InvalidFactory())) {
1558
1559 invalidFactoryPool.setMaxIdle(1);
1560 invalidFactoryPool.setMaxTotal(1);
1561 invalidFactoryPool.setTestOnBorrow(false);
1562 invalidFactoryPool.setTestOnReturn(false);
1563 invalidFactoryPool.setTestWhileIdle(true);
1564 invalidFactoryPool.setMinEvictableIdleTime(Duration.ofSeconds(100));
1565 invalidFactoryPool.setNumTestsPerEvictionRun(1);
1566
1567 final Object p = invalidFactoryPool.borrowObject();
1568 invalidFactoryPool.returnObject(p);
1569
1570
1571 final Thread t = new EvictionThread<>(invalidFactoryPool);
1572 t.start();
1573
1574
1575 Thread.sleep(300);
1576
1577 try {
1578 invalidFactoryPool.borrowObject(1);
1579 } catch (final NoSuchElementException nsee) {
1580
1581 }
1582
1583
1584 Thread.sleep(1000);
1585
1586
1587 assertEquals(0, invalidFactoryPool.getNumIdle(), "Idle count different than expected.");
1588 assertEquals(0, invalidFactoryPool.getNumActive(), "Total count different than expected.");
1589 }
1590 }
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600 @Test
1601 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1602 public void testEvictionOrder() throws Exception {
1603 checkEvictionOrder(false);
1604 tearDown();
1605 setUp();
1606 checkEvictionOrder(true);
1607 }
1608
1609 @Test
1610 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1611 public void testEvictionPolicy() throws Exception {
1612 genericObjectPool.setMaxIdle(500);
1613 genericObjectPool.setMaxTotal(500);
1614 genericObjectPool.setNumTestsPerEvictionRun(500);
1615 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250));
1616 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500));
1617 genericObjectPool.setTestWhileIdle(true);
1618
1619
1620 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(Long.toString(System.currentTimeMillis())),
1621 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1622
1623
1624 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.io.Serializable.class.getName()),
1625 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1626
1627
1628 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.util.Collections.class.getName()),
1629 "setEvictionPolicyClassName must throw an error if the class name is invalid.");
1630
1631 assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.lang.String.class.getName()),
1632 () -> "setEvictionPolicyClassName must throw an error if a class that does not implement EvictionPolicy is specified.");
1633
1634 genericObjectPool.setEvictionPolicy(new TestEvictionPolicy<>());
1635 assertEquals(TestEvictionPolicy.class.getName(), genericObjectPool.getEvictionPolicyClassName());
1636
1637 genericObjectPool.setEvictionPolicyClassName(TestEvictionPolicy.class.getName());
1638 assertEquals(TestEvictionPolicy.class.getName(), genericObjectPool.getEvictionPolicyClassName());
1639
1640 final String[] active = new String[500];
1641 for (int i = 0; i < 500; i++) {
1642 active[i] = genericObjectPool.borrowObject();
1643 }
1644 for (int i = 0; i < 500; i++) {
1645 genericObjectPool.returnObject(active[i]);
1646 }
1647
1648
1649
1650
1651 Waiter.sleepQuietly(1000L);
1652 assertEquals(500, genericObjectPool.getNumIdle(), "Should be 500 idle");
1653
1654
1655 Waiter.sleepQuietly(2000L);
1656 assertEquals(0, genericObjectPool.getNumIdle(), "Should be 0 idle");
1657 }
1658
1659 @Test
1660 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1661 public void testEvictionSoftMinIdle() throws Exception {
1662 class TimeTest extends BasePooledObjectFactory<TimeTest> {
1663 private final long createTimeMillis;
1664
1665 public TimeTest() {
1666 createTimeMillis = System.currentTimeMillis();
1667 }
1668
1669 @Override
1670 public TimeTest create() {
1671 return new TimeTest();
1672 }
1673
1674 public long getCreateTimeMillis() {
1675 return createTimeMillis;
1676 }
1677
1678 @Override
1679 public PooledObject<TimeTest> wrap(final TimeTest value) {
1680 return new DefaultPooledObject<>(value);
1681 }
1682 }
1683
1684 try (final GenericObjectPool<TimeTest> timePool = new GenericObjectPool<>(new TimeTest())) {
1685
1686 timePool.setMaxIdle(5);
1687 timePool.setMaxTotal(5);
1688 timePool.setNumTestsPerEvictionRun(5);
1689 timePool.setMinEvictableIdleDuration(Duration.ofSeconds(3));
1690 timePool.setMinEvictableIdle(Duration.ofSeconds(3));
1691 timePool.setMinEvictableIdleTime(Duration.ofSeconds(3));
1692 timePool.setSoftMinEvictableIdleTime(TestConstants.ONE_SECOND_DURATION);
1693 timePool.setMinIdle(2);
1694
1695 final TimeTest[] active = new TimeTest[5];
1696 final Long[] creationTime = new Long[5];
1697 for (int i = 0; i < 5; i++) {
1698 active[i] = timePool.borrowObject();
1699 creationTime[i] = Long.valueOf(active[i].getCreateTimeMillis());
1700 }
1701
1702 for (int i = 0; i < 5; i++) {
1703 timePool.returnObject(active[i]);
1704 }
1705
1706
1707 Thread.sleep(1500L);
1708 timePool.evict();
1709 assertEquals(2, timePool.getNumIdle(), "Idle count different than expected.");
1710
1711
1712 Thread.sleep(2000L);
1713 timePool.evict();
1714 assertEquals(0, timePool.getNumIdle(), "Idle count different than expected.");
1715 }
1716 }
1717
1718 @Test
1719 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1720 public void testEvictionWithNegativeNumTests() throws Exception {
1721
1722 genericObjectPool.setMaxIdle(6);
1723 genericObjectPool.setMaxTotal(6);
1724 genericObjectPool.setNumTestsPerEvictionRun(-2);
1725 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
1726 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
1727
1728 final String[] active = new String[6];
1729 for (int i = 0; i < 6; i++) {
1730 active[i] = genericObjectPool.borrowObject();
1731 }
1732 for (int i = 0; i < 6; i++) {
1733 genericObjectPool.returnObject(active[i]);
1734 }
1735
1736 Waiter.sleepQuietly(100L);
1737 assertTrue(genericObjectPool.getNumIdle() <= 6, "Should at most 6 idle, found " + genericObjectPool.getNumIdle());
1738 Waiter.sleepQuietly(100L);
1739 assertTrue(genericObjectPool.getNumIdle() <= 3, "Should at most 3 idle, found " + genericObjectPool.getNumIdle());
1740 Waiter.sleepQuietly(100L);
1741 assertTrue(genericObjectPool.getNumIdle() <= 2, "Should be at most 2 idle, found " + genericObjectPool.getNumIdle());
1742 Waiter.sleepQuietly(100L);
1743 assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle());
1744 }
1745
1746 @Test
1747 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1748 public void testEvictLIFO() throws Exception {
1749 checkEvict(true);
1750 }
1751
1752
1753
1754
1755
1756
1757
1758 @Test
1759 public void testEvictorVisiting() throws Exception {
1760 checkEvictorVisiting(true);
1761 checkEvictorVisiting(false);
1762 }
1763
1764 @Test
1765 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1766 public void testEvictWhileEmpty() throws Exception {
1767 genericObjectPool.evict();
1768 genericObjectPool.evict();
1769 genericObjectPool.close();
1770 }
1771
1772 @Test
1773 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1774 public void testExceptionInValidationDuringEviction() throws Exception {
1775 genericObjectPool.setMaxIdle(1);
1776 genericObjectPool.setMinEvictableIdleTime(Duration.ZERO);
1777 genericObjectPool.setTestWhileIdle(true);
1778
1779 final String active = genericObjectPool.borrowObject();
1780 genericObjectPool.returnObject(active);
1781
1782 simpleFactory.setThrowExceptionOnValidate(true);
1783
1784 assertThrows(RuntimeException.class, () -> genericObjectPool.evict());
1785 assertEquals(0, genericObjectPool.getNumActive());
1786 assertEquals(0, genericObjectPool.getNumIdle());
1787 }
1788
1789 @Test
1790 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1791 public void testExceptionOnActivateDuringBorrow() throws Exception {
1792 final String obj1 = genericObjectPool.borrowObject();
1793 final String obj2 = genericObjectPool.borrowObject();
1794 genericObjectPool.returnObject(obj1);
1795 genericObjectPool.returnObject(obj2);
1796 simpleFactory.setThrowExceptionOnActivate(true);
1797 simpleFactory.setEvenValid(false);
1798
1799
1800 final String obj = genericObjectPool.borrowObject();
1801 assertEquals(1, genericObjectPool.getNumActive());
1802 assertEquals(0, genericObjectPool.getNumIdle());
1803
1804 genericObjectPool.returnObject(obj);
1805 simpleFactory.setValid(false);
1806
1807
1808 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
1809 assertEquals(0, genericObjectPool.getNumActive());
1810 assertEquals(0, genericObjectPool.getNumIdle());
1811 }
1812
1813 @Test
1814 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1815 public void testExceptionOnDestroyDuringBorrow() throws Exception {
1816 simpleFactory.setThrowExceptionOnDestroy(true);
1817 genericObjectPool.setTestOnBorrow(true);
1818 genericObjectPool.borrowObject();
1819 simpleFactory.setValid(false);
1820 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
1821 assertEquals(1, genericObjectPool.getNumActive());
1822 assertEquals(0, genericObjectPool.getNumIdle());
1823 }
1824
1825 @Test
1826 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1827 public void testExceptionOnDestroyDuringReturn() throws Exception {
1828 simpleFactory.setThrowExceptionOnDestroy(true);
1829 genericObjectPool.setTestOnReturn(true);
1830 final String obj1 = genericObjectPool.borrowObject();
1831 genericObjectPool.borrowObject();
1832 simpleFactory.setValid(false);
1833 genericObjectPool.returnObject(obj1);
1834 assertEquals(1, genericObjectPool.getNumActive());
1835 assertEquals(0, genericObjectPool.getNumIdle());
1836 }
1837
1838 @Test
1839 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1840 public void testExceptionOnPassivateDuringReturn() throws Exception {
1841 final String obj = genericObjectPool.borrowObject();
1842 simpleFactory.setThrowExceptionOnPassivate(true);
1843 genericObjectPool.returnObject(obj);
1844 assertEquals(0,genericObjectPool.getNumIdle());
1845 }
1846
1847 @Test
1848 public void testFailingFactoryDoesNotBlockThreads() throws Exception {
1849
1850 final CreateFailFactory factory = new CreateFailFactory();
1851 try (final GenericObjectPool<String> createFailFactoryPool = new GenericObjectPool<>(factory)) {
1852
1853 createFailFactoryPool.setMaxTotal(1);
1854
1855
1856 final WaitingTestThread thread1 = new WaitingTestThread(createFailFactoryPool, 0);
1857 thread1.start();
1858
1859
1860 while (!factory.hasQueuedThreads()) {
1861 Thread.sleep(200);
1862 }
1863
1864
1865 final WaitingTestThread thread2 = new WaitingTestThread(createFailFactoryPool, 0);
1866 thread2.start();
1867
1868
1869
1870
1871
1872 Thread.sleep(1000);
1873
1874
1875 factory.release();
1876
1877 factory.release();
1878
1879
1880 boolean threadRunning = true;
1881 int count = 0;
1882 while (threadRunning && count < 15) {
1883 threadRunning = thread1.isAlive();
1884 threadRunning = thread2.isAlive();
1885 Thread.sleep(200);
1886 count++;
1887 }
1888 assertFalse(thread1.isAlive());
1889 assertFalse(thread2.isAlive());
1890
1891 assertTrue(thread1.thrown instanceof UnsupportedCharsetException);
1892 assertTrue(thread2.thrown instanceof UnsupportedCharsetException);
1893 }
1894 }
1895
1896 @Test
1897 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
1898 public void testFIFO() throws Exception {
1899 genericObjectPool.setLifo(false);
1900 genericObjectPool.addObject();
1901 genericObjectPool.addObject();
1902 genericObjectPool.addObject();
1903 assertEquals("0", genericObjectPool.borrowObject(), "Oldest");
1904 assertEquals("1", genericObjectPool.borrowObject(), "Middle");
1905 assertEquals("2", genericObjectPool.borrowObject(), "Youngest");
1906 final String o = genericObjectPool.borrowObject();
1907 assertEquals("3", o, "new-3");
1908 genericObjectPool.returnObject(o);
1909 assertEquals(o, genericObjectPool.borrowObject(), "returned-3");
1910 assertEquals("4", genericObjectPool.borrowObject(), "new-4");
1911 }
1912
1913 @Test
1914 public void testGetFactoryType_DefaultPooledObjectFactory() {
1915 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createDefaultPooledObjectFactory())) {
1916 assertNotNull(pool.getFactoryType());
1917 }
1918 }
1919
1920 @Test
1921 public void testGetFactoryType_NullPooledObjectFactory() {
1922 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(createNullPooledObjectFactory())) {
1923 assertNotNull(pool.getFactoryType());
1924 }
1925 }
1926
1927 @Test
1928 public void testGetFactoryType_PoolUtilsSynchronizedDefaultPooledFactory() {
1929 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1930 PoolUtils.synchronizedPooledFactory(createDefaultPooledObjectFactory()))) {
1931 assertNotNull(pool.getFactoryType());
1932 }
1933 }
1934
1935 @Test
1936 public void testGetFactoryType_PoolUtilsSynchronizedNullPooledFactory() {
1937 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1938 PoolUtils.synchronizedPooledFactory(createNullPooledObjectFactory()))) {
1939 assertNotNull(pool.getFactoryType());
1940 }
1941 }
1942
1943 @Test
1944 public void testGetFactoryType_SynchronizedDefaultPooledObjectFactory() {
1945 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1946 new TestSynchronizedPooledObjectFactory<>(createDefaultPooledObjectFactory()))) {
1947 assertNotNull(pool.getFactoryType());
1948 }
1949 }
1950
1951 @Test
1952 public void testGetFactoryType_SynchronizedNullPooledObjectFactory() {
1953 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1954 new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) {
1955 assertNotNull(pool.getFactoryType());
1956 }
1957 }
1958
1959 @Test
1960 public void testGetStatsString() {
1961 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(
1962 new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) {
1963 assertNotNull(pool.getStatsString());
1964 }
1965 }
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975 @Test
1976 public void testInvalidateFreesCapacity() throws Exception {
1977 final SimpleFactory factory = new SimpleFactory();
1978 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory)) {
1979 pool.setMaxTotal(2);
1980 pool.setMaxWaitMillis(500);
1981
1982 final WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
1983 thread1.start();
1984
1985 final String obj = pool.borrowObject();
1986
1987 final WaitingTestThread thread2 = new WaitingTestThread(pool, 100);
1988 thread2.start();
1989
1990 Thread.sleep(20);
1991 pool.invalidateObject(obj);
1992 Thread.sleep(600);
1993 if (thread2.thrown != null) {
1994 fail(thread2.thrown.toString());
1995 }
1996 }
1997 }
1998
1999
2000
2001
2002 @Test
2003 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2004 public void testJmxRegistration() {
2005 final ObjectName oname = genericObjectPool.getJmxName();
2006 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
2007 final Set<ObjectName> result = mbs.queryNames(oname, null);
2008 assertEquals(1, result.size());
2009 genericObjectPool.jmxUnregister();
2010
2011 final GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
2012 config.setJmxEnabled(false);
2013 try (final GenericObjectPool<String> poolWithoutJmx = new GenericObjectPool<>(simpleFactory, config)) {
2014 assertNull(poolWithoutJmx.getJmxName());
2015 config.setJmxEnabled(true);
2016 poolWithoutJmx.jmxUnregister();
2017 }
2018
2019 config.setJmxNameBase(null);
2020 try (final GenericObjectPool<String> poolWithDefaultJmxNameBase = new GenericObjectPool<>(simpleFactory, config)) {
2021 assertNotNull(poolWithDefaultJmxNameBase.getJmxName());
2022 }
2023 }
2024
2025 @Test
2026 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2027 public void testLIFO() throws Exception {
2028 final String o;
2029 genericObjectPool.setLifo(true);
2030 genericObjectPool.addObject();
2031 genericObjectPool.addObject();
2032 genericObjectPool.addObject();
2033 assertEquals("2", genericObjectPool.borrowObject(), "Youngest");
2034 assertEquals("1", genericObjectPool.borrowObject(), "Middle");
2035 assertEquals("0", genericObjectPool.borrowObject(), "Oldest");
2036 o = genericObjectPool.borrowObject();
2037 assertEquals("3", o, "new-3");
2038 genericObjectPool.returnObject(o);
2039 assertEquals(o, genericObjectPool.borrowObject(), "returned-3");
2040 assertEquals("4", genericObjectPool.borrowObject(), "new-4");
2041 }
2042
2043
2044
2045
2046
2047
2048
2049 @Test
2050 @Disabled
2051 @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
2052 public void testLivenessOnTransientFactoryFailure() throws Exception {
2053 final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>(
2054 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_CREATE_ACTION,
2055 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION,
2056 (obj) -> false
2057 );
2058 final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory);
2059 pool.setMaxWait(Duration.ofMillis(100));
2060 pool.setTestOnReturn(true);
2061 pool.setMaxTotal(1);
2062 final Waiter w = pool.borrowObject();
2063 final AtomicBoolean failed = new AtomicBoolean(false);
2064 final Thread t = new Thread(() -> {
2065 try {
2066 pool.borrowObject();
2067 } catch (final Exception e) {
2068 failed.set(true);
2069 }
2070 });
2071 Thread.sleep(10);
2072 t.start();
2073
2074 Thread.sleep(10);
2075 factory.disconnect();
2076 pool.returnObject(w);
2077 Thread.sleep(10);
2078 factory.connect();
2079
2080 t.join();
2081 pool.close();
2082 if (failed.get()) {
2083 fail("Borrower timed out waiting for an instance");
2084 }
2085 }
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097 @Test
2098 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2099 public void testMakeConcurrentWithReturn() throws Exception {
2100 genericObjectPool.setTestOnBorrow(true);
2101 simpleFactory.setValid(true);
2102
2103 final WaitingTestThread thread1 = new WaitingTestThread(genericObjectPool, 200);
2104 thread1.start();
2105 Thread.sleep(50);
2106
2107 simpleFactory.setValidateLatency(400);
2108 final String instance = genericObjectPool.borrowObject();
2109
2110 assertEquals(simpleFactory.getMakeCounter(), genericObjectPool.getNumIdle() + 1);
2111 genericObjectPool.returnObject(instance);
2112 assertEquals(simpleFactory.getMakeCounter(), genericObjectPool.getNumIdle());
2113 }
2114
2115 @Test
2116 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2117 public void testMaxIdle() throws Exception {
2118 genericObjectPool.setMaxTotal(100);
2119 genericObjectPool.setMaxIdle(8);
2120 final String[] active = new String[100];
2121 for (int i = 0; i < 100; i++) {
2122 active[i] = genericObjectPool.borrowObject();
2123 }
2124 assertEquals(100, genericObjectPool.getNumActive());
2125 assertEquals(0, genericObjectPool.getNumIdle());
2126 for (int i = 0; i < 100; i++) {
2127 genericObjectPool.returnObject(active[i]);
2128 assertEquals(99 - i, genericObjectPool.getNumActive());
2129 assertEquals(i < 8 ? i + 1 : 8, genericObjectPool.getNumIdle());
2130 }
2131 }
2132
2133 @Test
2134 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2135 public void testMaxIdleZero() throws Exception {
2136 genericObjectPool.setMaxTotal(100);
2137 genericObjectPool.setMaxIdle(0);
2138 final String[] active = new String[100];
2139 for (int i = 0; i < 100; i++) {
2140 active[i] = genericObjectPool.borrowObject();
2141 }
2142 assertEquals(100, genericObjectPool.getNumActive());
2143 assertEquals(0, genericObjectPool.getNumIdle());
2144 for (int i = 0; i < 100; i++) {
2145 genericObjectPool.returnObject(active[i]);
2146 assertEquals(99 - i, genericObjectPool.getNumActive());
2147 assertEquals(0, genericObjectPool.getNumIdle());
2148 }
2149 }
2150
2151
2152
2153
2154 @Test
2155 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2156 @SuppressWarnings("rawtypes")
2157 public void testMaxIdleZeroUnderLoad() {
2158
2159 final int numThreads = 199;
2160 final int numIter = 20;
2161 final int delay = 25;
2162 final int maxTotal = 10;
2163
2164 simpleFactory.setMaxTotal(maxTotal);
2165 genericObjectPool.setMaxTotal(maxTotal);
2166 genericObjectPool.setBlockWhenExhausted(true);
2167 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(-1));
2168
2169
2170 genericObjectPool.setMaxIdle(0);
2171
2172
2173 final TestThread[] threads = new TestThread[numThreads];
2174 for(int i=0;i<numThreads;i++) {
2175
2176
2177
2178 threads[i] = new TestThread<>(genericObjectPool, numIter * 2, delay * 2);
2179 final Thread t = new Thread(threads[i]);
2180 t.start();
2181 }
2182
2183 Waiter.sleepQuietly(100L);
2184
2185 for (int i = 0; i < numIter; i++) {
2186 String obj = null;
2187 try {
2188 Waiter.sleepQuietly(delay);
2189 obj = genericObjectPool.borrowObject();
2190
2191 if (genericObjectPool.getNumActive() > genericObjectPool.getMaxTotal()) {
2192 throw new IllegalStateException("Too many active objects");
2193 }
2194 Waiter.sleepQuietly(delay);
2195 } catch (final Exception e) {
2196
2197 e.printStackTrace();
2198 fail("Exception on borrow");
2199 } finally {
2200 if (obj != null) {
2201 try {
2202 genericObjectPool.returnObject(obj);
2203 } catch (final Exception e) {
2204
2205 }
2206 }
2207 }
2208 }
2209
2210 for (int i = 0; i < numThreads; i++) {
2211 while (!threads[i].complete()) {
2212 Waiter.sleepQuietly(500L);
2213 }
2214 if (threads[i].failed()) {
2215 threads[i].error.printStackTrace();
2216 fail("Thread " + i + " failed: " + threads[i].error.toString());
2217 }
2218 }
2219 }
2220
2221 @Test
2222 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2223 public void testMaxTotal() throws Exception {
2224 genericObjectPool.setMaxTotal(3);
2225 genericObjectPool.setBlockWhenExhausted(false);
2226
2227 genericObjectPool.borrowObject();
2228 genericObjectPool.borrowObject();
2229 genericObjectPool.borrowObject();
2230 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2231 }
2232
2233
2234
2235
2236
2237
2238 @Test
2239 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2240 public void testMaxTotalInvariant() {
2241 final int maxTotal = 15;
2242 simpleFactory.setEvenValid(false);
2243 simpleFactory.setDestroyLatency(100);
2244 simpleFactory.setMaxTotal(maxTotal);
2245 simpleFactory.setValidationEnabled(true);
2246 genericObjectPool.setMaxTotal(maxTotal);
2247 genericObjectPool.setMaxIdle(-1);
2248 genericObjectPool.setTestOnReturn(true);
2249 genericObjectPool.setMaxWaitMillis(1000L);
2250 runTestThreads(5, 10, 50, genericObjectPool);
2251 }
2252
2253 @Test
2254 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2255 @SuppressWarnings("rawtypes")
2256 public void testMaxTotalUnderLoad() {
2257
2258 final int numThreads = 199;
2259 final int numIter = 20;
2260 final int delay = 25;
2261 final int maxTotal = 10;
2262
2263 simpleFactory.setMaxTotal(maxTotal);
2264 genericObjectPool.setMaxTotal(maxTotal);
2265 genericObjectPool.setBlockWhenExhausted(true);
2266 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(-1));
2267
2268
2269 final TestThread[] threads = new TestThread[numThreads];
2270 for(int i=0;i<numThreads;i++) {
2271
2272
2273
2274 threads[i] = new TestThread<>(genericObjectPool, numIter * 2, delay * 2);
2275 final Thread t = new Thread(threads[i]);
2276 t.start();
2277 }
2278
2279 Waiter.sleepQuietly(5000);
2280
2281 for (int i = 0; i < numIter; i++) {
2282 String obj = null;
2283 try {
2284 Waiter.sleepQuietly(delay);
2285 obj = genericObjectPool.borrowObject();
2286
2287 if (genericObjectPool.getNumActive() > genericObjectPool.getMaxTotal()) {
2288 throw new IllegalStateException("Too many active objects");
2289 }
2290 Waiter.sleepQuietly(delay);
2291 } catch (final Exception e) {
2292
2293 e.printStackTrace();
2294 fail("Exception on borrow");
2295 } finally {
2296 if (obj != null) {
2297 try {
2298 genericObjectPool.returnObject(obj);
2299 } catch (final Exception e) {
2300
2301 }
2302 }
2303 }
2304 }
2305
2306 for (int i = 0; i < numThreads; i++) {
2307 while(!threads[i].complete()) {
2308 Waiter.sleepQuietly(500L);
2309 }
2310 if(threads[i].failed()) {
2311 fail("Thread " + i + " failed: " + threads[i].error.toString());
2312 }
2313 }
2314 }
2315
2316 @Test
2317 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2318 public void testMaxTotalZero() throws Exception {
2319 genericObjectPool.setMaxTotal(0);
2320 genericObjectPool.setBlockWhenExhausted(false);
2321 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2322 }
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332 @Test
2333 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2334 public void testMaxWaitMultiThreaded() throws Exception {
2335 final long maxWait = 500;
2336 final long holdTime = 2 * maxWait;
2337 final int threads = 10;
2338 genericObjectPool.setBlockWhenExhausted(true);
2339 genericObjectPool.setMaxWaitMillis(maxWait);
2340 genericObjectPool.setMaxTotal(threads);
2341
2342 final WaitingTestThread[] wtt = new WaitingTestThread[threads * 2];
2343 for (int i = 0; i < wtt.length; i++) {
2344 wtt[i] = new WaitingTestThread(genericObjectPool, holdTime);
2345 }
2346 final long originMillis = System.currentTimeMillis() - 1000;
2347 for (final WaitingTestThread element : wtt) {
2348 element.start();
2349 }
2350 int failed = 0;
2351 for (final WaitingTestThread element : wtt) {
2352 element.join();
2353 if (element.thrown != null){
2354 failed++;
2355 }
2356 }
2357 if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){
2358 System.out.println(
2359 "MaxWait: " + maxWait +
2360 " HoldTime: " + holdTime +
2361 " MaxTotal: " + threads +
2362 " Threads: " + wtt.length +
2363 " Failed: " + failed
2364 );
2365 for (final WaitingTestThread wt : wtt) {
2366 System.out.println(
2367 "PreBorrow: " + (wt.preBorrowMillis - originMillis) +
2368 " PostBorrow: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - originMillis : -1) +
2369 " BorrowTime: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - wt.preBorrowMillis : -1) +
2370 " PostReturn: " + (wt.postReturnMillis != 0 ? wt.postReturnMillis - originMillis : -1) +
2371 " Ended: " + (wt.endedMillis - originMillis) +
2372 " ObjId: " + wt.objectId
2373 );
2374 }
2375 }
2376 assertEquals(wtt.length / 2, failed, "Expected half the threads to fail");
2377 }
2378
2379 @Test
2380 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2381 public void testMinIdle() throws Exception {
2382 genericObjectPool.setMaxIdle(500);
2383 genericObjectPool.setMinIdle(5);
2384 genericObjectPool.setMaxTotal(10);
2385 genericObjectPool.setNumTestsPerEvictionRun(0);
2386 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
2387 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
2388 genericObjectPool.setTestWhileIdle(true);
2389
2390 Waiter.sleepQuietly(150L);
2391 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2392
2393 final String[] active = new String[5];
2394 active[0] = genericObjectPool.borrowObject();
2395
2396 Waiter.sleepQuietly(150L);
2397 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2398
2399 for (int i = 1; i < 5; i++) {
2400 active[i] = genericObjectPool.borrowObject();
2401 }
2402
2403 Waiter.sleepQuietly(150L);
2404 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2405
2406 for (int i = 0; i < 5; i++) {
2407 genericObjectPool.returnObject(active[i]);
2408 }
2409
2410 Waiter.sleepQuietly(150L);
2411 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2412 }
2413
2414 @Test
2415 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2416 public void testMinIdleMaxTotal() throws Exception {
2417 genericObjectPool.setMaxIdle(500);
2418 genericObjectPool.setMinIdle(5);
2419 genericObjectPool.setMaxTotal(10);
2420 genericObjectPool.setNumTestsPerEvictionRun(0);
2421 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50));
2422 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
2423 genericObjectPool.setTestWhileIdle(true);
2424
2425 Waiter.sleepQuietly(150L);
2426 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2427
2428 final String[] active = new String[10];
2429
2430 Waiter.sleepQuietly(150L);
2431 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2432
2433 for (int i = 0; i < 5; i++) {
2434 active[i] = genericObjectPool.borrowObject();
2435 }
2436
2437 Waiter.sleepQuietly(150L);
2438 assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle());
2439
2440 for(int i = 0 ; i < 5 ; i++) {
2441 genericObjectPool.returnObject(active[i]);
2442 }
2443
2444 Waiter.sleepQuietly(150L);
2445 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2446
2447 for (int i = 0; i < 10; i++) {
2448 active[i] = genericObjectPool.borrowObject();
2449 }
2450
2451 Waiter.sleepQuietly(150L);
2452 assertEquals(0, genericObjectPool.getNumIdle(), "Should be 0 idle, found " + genericObjectPool.getNumIdle());
2453
2454 for (int i = 0; i < 10; i++) {
2455 genericObjectPool.returnObject(active[i]);
2456 }
2457
2458 Waiter.sleepQuietly(150L);
2459 assertEquals(10, genericObjectPool.getNumIdle(), "Should be 10 idle, found " + genericObjectPool.getNumIdle());
2460 }
2461
2462
2463
2464
2465
2466
2467
2468 @Test
2469 public void testMultipleReturn() throws Exception {
2470 final WaiterFactory<String> factory = new WaiterFactory<>(0, 0, 0, 0, 0, 0);
2471 try (final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory)) {
2472 pool.setTestOnReturn(true);
2473 final Waiter waiter = pool.borrowObject();
2474 pool.returnObject(waiter);
2475 assertEquals(1, waiter.getValidationCount());
2476 assertEquals(1, waiter.getPassivationCount());
2477 try {
2478 pool.returnObject(waiter);
2479 fail("Expecting IllegalStateException from multiple return");
2480 } catch (final IllegalStateException ex) {
2481
2482 assertEquals(1, waiter.getValidationCount());
2483 assertEquals(1, waiter.getPassivationCount());
2484 }
2485 }
2486 }
2487
2488
2489 @Test
2490 public void testMultipleReturnOfSameObject() throws Exception {
2491 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(simpleFactory, new GenericObjectPoolConfig<>())) {
2492
2493 assertEquals(0, pool.getNumActive());
2494 assertEquals(0, pool.getNumIdle());
2495
2496 final String obj = pool.borrowObject();
2497
2498 assertEquals(1, pool.getNumActive());
2499 assertEquals(0, pool.getNumIdle());
2500
2501 pool.returnObject(obj);
2502
2503 assertEquals(0, pool.getNumActive());
2504 assertEquals(1, pool.getNumIdle());
2505
2506 assertThrows(IllegalStateException.class,
2507 () -> pool.returnObject(obj));
2508
2509 assertEquals(0, pool.getNumActive());
2510 assertEquals(1, pool.getNumIdle());
2511 }
2512 }
2513
2514
2515
2516
2517
2518
2519
2520 @Test
2521 public void testMutable() throws Exception {
2522 final HashSetFactory factory = new HashSetFactory();
2523 try (final GenericObjectPool<HashSet<String>> pool = new GenericObjectPool<>(factory,
2524 new GenericObjectPoolConfig<>())) {
2525 final HashSet<String> s1 = pool.borrowObject();
2526 final HashSet<String> s2 = pool.borrowObject();
2527 s1.add("One");
2528 s2.add("One");
2529 pool.returnObject(s1);
2530 pool.returnObject(s2);
2531 }
2532 }
2533
2534 @Test
2535 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2536 public void testNegativeMaxTotal() throws Exception {
2537 genericObjectPool.setMaxTotal(-1);
2538 genericObjectPool.setBlockWhenExhausted(false);
2539 final String obj = genericObjectPool.borrowObject();
2540 assertEquals(getNthObject(0), obj);
2541 genericObjectPool.returnObject(obj);
2542 }
2543
2544
2545
2546
2547 @Test
2548 public void testNoInstanceOverlap() {
2549 final int maxTotal = 5;
2550 final int numThreads = 100;
2551 final int delay = 1;
2552 final int iterations = 1000;
2553 final AtomicIntegerFactory factory = new AtomicIntegerFactory();
2554 try (final GenericObjectPool<AtomicInteger> pool = new GenericObjectPool<>(factory)) {
2555 pool.setMaxTotal(maxTotal);
2556 pool.setMaxIdle(maxTotal);
2557 pool.setTestOnBorrow(true);
2558 pool.setBlockWhenExhausted(true);
2559 pool.setMaxWaitMillis(-1);
2560 runTestThreads(numThreads, iterations, delay, pool);
2561 assertEquals(0, pool.getDestroyedByBorrowValidationCount());
2562 }
2563 }
2564
2565
2566
2567
2568 @Test
2569 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2570 public void testNoInvalidateNPE() throws Exception {
2571 genericObjectPool.setMaxTotal(1);
2572 genericObjectPool.setTestOnCreate(true);
2573 genericObjectPool.setMaxWaitMillis(-1);
2574 final String obj = genericObjectPool.borrowObject();
2575
2576 simpleFactory.setValid(false);
2577
2578 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200);
2579 wtt.start();
2580
2581 Thread.sleep(200);
2582 genericObjectPool.invalidateObject(obj);
2583
2584 simpleFactory.setValid(true);
2585 }
2586
2587
2588
2589
2590
2591 @Test
2592 @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
2593 public void testNPEOnFactoryNull() throws Exception {
2594 final DisconnectingWaiterFactory<String> factory = new DisconnectingWaiterFactory<>(
2595 () -> null,
2596 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION,
2597 DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION
2598 );
2599 final GenericObjectPool<Waiter> pool = new GenericObjectPool<>(factory);
2600 pool.setTestOnBorrow(true);
2601 pool.setMaxTotal(-1);
2602 pool.setMinIdle(1);
2603
2604 factory.disconnect();
2605 try {
2606 pool.borrowObject();
2607 fail("Expecting NullPointerException");
2608 } catch (final NullPointerException ex) {
2609
2610 }
2611 try {
2612 pool.addObject();
2613 fail("Expecting NullPointerException");
2614 } catch (final NullPointerException ex2) {
2615
2616 }
2617 try {
2618 pool.ensureMinIdle();
2619 fail("Expecting NullPointerException");
2620 } catch (final NullPointerException ex3) {
2621
2622 }
2623 pool.close();
2624 }
2625
2626 @Test
2627 public void testPreparePool() throws Exception {
2628 genericObjectPool.setMinIdle(1);
2629 genericObjectPool.setMaxTotal(1);
2630 genericObjectPool.preparePool();
2631 assertEquals(1, genericObjectPool.getNumIdle());
2632 final String obj = genericObjectPool.borrowObject();
2633 genericObjectPool.preparePool();
2634 assertEquals(0, genericObjectPool.getNumIdle());
2635 genericObjectPool.setMinIdle(0);
2636 genericObjectPool.returnObject(obj);
2637 genericObjectPool.preparePool();
2638 assertEquals(1, genericObjectPool.getNumIdle());
2639 }
2640
2641 @Test
2642 @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS)
2643 public void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception {
2644 final long maxWaitMillis = 500;
2645
2646 try (final GenericObjectPool<String> createSlowObjectFactoryPool = new GenericObjectPool<>(
2647 createSlowObjectFactory(60000))) {
2648 createSlowObjectFactoryPool.setMaxTotal(1);
2649 createSlowObjectFactoryPool.setMaxWaitMillis(maxWaitMillis);
2650
2651
2652 final WaitingTestThread thread1 = new WaitingTestThread(createSlowObjectFactoryPool, 0);
2653 thread1.start();
2654
2655
2656 Thread.sleep(100);
2657
2658
2659 assertThrows(NoSuchElementException.class, () -> createSlowObjectFactoryPool.borrowObject(maxWaitMillis),
2660 "borrowObject must fail due to timeout by maxWaitMillis");
2661
2662 assertTrue(thread1.isAlive());
2663 }
2664 }
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2676 public void testReturnObject() throws Exception {
2677
2678 genericObjectPool.setMaxTotal(1);
2679 genericObjectPool.setMaxIdle(-1);
2680 final String active = genericObjectPool.borrowObject();
2681
2682 assertEquals(1, genericObjectPool.getNumActive());
2683 assertEquals(0, genericObjectPool.getNumIdle());
2684
2685 final Thread t = new Thread(() -> genericObjectPool.close());
2686 t.start();
2687
2688 genericObjectPool.returnObject(active);
2689
2690
2691 while (t.isAlive()) {
2692 Thread.sleep(50);
2693 }
2694
2695 assertEquals(0, genericObjectPool.getNumIdle());
2696 }
2697
2698 @Test
2699 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2700 public void testSetConfig() throws Exception {
2701 final GenericObjectPoolConfig<String> expected = new GenericObjectPoolConfig<>();
2702 assertConfiguration(expected, genericObjectPool);
2703 expected.setMaxTotal(2);
2704 expected.setMaxIdle(3);
2705 expected.setMaxWait(Duration.ofMillis(5));
2706 expected.setMinEvictableIdleDuration(Duration.ofMillis(7L));
2707 expected.setNumTestsPerEvictionRun(9);
2708 expected.setTestOnCreate(true);
2709 expected.setTestOnBorrow(true);
2710 expected.setTestOnReturn(true);
2711 expected.setTestWhileIdle(true);
2712 expected.setTimeBetweenEvictionRuns(Duration.ofMillis(11L));
2713 expected.setBlockWhenExhausted(false);
2714 genericObjectPool.setConfig(expected);
2715 assertConfiguration(expected, genericObjectPool);
2716 }
2717
2718 @Test
2719 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2720 public void testSettersAndGetters() throws Exception {
2721 {
2722
2723
2724 assertNotEquals("", genericObjectPool.getCreationStackTrace());
2725 }
2726 {
2727 assertEquals(0, genericObjectPool.getBorrowedCount());
2728 }
2729 {
2730 assertEquals(0, genericObjectPool.getReturnedCount());
2731 }
2732 {
2733 assertEquals(0, genericObjectPool.getCreatedCount());
2734 }
2735 {
2736 assertEquals(0, genericObjectPool.getDestroyedCount());
2737 }
2738 {
2739 assertEquals(0, genericObjectPool.getDestroyedByEvictorCount());
2740 }
2741 {
2742 assertEquals(0, genericObjectPool.getDestroyedByBorrowValidationCount());
2743 }
2744 {
2745 assertEquals(0, genericObjectPool.getMeanActiveTimeMillis());
2746 }
2747 {
2748 assertEquals(0, genericObjectPool.getMeanIdleTimeMillis());
2749 }
2750 {
2751 assertEquals(0, genericObjectPool.getMeanBorrowWaitTimeMillis());
2752 }
2753 {
2754 assertEquals(0, genericObjectPool.getMaxBorrowWaitTimeMillis());
2755 }
2756 {
2757 assertEquals(0, genericObjectPool.getNumIdle());
2758 }
2759 {
2760 genericObjectPool.setMaxTotal(123);
2761 assertEquals(123, genericObjectPool.getMaxTotal());
2762 }
2763 {
2764 genericObjectPool.setMaxIdle(12);
2765 assertEquals(12, genericObjectPool.getMaxIdle());
2766 }
2767 {
2768 genericObjectPool.setMaxWaitMillis(1234L);
2769 assertEquals(1234L, genericObjectPool.getMaxWaitMillis());
2770 }
2771 {
2772 genericObjectPool.setMinEvictableIdleTimeMillis(12345L);
2773 assertEquals(12345L, genericObjectPool.getMinEvictableIdleDuration().toMillis());
2774 assertEquals(12345L, genericObjectPool.getMinEvictableIdleTimeMillis());
2775 assertEquals(12345L, genericObjectPool.getMinEvictableIdleTime().toMillis());
2776 }
2777 {
2778 genericObjectPool.setNumTestsPerEvictionRun(11);
2779 assertEquals(11, genericObjectPool.getNumTestsPerEvictionRun());
2780 }
2781 {
2782 genericObjectPool.setTestOnBorrow(true);
2783 assertTrue(genericObjectPool.getTestOnBorrow());
2784 genericObjectPool.setTestOnBorrow(false);
2785 assertFalse(genericObjectPool.getTestOnBorrow());
2786 }
2787 {
2788 genericObjectPool.setTestOnReturn(true);
2789 assertTrue(genericObjectPool.getTestOnReturn());
2790 genericObjectPool.setTestOnReturn(false);
2791 assertFalse(genericObjectPool.getTestOnReturn());
2792 }
2793 {
2794 genericObjectPool.setTestWhileIdle(true);
2795 assertTrue(genericObjectPool.getTestWhileIdle());
2796 genericObjectPool.setTestWhileIdle(false);
2797 assertFalse(genericObjectPool.getTestWhileIdle());
2798 }
2799 {
2800 genericObjectPool.setTimeBetweenEvictionRunsMillis(11235L);
2801 assertEquals(11235L, genericObjectPool.getDurationBetweenEvictionRuns().toMillis());
2802 assertEquals(11235L, genericObjectPool.getTimeBetweenEvictionRunsMillis());
2803 assertEquals(11235L, genericObjectPool.getTimeBetweenEvictionRuns().toMillis());
2804 }
2805 {
2806 genericObjectPool.setSoftMinEvictableIdleTimeMillis(12135L);
2807 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleDuration().toMillis());
2808 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleTimeMillis());
2809 assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleTime().toMillis());
2810 }
2811 {
2812 genericObjectPool.setBlockWhenExhausted(true);
2813 assertTrue(genericObjectPool.getBlockWhenExhausted());
2814 genericObjectPool.setBlockWhenExhausted(false);
2815 assertFalse(genericObjectPool.getBlockWhenExhausted());
2816 }
2817 }
2818
2819 @Test
2820 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2821 public void testStartAndStopEvictor() throws Exception {
2822
2823 genericObjectPool.setMaxIdle(6);
2824 genericObjectPool.setMaxTotal(6);
2825 genericObjectPool.setNumTestsPerEvictionRun(6);
2826 genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100));
2827
2828 for (int j = 0; j < 2; j++) {
2829
2830 {
2831 final String[] active = new String[6];
2832 for (int i = 0; i < 6; i++) {
2833 active[i] = genericObjectPool.borrowObject();
2834 }
2835 for (int i = 0; i < 6; i++) {
2836 genericObjectPool.returnObject(active[i]);
2837 }
2838 }
2839
2840
2841 assertEquals(6, genericObjectPool.getNumIdle(), "Should have 6 idle");
2842
2843
2844 genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(50));
2845
2846
2847 Waiter.sleepQuietly(200L);
2848
2849
2850 assertEquals(0, genericObjectPool.getNumIdle(), "Should have 0 idle");
2851
2852
2853 genericObjectPool.startEvictor(Duration.ZERO);
2854 }
2855 }
2856
2857 @Test
2858 public void testSwallowedExceptionListener() {
2859 genericObjectPool.setSwallowedExceptionListener(null);
2860 final List<Exception> swallowedExceptions = new ArrayList<>();
2861
2862
2863
2864 final SwallowedExceptionListener listener = e -> {
2865 if (swallowedExceptions.size() == 2) {
2866 throw new OutOfMemoryError();
2867 }
2868 swallowedExceptions.add(e);
2869 };
2870 genericObjectPool.setSwallowedExceptionListener(listener);
2871
2872 final Exception e1 = new Exception();
2873 final Exception e2 = new ArrayIndexOutOfBoundsException();
2874
2875 genericObjectPool.swallowException(e1);
2876 genericObjectPool.swallowException(e2);
2877
2878 assertThrows(OutOfMemoryError.class, () -> genericObjectPool.swallowException(e1));
2879
2880 assertEquals(2, swallowedExceptions.size());
2881 }
2882
2883 @Test
2884 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2885 public void testThreaded1() throws Exception {
2886 genericObjectPool.setMaxTotal(15);
2887 genericObjectPool.setMaxIdle(15);
2888 genericObjectPool.setMaxWaitMillis(1000L);
2889 runTestThreads(20, 100, 50, genericObjectPool);
2890 }
2891
2892 @Test
2893 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
2894 public void testTimeoutNoLeak() throws Exception {
2895 genericObjectPool.setMaxTotal(2);
2896 genericObjectPool.setMaxWaitMillis(10);
2897 genericObjectPool.setBlockWhenExhausted(true);
2898 final String obj = genericObjectPool.borrowObject();
2899 final String obj2 = genericObjectPool.borrowObject();
2900 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
2901 genericObjectPool.returnObject(obj2);
2902 genericObjectPool.returnObject(obj);
2903
2904 genericObjectPool.borrowObject();
2905 genericObjectPool.borrowObject();
2906 }
2907
2908
2909
2910
2911 @Test
2912 public void testValidateOnCreate() throws Exception {
2913 genericObjectPool.setTestOnCreate(true);
2914 genericObjectPool.addObject();
2915 assertEquals(1, simpleFactory.validateCounter);
2916 }
2917
2918
2919
2920
2921 @Test
2922 public void testValidateOnCreateFailure() throws Exception {
2923 genericObjectPool.setTestOnCreate(true);
2924 genericObjectPool.setTestOnBorrow(false);
2925 genericObjectPool.setMaxTotal(2);
2926 simpleFactory.setValid(false);
2927
2928 genericObjectPool.addObject();
2929 genericObjectPool.addObject();
2930 assertEquals(0, genericObjectPool.getNumIdle());
2931 assertEquals(0, genericObjectPool.getNumActive());
2932 simpleFactory.setValid(true);
2933 final String obj = genericObjectPool.borrowObject();
2934 assertNotNull(obj);
2935 genericObjectPool.addObject();
2936
2937 assertEquals(1, genericObjectPool.getNumIdle());
2938 assertEquals(1, genericObjectPool.getNumActive());
2939 }
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949 @Test
2950 public void testValidationFailureOnReturnFreesCapacity() throws Exception {
2951 final SimpleFactory factory = new SimpleFactory();
2952 factory.setValid(false);
2953 factory.setValidationEnabled(true);
2954 try (final GenericObjectPool<String> pool = new GenericObjectPool<>(factory)) {
2955 pool.setMaxTotal(2);
2956 pool.setMaxWaitMillis(1500);
2957 pool.setTestOnReturn(true);
2958 pool.setTestOnBorrow(false);
2959
2960 final WaitingTestThread thread1 = new WaitingTestThread(pool, 5000);
2961 thread1.start();
2962
2963 final WaitingTestThread thread2 = new WaitingTestThread(pool, 500);
2964 thread2.start();
2965 Thread.sleep(50);
2966
2967 final String obj = pool.borrowObject();
2968 pool.returnObject(obj);
2969 }
2970 }
2971
2972
2973 @Test
2974 public void testValidationOnCreateOnly() throws Exception {
2975 genericObjectPool.setMaxTotal(1);
2976 genericObjectPool.setTestOnCreate(true);
2977 genericObjectPool.setTestOnBorrow(false);
2978 genericObjectPool.setTestOnReturn(false);
2979 genericObjectPool.setTestWhileIdle(false);
2980
2981 final String o1 = genericObjectPool.borrowObject();
2982 assertEquals("0", o1);
2983 final Timer t = new Timer();
2984 t.schedule(
2985 new TimerTask() {
2986 @Override
2987 public void run() {
2988 genericObjectPool.returnObject(o1);
2989 }
2990 }, 3000);
2991
2992 final String o2 = genericObjectPool.borrowObject();
2993 assertEquals("0", o2);
2994
2995 assertEquals(1, simpleFactory.validateCounter);
2996 }
2997
2998 @Test
2999 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3000 public void testWhenExhaustedBlock() throws Exception {
3001 genericObjectPool.setMaxTotal(1);
3002 genericObjectPool.setBlockWhenExhausted(true);
3003 genericObjectPool.setMaxWaitMillis(10L);
3004 final String obj1 = genericObjectPool.borrowObject();
3005 assertNotNull(obj1);
3006 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
3007 genericObjectPool.returnObject(obj1);
3008 genericObjectPool.close();
3009 }
3010
3011
3012
3013
3014
3015
3016 @Test
3017 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3018 public void testWhenExhaustedBlockClosePool() throws Exception {
3019 genericObjectPool.setMaxTotal(1);
3020 genericObjectPool.setBlockWhenExhausted(true);
3021 genericObjectPool.setMaxWaitMillis(-1);
3022 final Object obj1 = genericObjectPool.borrowObject();
3023
3024
3025 assertNotNull(obj1);
3026
3027
3028 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200);
3029 wtt.start();
3030
3031 Thread.sleep(200);
3032
3033
3034 genericObjectPool.close();
3035
3036
3037 Thread.sleep(200);
3038
3039
3040 assertTrue(wtt.thrown instanceof InterruptedException);
3041 }
3042
3043 @Test
3044 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3045 public void testWhenExhaustedBlockInterrupt() throws Exception {
3046 genericObjectPool.setMaxTotal(1);
3047 genericObjectPool.setBlockWhenExhausted(true);
3048 genericObjectPool.setMaxWaitMillis(-1);
3049 final String obj1 = genericObjectPool.borrowObject();
3050
3051
3052 assertNotNull(obj1);
3053
3054
3055 final WaitingTestThread wtt = new WaitingTestThread(genericObjectPool, 200000);
3056 wtt.start();
3057
3058 Thread.sleep(200);
3059 wtt.interrupt();
3060
3061
3062 Thread.sleep(200);
3063
3064
3065 assertTrue(wtt.thrown instanceof InterruptedException);
3066
3067
3068 genericObjectPool.returnObject(obj1);
3069
3070
3071 genericObjectPool.setMaxWaitMillis(10L);
3072 String obj2 = null;
3073 try {
3074 obj2 = genericObjectPool.borrowObject();
3075 assertNotNull(obj2);
3076 } catch (final NoSuchElementException e) {
3077
3078 fail("NoSuchElementException not expected");
3079 }
3080 genericObjectPool.returnObject(obj2);
3081 genericObjectPool.close();
3082
3083 }
3084
3085 @Test
3086 @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS)
3087 public void testWhenExhaustedFail() throws Exception {
3088 genericObjectPool.setMaxTotal(1);
3089 genericObjectPool.setBlockWhenExhausted(false);
3090 final String obj1 = genericObjectPool.borrowObject();
3091 assertNotNull(obj1);
3092 assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject());
3093 genericObjectPool.returnObject(obj1);
3094 assertEquals(1, genericObjectPool.getNumIdle());
3095 genericObjectPool.close();
3096 }
3097
3098 }