1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.pool.impl;
19
20 import junit.framework.Test;
21 import junit.framework.TestSuite;
22 import org.apache.commons.pool.BasePoolableObjectFactory;
23 import org.apache.commons.pool.ObjectPool;
24 import org.apache.commons.pool.PoolableObjectFactory;
25 import org.apache.commons.pool.PoolUtils;
26 import org.apache.commons.pool.TestBaseObjectPool;
27 import org.apache.commons.pool.VisitTracker;
28 import org.apache.commons.pool.VisitTrackerFactory;
29
30 import java.util.NoSuchElementException;
31 import java.util.Random;
32
33 /***
34 * @author Rodney Waldhoff
35 * @author Dirk Verbeeck
36 * @author Sandy McArthur
37 * @version $Revision: 609415 $ $Date: 2008-01-06 14:45:32 -0700 (Sun, 06 Jan 2008) $
38 */
39 public class TestGenericObjectPool extends TestBaseObjectPool {
40 public TestGenericObjectPool(String testName) {
41 super(testName);
42 }
43
44 public static Test suite() {
45 return new TestSuite(TestGenericObjectPool.class);
46 }
47
48 protected ObjectPool makeEmptyPool(int mincap) {
49 GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
50 pool.setMaxActive(mincap);
51 pool.setMaxIdle(mincap);
52 return pool;
53 }
54
55 protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) {
56 return new GenericObjectPool(factory);
57 }
58
59 protected Object getNthObject(int n) {
60 return String.valueOf(n);
61 }
62
63 public void setUp() throws Exception {
64 super.setUp();
65 pool = new GenericObjectPool(new SimpleFactory());
66 }
67
68 public void tearDown() throws Exception {
69 super.tearDown();
70 pool.close();
71 pool = null;
72 }
73
74 public void testWhenExhaustedGrow() throws Exception {
75 pool.setMaxActive(1);
76 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
77 Object obj1 = pool.borrowObject();
78 assertNotNull(obj1);
79 Object obj2 = pool.borrowObject();
80 assertNotNull(obj2);
81 pool.returnObject(obj2);
82 pool.returnObject(obj1);
83 pool.close();
84 }
85
86 public void testWhenExhaustedFail() throws Exception {
87 pool.setMaxActive(1);
88 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
89 Object obj1 = pool.borrowObject();
90 assertNotNull(obj1);
91 try {
92 pool.borrowObject();
93 fail("Expected NoSuchElementException");
94 } catch(NoSuchElementException e) {
95
96 }
97 pool.returnObject(obj1);
98 pool.close();
99 }
100
101 public void testWhenExhaustedBlock() throws Exception {
102 pool.setMaxActive(1);
103 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
104 pool.setMaxWait(10L);
105 Object obj1 = pool.borrowObject();
106 assertNotNull(obj1);
107 try {
108 pool.borrowObject();
109 fail("Expected NoSuchElementException");
110 } catch(NoSuchElementException e) {
111
112 }
113 pool.returnObject(obj1);
114 pool.close();
115 }
116
117 public void testEvictWhileEmpty() throws Exception {
118 pool.evict();
119 pool.evict();
120 pool.close();
121 }
122
123 /***
124 * Tests addObject contention between ensureMinIdle triggered by
125 * the Evictor with minIdle > 0 and borrowObject.
126 */
127 public void testEvictAddObjects() throws Exception {
128 SimpleFactory factory = new SimpleFactory();
129 factory.setMakeLatency(300);
130 factory.setMaxActive(2);
131 GenericObjectPool pool = new GenericObjectPool(factory);
132 pool.setMaxActive(2);
133 pool.setMinIdle(1);
134 Object obj = pool.borrowObject();
135
136
137 TestThread borrower = new TestThread(pool, 1, 150, false);
138 Thread borrowerThread = new Thread(borrower);
139
140 pool.setTimeBetweenEvictionRunsMillis(100);
141 borrowerThread.start();
142 borrowerThread.join();
143 assertTrue(!borrower.failed());
144 pool.close();
145 }
146
147 public void testEvictLIFO() throws Exception {
148 checkEvict(true);
149 }
150
151 public void testEvictFIFO() throws Exception {
152 checkEvict(false);
153 }
154
155 public void checkEvict(boolean lifo) throws Exception {
156
157 final SimpleFactory factory = new SimpleFactory();
158 final GenericObjectPool pool = new GenericObjectPool(factory);
159 pool.setSoftMinEvictableIdleTimeMillis(10);
160 pool.setMinIdle(2);
161 pool.setTestWhileIdle(true);
162 pool.setLifo(lifo);
163 PoolUtils.prefill(pool, 5);
164 pool.evict();
165 factory.setEvenValid(false);
166 factory.setOddValid(false);
167 factory.setThrowExceptionOnActivate(true);
168 pool.evict();
169 PoolUtils.prefill(pool, 5);
170 factory.setThrowExceptionOnActivate(false);
171 factory.setThrowExceptionOnPassivate(true);
172 pool.evict();
173 factory.setThrowExceptionOnPassivate(false);
174 factory.setEvenValid(true);
175 factory.setOddValid(true);
176 Thread.sleep(125);
177 pool.evict();
178 assertEquals(2, pool.getNumIdle());
179 }
180
181 /***
182 * Test to make sure evictor visits least recently used objects first,
183 * regardless of FIFO/LIFO
184 *
185 * JIRA: POOL-86
186 */
187 public void testEvictionOrder() throws Exception {
188 checkEvictionOrder(false);
189 checkEvictionOrder(true);
190 }
191
192 private void checkEvictionOrder(boolean lifo) throws Exception {
193 SimpleFactory factory = new SimpleFactory();
194 GenericObjectPool pool = new GenericObjectPool(factory);
195 pool.setNumTestsPerEvictionRun(2);
196 pool.setMinEvictableIdleTimeMillis(100);
197 pool.setLifo(lifo);
198 for (int i = 0; i < 5; i++) {
199 pool.addObject();
200 Thread.sleep(100);
201 }
202
203 pool.evict();
204 Object obj = pool.borrowObject();
205 assertTrue("oldest not evicted", !obj.equals("0"));
206 assertTrue("second oldest not evicted", !obj.equals("1"));
207
208 assertEquals("Wrong instance returned", lifo ? "4" : "2" , obj);
209
210
211 factory = new SimpleFactory();
212 pool = new GenericObjectPool(factory);
213 pool.setNumTestsPerEvictionRun(2);
214 pool.setMinEvictableIdleTimeMillis(100);
215 pool.setLifo(lifo);
216 for (int i = 0; i < 5; i++) {
217 pool.addObject();
218 Thread.sleep(100);
219 }
220 pool.evict();
221 pool.evict();
222 obj = pool.borrowObject();
223 assertEquals("Wrong instance remaining in pool", "4", obj);
224 }
225
226 /***
227 * Verifies that the evictor visits objects in expected order
228 * and frequency.
229 */
230 public void testEvictorVisiting() throws Exception {
231 checkEvictorVisiting(true);
232 checkEvictorVisiting(false);
233 }
234
235 private void checkEvictorVisiting(boolean lifo) throws Exception {
236 VisitTrackerFactory factory = new VisitTrackerFactory();
237 GenericObjectPool pool = new GenericObjectPool(factory);
238 pool.setNumTestsPerEvictionRun(2);
239 pool.setMinEvictableIdleTimeMillis(-1);
240 pool.setTestWhileIdle(true);
241 pool.setLifo(lifo);
242 pool.setTestOnReturn(false);
243 pool.setTestOnBorrow(false);
244 for (int i = 0; i < 8; i++) {
245 pool.addObject();
246 }
247 pool.evict();
248 Object obj = pool.borrowObject();
249 pool.returnObject(obj);
250 obj = pool.borrowObject();
251 pool.returnObject(obj);
252
253
254
255 pool.evict();
256 for (int i = 0; i < 8; i++) {
257 VisitTracker tracker = (VisitTracker) pool.borrowObject();
258 if (tracker.getId() >= 4) {
259 assertEquals("Unexpected instance visited " + tracker.getId(),
260 0, tracker.getValidateCount());
261 } else {
262 assertEquals("Instance " + tracker.getId() +
263 " visited wrong number of times.",
264 1, tracker.getValidateCount());
265 }
266 }
267
268 factory = new VisitTrackerFactory();
269 pool = new GenericObjectPool(factory);
270 pool.setNumTestsPerEvictionRun(3);
271 pool.setMinEvictableIdleTimeMillis(-1);
272 pool.setTestWhileIdle(true);
273 pool.setLifo(lifo);
274 pool.setTestOnReturn(false);
275 pool.setTestOnBorrow(false);
276 for (int i = 0; i < 8; i++) {
277 pool.addObject();
278 }
279 pool.evict();
280 pool.evict();
281 obj = pool.borrowObject();
282 pool.returnObject(obj);
283 obj = pool.borrowObject();
284 pool.returnObject(obj);
285 obj = pool.borrowObject();
286 pool.returnObject(obj);
287
288
289
290
291 pool.evict();
292
293 for (int i = 0; i < 8; i++) {
294 VisitTracker tracker = (VisitTracker) pool.borrowObject();
295 if (tracker.getId() != 0) {
296 assertEquals("Instance " + tracker.getId() +
297 " visited wrong number of times.",
298 1, tracker.getValidateCount());
299 } else {
300 assertEquals("Instance " + tracker.getId() +
301 " visited wrong number of times.",
302 2, tracker.getValidateCount());
303 }
304 }
305
306
307 int[] smallPrimes = {2, 3, 5, 7};
308 Random random = new Random();
309 random.setSeed(System.currentTimeMillis());
310 pool.setMaxIdle(-1);
311 for (int i = 0; i < 4; i++) {
312 pool.setNumTestsPerEvictionRun(smallPrimes[i]);
313 for (int j = 0; j < 5; j++) {
314 pool.clear();
315 int instanceCount = 10 + random.nextInt(20);
316 for (int k = 0; k < instanceCount; k++) {
317 pool.addObject();
318 }
319
320
321 int runs = 10 + random.nextInt(50);
322 for (int k = 0; k < runs; k++) {
323 pool.evict();
324 }
325
326
327 int cycleCount = (runs * pool.getNumTestsPerEvictionRun())
328 / instanceCount;
329
330
331
332 VisitTracker tracker = null;
333 int visitCount = 0;
334 for (int k = 0; k < instanceCount; k++) {
335 tracker = (VisitTracker) pool.borrowObject();
336 visitCount = tracker.getValidateCount();
337 assertTrue(visitCount >= cycleCount &&
338 visitCount <= cycleCount + 1);
339 }
340 }
341 }
342 }
343
344 public void testExceptionOnPassivateDuringReturn() throws Exception {
345 SimpleFactory factory = new SimpleFactory();
346 GenericObjectPool pool = new GenericObjectPool(factory);
347 Object obj = pool.borrowObject();
348 factory.setThrowExceptionOnPassivate(true);
349 pool.returnObject(obj);
350 assertEquals(0,pool.getNumIdle());
351 pool.close();
352 }
353
354 public void testSetFactoryWithActiveObjects() throws Exception {
355 GenericObjectPool pool = new GenericObjectPool();
356 pool.setMaxIdle(10);
357 pool.setFactory(new SimpleFactory());
358 Object obj = pool.borrowObject();
359 assertNotNull(obj);
360 try {
361 pool.setFactory(null);
362 fail("Expected IllegalStateException");
363 } catch(IllegalStateException e) {
364
365 }
366 try {
367 pool.setFactory(new SimpleFactory());
368 fail("Expected IllegalStateException");
369 } catch(IllegalStateException e) {
370
371 }
372 }
373
374 public void testSetFactoryWithNoActiveObjects() throws Exception {
375 GenericObjectPool pool = new GenericObjectPool();
376 pool.setMaxIdle(10);
377 pool.setFactory(new SimpleFactory());
378 Object obj = pool.borrowObject();
379 pool.returnObject(obj);
380 assertEquals(1,pool.getNumIdle());
381 pool.setFactory(new SimpleFactory());
382 assertEquals(0,pool.getNumIdle());
383 }
384
385 public void testNegativeMaxActive() throws Exception {
386 pool.setMaxActive(-1);
387 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
388 Object obj = pool.borrowObject();
389 assertEquals(getNthObject(0),obj);
390 pool.returnObject(obj);
391 }
392
393 public void testMaxIdle() throws Exception {
394 pool.setMaxActive(100);
395 pool.setMaxIdle(8);
396 Object[] active = new Object[100];
397 for(int i=0;i<100;i++) {
398 active[i] = pool.borrowObject();
399 }
400 assertEquals(100,pool.getNumActive());
401 assertEquals(0,pool.getNumIdle());
402 for(int i=0;i<100;i++) {
403 pool.returnObject(active[i]);
404 assertEquals(99 - i,pool.getNumActive());
405 assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
406 }
407 }
408
409 public void testMaxIdleZero() throws Exception {
410 pool.setMaxActive(100);
411 pool.setMaxIdle(0);
412 Object[] active = new Object[100];
413 for(int i=0;i<100;i++) {
414 active[i] = pool.borrowObject();
415 }
416 assertEquals(100,pool.getNumActive());
417 assertEquals(0,pool.getNumIdle());
418 for(int i=0;i<100;i++) {
419 pool.returnObject(active[i]);
420 assertEquals(99 - i,pool.getNumActive());
421 assertEquals(0, pool.getNumIdle());
422 }
423 }
424
425 public void testMaxActive() throws Exception {
426 pool.setMaxActive(3);
427 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
428
429 pool.borrowObject();
430 pool.borrowObject();
431 pool.borrowObject();
432 try {
433 pool.borrowObject();
434 fail("Expected NoSuchElementException");
435 } catch(NoSuchElementException e) {
436
437 }
438 }
439
440 public void testMaxActiveZero() throws Exception {
441 pool.setMaxActive(0);
442 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
443
444 try {
445 pool.borrowObject();
446 fail("Expected NoSuchElementException");
447 } catch(NoSuchElementException e) {
448
449 }
450 }
451
452 public void testInvalidWhenExhaustedAction() throws Exception {
453 try {
454 pool.setWhenExhaustedAction(Byte.MAX_VALUE);
455 fail("Expected IllegalArgumentException");
456 } catch(IllegalArgumentException e) {
457
458 }
459
460 try {
461 ObjectPool pool = new GenericObjectPool(
462 new SimpleFactory(),
463 GenericObjectPool.DEFAULT_MAX_ACTIVE,
464 Byte.MAX_VALUE,
465 GenericObjectPool.DEFAULT_MAX_WAIT,
466 GenericObjectPool.DEFAULT_MAX_IDLE,
467 false,
468 false,
469 GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
470 GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
471 GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
472 false
473 );
474 assertNotNull(pool);
475 fail("Expected IllegalArgumentException");
476 } catch(IllegalArgumentException e) {
477
478 }
479 }
480
481 public void testSettersAndGetters() throws Exception {
482 GenericObjectPool pool = new GenericObjectPool();
483 {
484 pool.setFactory(new SimpleFactory());
485 }
486 {
487 pool.setMaxActive(123);
488 assertEquals(123,pool.getMaxActive());
489 }
490 {
491 pool.setMaxIdle(12);
492 assertEquals(12,pool.getMaxIdle());
493 }
494 {
495 pool.setMaxWait(1234L);
496 assertEquals(1234L,pool.getMaxWait());
497 }
498 {
499 pool.setMinEvictableIdleTimeMillis(12345L);
500 assertEquals(12345L,pool.getMinEvictableIdleTimeMillis());
501 }
502 {
503 pool.setNumTestsPerEvictionRun(11);
504 assertEquals(11,pool.getNumTestsPerEvictionRun());
505 }
506 {
507 pool.setTestOnBorrow(true);
508 assertTrue(pool.getTestOnBorrow());
509 pool.setTestOnBorrow(false);
510 assertTrue(!pool.getTestOnBorrow());
511 }
512 {
513 pool.setTestOnReturn(true);
514 assertTrue(pool.getTestOnReturn());
515 pool.setTestOnReturn(false);
516 assertTrue(!pool.getTestOnReturn());
517 }
518 {
519 pool.setTestWhileIdle(true);
520 assertTrue(pool.getTestWhileIdle());
521 pool.setTestWhileIdle(false);
522 assertTrue(!pool.getTestWhileIdle());
523 }
524 {
525 pool.setTimeBetweenEvictionRunsMillis(11235L);
526 assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis());
527 }
528 {
529 pool.setSoftMinEvictableIdleTimeMillis(12135L);
530 assertEquals(12135L,pool.getSoftMinEvictableIdleTimeMillis());
531 }
532 {
533 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
534 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction());
535 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
536 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction());
537 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
538 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction());
539 }
540 }
541
542 public void testDefaultConfiguration() throws Exception {
543 GenericObjectPool pool = new GenericObjectPool();
544 assertConfiguration(new GenericObjectPool.Config(),pool);
545 }
546
547 public void testConstructors() throws Exception {
548 {
549 GenericObjectPool pool = new GenericObjectPool();
550 assertConfiguration(new GenericObjectPool.Config(),pool);
551 }
552 {
553 GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
554 assertConfiguration(new GenericObjectPool.Config(),pool);
555 }
556 {
557 GenericObjectPool.Config expected = new GenericObjectPool.Config();
558 expected.maxActive = 2;
559 expected.maxIdle = 3;
560 expected.maxWait = 5L;
561 expected.minEvictableIdleTimeMillis = 7L;
562 expected.numTestsPerEvictionRun = 9;
563 expected.testOnBorrow = true;
564 expected.testOnReturn = true;
565 expected.testWhileIdle = true;
566 expected.timeBetweenEvictionRunsMillis = 11L;
567 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
568 GenericObjectPool pool = new GenericObjectPool(null,expected);
569 assertConfiguration(expected,pool);
570 }
571 {
572 GenericObjectPool.Config expected = new GenericObjectPool.Config();
573 expected.maxActive = 2;
574 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive);
575 assertConfiguration(expected,pool);
576 }
577 {
578 GenericObjectPool.Config expected = new GenericObjectPool.Config();
579 expected.maxActive = 2;
580 expected.maxWait = 5L;
581 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
582 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait);
583 assertConfiguration(expected,pool);
584 }
585 {
586 GenericObjectPool.Config expected = new GenericObjectPool.Config();
587 expected.maxActive = 2;
588 expected.maxWait = 5L;
589 expected.testOnBorrow = true;
590 expected.testOnReturn = true;
591 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
592 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.testOnBorrow,expected.testOnReturn);
593 assertConfiguration(expected,pool);
594 }
595 {
596 GenericObjectPool.Config expected = new GenericObjectPool.Config();
597 expected.maxActive = 2;
598 expected.maxIdle = 3;
599 expected.maxWait = 5L;
600 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
601 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle);
602 assertConfiguration(expected,pool);
603 }
604 {
605 GenericObjectPool.Config expected = new GenericObjectPool.Config();
606 expected.maxActive = 2;
607 expected.maxIdle = 3;
608 expected.maxWait = 5L;
609 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
610 expected.testOnBorrow = true;
611 expected.testOnReturn = true;
612 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle,expected.testOnBorrow,expected.testOnReturn);
613 assertConfiguration(expected,pool);
614 }
615 {
616 GenericObjectPool.Config expected = new GenericObjectPool.Config();
617 expected.maxActive = 2;
618 expected.maxIdle = 3;
619 expected.maxWait = 5L;
620 expected.minEvictableIdleTimeMillis = 7L;
621 expected.numTestsPerEvictionRun = 9;
622 expected.testOnBorrow = true;
623 expected.testOnReturn = true;
624 expected.testWhileIdle = true;
625 expected.timeBetweenEvictionRunsMillis = 11L;
626 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
627 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle);
628 assertConfiguration(expected,pool);
629 }
630 {
631 GenericObjectPool.Config expected = new GenericObjectPool.Config();
632 expected.maxActive = 2;
633 expected.maxIdle = 3;
634 expected.minIdle = 1;
635 expected.maxWait = 5L;
636 expected.minEvictableIdleTimeMillis = 7L;
637 expected.numTestsPerEvictionRun = 9;
638 expected.testOnBorrow = true;
639 expected.testOnReturn = true;
640 expected.testWhileIdle = true;
641 expected.timeBetweenEvictionRunsMillis = 11L;
642 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
643 GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.minIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle);
644 assertConfiguration(expected,pool);
645 }
646 }
647
648 public void testSetConfig() throws Exception {
649 GenericObjectPool.Config expected = new GenericObjectPool.Config();
650 GenericObjectPool pool = new GenericObjectPool();
651 assertConfiguration(expected,pool);
652 expected.maxActive = 2;
653 expected.maxIdle = 3;
654 expected.maxWait = 5L;
655 expected.minEvictableIdleTimeMillis = 7L;
656 expected.numTestsPerEvictionRun = 9;
657 expected.testOnBorrow = true;
658 expected.testOnReturn = true;
659 expected.testWhileIdle = true;
660 expected.timeBetweenEvictionRunsMillis = 11L;
661 expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
662 pool.setConfig(expected);
663 assertConfiguration(expected,pool);
664 }
665
666 public void testDebugInfo() throws Exception {
667 GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
668 pool.setMaxIdle(3);
669 assertNotNull(pool.debugInfo());
670 Object obj = pool.borrowObject();
671 assertNotNull(pool.debugInfo());
672 pool.returnObject(obj);
673 assertNotNull(pool.debugInfo());
674 }
675
676 public void testStartAndStopEvictor() throws Exception {
677
678 pool.setMaxIdle(6);
679 pool.setMaxActive(6);
680 pool.setNumTestsPerEvictionRun(6);
681 pool.setMinEvictableIdleTimeMillis(100L);
682
683 for(int j=0;j<2;j++) {
684
685 {
686 Object[] active = new Object[6];
687 for(int i=0;i<6;i++) {
688 active[i] = pool.borrowObject();
689 }
690 for(int i=0;i<6;i++) {
691 pool.returnObject(active[i]);
692 }
693 }
694
695
696 assertEquals("Should have 6 idle",6,pool.getNumIdle());
697
698
699 pool.setTimeBetweenEvictionRunsMillis(50L);
700
701
702 try { Thread.sleep(200L); } catch(Exception e) { }
703
704
705 assertEquals("Should have 0 idle",0,pool.getNumIdle());
706
707
708 pool.startEvictor(0L);
709 }
710 }
711
712 public void testEvictionWithNegativeNumTests() throws Exception {
713
714 pool.setMaxIdle(6);
715 pool.setMaxActive(6);
716 pool.setNumTestsPerEvictionRun(-2);
717 pool.setMinEvictableIdleTimeMillis(50L);
718 pool.setTimeBetweenEvictionRunsMillis(100L);
719
720 Object[] active = new Object[6];
721 for(int i=0;i<6;i++) {
722 active[i] = pool.borrowObject();
723 }
724 for(int i=0;i<6;i++) {
725 pool.returnObject(active[i]);
726 }
727
728 try { Thread.sleep(100L); } catch(Exception e) { }
729 assertTrue("Should at most 6 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 6);
730 try { Thread.sleep(100L); } catch(Exception e) { }
731 assertTrue("Should at most 3 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 3);
732 try { Thread.sleep(100L); } catch(Exception e) { }
733 assertTrue("Should be at most 2 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 2);
734 try { Thread.sleep(100L); } catch(Exception e) { }
735 assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
736 }
737
738 public void testEviction() throws Exception {
739 pool.setMaxIdle(500);
740 pool.setMaxActive(500);
741 pool.setNumTestsPerEvictionRun(100);
742 pool.setMinEvictableIdleTimeMillis(250L);
743 pool.setTimeBetweenEvictionRunsMillis(500L);
744 pool.setTestWhileIdle(true);
745
746 Object[] active = new Object[500];
747 for(int i=0;i<500;i++) {
748 active[i] = pool.borrowObject();
749 }
750 for(int i=0;i<500;i++) {
751 pool.returnObject(active[i]);
752 }
753
754 try { Thread.sleep(1000L); } catch(Exception e) { }
755 assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
756 try { Thread.sleep(600L); } catch(Exception e) { }
757 assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
758 try { Thread.sleep(600L); } catch(Exception e) { }
759 assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
760 try { Thread.sleep(600L); } catch(Exception e) { }
761 assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
762 try { Thread.sleep(600L); } catch(Exception e) { }
763 assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
764 try { Thread.sleep(600L); } catch(Exception e) { }
765 assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
766
767 for(int i=0;i<500;i++) {
768 active[i] = pool.borrowObject();
769 }
770 for(int i=0;i<500;i++) {
771 pool.returnObject(active[i]);
772 }
773
774 try { Thread.sleep(1000L); } catch(Exception e) { }
775 assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
776 try { Thread.sleep(600L); } catch(Exception e) { }
777 assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
778 try { Thread.sleep(600L); } catch(Exception e) { }
779 assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
780 try { Thread.sleep(600L); } catch(Exception e) { }
781 assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
782 try { Thread.sleep(600L); } catch(Exception e) { }
783 assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
784 try { Thread.sleep(600L); } catch(Exception e) { }
785 assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
786 }
787
788 /***
789 * This test has a number of problems.
790 * 1. without the wait code in the for loop the create time for each instance
791 * was usually the same due to clock presision.
792 * 2. It's very hard to follow.
793 */
794 public void DISABLEDtestEvictionSoftMinIdle() throws Exception {
795 GenericObjectPool pool = null;
796
797 class TimeTest extends BasePoolableObjectFactory {
798 private final long createTime;
799 public TimeTest() {
800 createTime = System.currentTimeMillis();
801 }
802 public Object makeObject() throws Exception {
803 return new TimeTest();
804 }
805 public long getCreateTime() {
806 return createTime;
807 }
808 }
809
810 pool = new GenericObjectPool(new TimeTest());
811
812 pool.setMaxIdle(5);
813 pool.setMaxActive(5);
814 pool.setNumTestsPerEvictionRun(5);
815 pool.setMinEvictableIdleTimeMillis(3000L);
816 pool.setTimeBetweenEvictionRunsMillis(250L);
817 pool.setTestWhileIdle(true);
818 pool.setSoftMinEvictableIdleTimeMillis(1000L);
819 pool.setMinIdle(2);
820
821 Object[] active = new Object[5];
822 Long[] creationTime = new Long[5] ;
823 long lastCreationTime = System.currentTimeMillis();
824 for(int i=0;i<5;i++) {
825
826 while (lastCreationTime == System.currentTimeMillis()) {
827 Thread.sleep(1);
828 }
829 active[i] = pool.borrowObject();
830 creationTime[i] = new Long(((TimeTest)active[i]).getCreateTime());
831 lastCreationTime = creationTime[i].longValue();
832 }
833
834 for(int i=0;i<5;i++) {
835 pool.returnObject(active[i]);
836 }
837
838 try { Thread.sleep(1500L); } catch(Exception e) { }
839 assertTrue("Should be 2 OLD idle, found " + pool.getNumIdle(),pool.getNumIdle() == 2 &&
840 ((TimeTest)pool.borrowObject()).getCreateTime() == creationTime[3].longValue() &&
841 ((TimeTest)pool.borrowObject()).getCreateTime() == creationTime[4].longValue());
842
843 try { Thread.sleep(2000L); } catch(Exception e) { }
844 assertTrue("Should be 2 NEW idle , found " + pool.getNumIdle(),pool.getNumIdle() == 2 &&
845 ((TimeTest)pool.borrowObject()).getCreateTime() != creationTime[0].longValue() &&
846 ((TimeTest)pool.borrowObject()).getCreateTime() != creationTime[1].longValue());
847 }
848
849 public void testMinIdle() throws Exception {
850 pool.setMaxIdle(500);
851 pool.setMinIdle(5);
852 pool.setMaxActive(10);
853 pool.setNumTestsPerEvictionRun(0);
854 pool.setMinEvictableIdleTimeMillis(50L);
855 pool.setTimeBetweenEvictionRunsMillis(100L);
856 pool.setTestWhileIdle(true);
857
858 try { Thread.sleep(150L); } catch(Exception e) { }
859 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
860
861 Object[] active = new Object[5];
862 active[0] = pool.borrowObject();
863
864 try { Thread.sleep(150L); } catch(Exception e) { }
865 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
866
867 for(int i=1 ; i<5 ; i++) {
868 active[i] = pool.borrowObject();
869 }
870
871 try { Thread.sleep(150L); } catch(Exception e) { }
872 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
873
874 for(int i=0 ; i<5 ; i++) {
875 pool.returnObject(active[i]);
876 }
877
878 try { Thread.sleep(150L); } catch(Exception e) { }
879 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
880 }
881
882 public void testMinIdleMaxActive() throws Exception {
883 pool.setMaxIdle(500);
884 pool.setMinIdle(5);
885 pool.setMaxActive(10);
886 pool.setNumTestsPerEvictionRun(0);
887 pool.setMinEvictableIdleTimeMillis(50L);
888 pool.setTimeBetweenEvictionRunsMillis(100L);
889 pool.setTestWhileIdle(true);
890
891 try { Thread.sleep(150L); } catch(Exception e) { }
892 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
893
894 Object[] active = new Object[10];
895
896 try { Thread.sleep(150L); } catch(Exception e) { }
897 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
898
899 for(int i=0 ; i<5 ; i++) {
900 active[i] = pool.borrowObject();
901 }
902
903 try { Thread.sleep(150L); } catch(Exception e) { }
904 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
905
906 for(int i=0 ; i<5 ; i++) {
907 pool.returnObject(active[i]);
908 }
909
910 try { Thread.sleep(150L); } catch(Exception e) { }
911 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
912
913 for(int i=0 ; i<10 ; i++) {
914 active[i] = pool.borrowObject();
915 }
916
917 try { Thread.sleep(150L); } catch(Exception e) { }
918 assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
919
920 for(int i=0 ; i<10 ; i++) {
921 pool.returnObject(active[i]);
922 }
923
924 try { Thread.sleep(150L); } catch(Exception e) { }
925 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
926 }
927
928 /***
929 * Kicks off <numThreads> test threads, each of which will go through
930 * <iterations> borrow-return cycles with random delay times <= delay
931 * in between.
932 */
933 public void runTestThreads(int numThreads, int iterations, int delay) {
934 TestThread[] threads = new TestThread[numThreads];
935 for(int i=0;i<numThreads;i++) {
936 threads[i] = new TestThread(pool,iterations,delay);
937 Thread t = new Thread(threads[i]);
938 t.start();
939 }
940 for(int i=0;i<numThreads;i++) {
941 while(!(threads[i]).complete()) {
942 try {
943 Thread.sleep(500L);
944 } catch(Exception e) {
945
946 }
947 }
948 if(threads[i].failed()) {
949 fail();
950 }
951 }
952 }
953
954 public void testThreaded1() throws Exception {
955 pool.setMaxActive(15);
956 pool.setMaxIdle(15);
957 pool.setMaxWait(1000L);
958 runTestThreads(20, 100, 50);
959 }
960
961 /***
962 * Verifies that maxActive is not exceeded when factory destroyObject
963 * has high latency, testOnReturn is set and there is high incidence of
964 * validation failures.
965 */
966 public void testMaxActiveInvariant() throws Exception {
967 int maxActive = 15;
968 SimpleFactory factory = new SimpleFactory();
969 factory.setEvenValid(false);
970 factory.setDestroyLatency(100);
971 factory.setMaxActive(maxActive);
972 factory.setValidationEnabled(true);
973 pool = new GenericObjectPool(factory);
974 pool.setMaxActive(maxActive);
975 pool.setMaxIdle(-1);
976 pool.setTestOnReturn(true);
977 pool.setMaxWait(1000L);
978 runTestThreads(5, 10, 50);
979 }
980
981 class TestThread implements Runnable {
982 java.util.Random _random = new java.util.Random();
983 ObjectPool _pool = null;
984 boolean _complete = false;
985 boolean _failed = false;
986 int _iter = 100;
987 int _delay = 50;
988 boolean _randomDelay = true;
989
990 public TestThread(ObjectPool pool) {
991 _pool = pool;
992 }
993
994 public TestThread(ObjectPool pool, int iter) {
995 _pool = pool;
996 _iter = iter;
997 }
998
999 public TestThread(ObjectPool pool, int iter, int delay) {
1000 _pool = pool;
1001 _iter = iter;
1002 _delay = delay;
1003 }
1004
1005 public TestThread(ObjectPool pool, int iter, int delay,
1006 boolean randomDelay) {
1007 _pool = pool;
1008 _iter = iter;
1009 _delay = delay;
1010 _randomDelay = randomDelay;
1011 }
1012
1013 public boolean complete() {
1014 return _complete;
1015 }
1016
1017 public boolean failed() {
1018 return _failed;
1019 }
1020
1021 public void run() {
1022 for(int i=0;i<_iter;i++) {
1023 long delay =
1024 _randomDelay ? (long)_random.nextInt(_delay) : _delay;
1025 try {
1026 Thread.sleep(delay);
1027 } catch(Exception e) {
1028
1029 }
1030 Object obj = null;
1031 try {
1032 obj = _pool.borrowObject();
1033 } catch(Exception e) {
1034 e.printStackTrace();
1035 _failed = true;
1036 _complete = true;
1037 break;
1038 }
1039
1040 try {
1041 Thread.sleep(delay);
1042 } catch(Exception e) {
1043
1044 }
1045 try {
1046 _pool.returnObject(obj);
1047 } catch(Exception e) {
1048 _failed = true;
1049 _complete = true;
1050 break;
1051 }
1052 }
1053 _complete = true;
1054 }
1055 }
1056
1057 public void testFIFO() throws Exception {
1058 pool.setLifo(false);
1059 pool.addObject();
1060 pool.addObject();
1061 pool.addObject();
1062 assertEquals("Oldest", "0", pool.borrowObject());
1063 assertEquals("Middle", "1", pool.borrowObject());
1064 assertEquals("Youngest", "2", pool.borrowObject());
1065 assertEquals("new-3", "3", pool.borrowObject());
1066 pool.returnObject("r");
1067 assertEquals("returned", "r", pool.borrowObject());
1068 assertEquals("new-4", "4", pool.borrowObject());
1069 }
1070
1071 public void testLIFO() throws Exception {
1072 pool.setLifo(true);
1073 pool.addObject();
1074 pool.addObject();
1075 pool.addObject();
1076 assertEquals("Youngest", "2", pool.borrowObject());
1077 assertEquals("Middle", "1", pool.borrowObject());
1078 assertEquals("Oldest", "0", pool.borrowObject());
1079 assertEquals("new-3", "3", pool.borrowObject());
1080 pool.returnObject("r");
1081 assertEquals("returned", "r", pool.borrowObject());
1082 assertEquals("new-4", "4", pool.borrowObject());
1083 }
1084
1085 public void testAddObject() throws Exception {
1086 assertEquals("should be zero idle", 0, pool.getNumIdle());
1087 pool.addObject();
1088 assertEquals("should be one idle", 1, pool.getNumIdle());
1089 assertEquals("should be zero active", 0, pool.getNumActive());
1090 Object obj = pool.borrowObject();
1091 assertEquals("should be zero idle", 0, pool.getNumIdle());
1092 assertEquals("should be one active", 1, pool.getNumActive());
1093 pool.returnObject(obj);
1094 assertEquals("should be one idle", 1, pool.getNumIdle());
1095 assertEquals("should be zero active", 0, pool.getNumActive());
1096
1097 ObjectPool op = new GenericObjectPool();
1098 try {
1099 op.addObject();
1100 fail("Expected IllegalStateException when there is no factory.");
1101 } catch (IllegalStateException ise) {
1102
1103 }
1104 op.close();
1105 }
1106
1107 protected GenericObjectPool pool = null;
1108
1109 private void assertConfiguration(GenericObjectPool.Config expected, GenericObjectPool actual) throws Exception {
1110 assertEquals("testOnBorrow",expected.testOnBorrow,actual.getTestOnBorrow());
1111 assertEquals("testOnReturn",expected.testOnReturn,actual.getTestOnReturn());
1112 assertEquals("testWhileIdle",expected.testWhileIdle,actual.getTestWhileIdle());
1113 assertEquals("whenExhaustedAction",expected.whenExhaustedAction,actual.getWhenExhaustedAction());
1114 assertEquals("maxActive",expected.maxActive,actual.getMaxActive());
1115 assertEquals("maxIdle",expected.maxIdle,actual.getMaxIdle());
1116 assertEquals("maxWait",expected.maxWait,actual.getMaxWait());
1117 assertEquals("minEvictableIdleTimeMillis",expected.minEvictableIdleTimeMillis,actual.getMinEvictableIdleTimeMillis());
1118 assertEquals("numTestsPerEvictionRun",expected.numTestsPerEvictionRun,actual.getNumTestsPerEvictionRun());
1119 assertEquals("timeBetweenEvictionRunsMillis",expected.timeBetweenEvictionRunsMillis,actual.getTimeBetweenEvictionRunsMillis());
1120 }
1121
1122 public class SimpleFactory implements PoolableObjectFactory {
1123 public SimpleFactory() {
1124 this(true);
1125 }
1126 public SimpleFactory(boolean valid) {
1127 this(valid,valid);
1128 }
1129 public SimpleFactory(boolean evalid, boolean ovalid) {
1130 evenValid = evalid;
1131 oddValid = ovalid;
1132 }
1133 void setValid(boolean valid) {
1134 setEvenValid(valid);
1135 setOddValid(valid);
1136 }
1137 void setEvenValid(boolean valid) {
1138 evenValid = valid;
1139 }
1140 void setOddValid(boolean valid) {
1141 oddValid = valid;
1142 }
1143 public void setThrowExceptionOnPassivate(boolean bool) {
1144 exceptionOnPassivate = bool;
1145 }
1146 public void setMaxActive(int maxActive) {
1147 this.maxActive = maxActive;
1148 }
1149 public void setDestroyLatency(long destroyLatency) {
1150 this.destroyLatency = destroyLatency;
1151 }
1152 public void setMakeLatency(long makeLatency) {
1153 this.makeLatency = makeLatency;
1154 }
1155 public Object makeObject() {
1156 synchronized(this) {
1157 activeCount++;
1158 if (activeCount > maxActive) {
1159 throw new IllegalStateException(
1160 "Too many active instances: " + activeCount);
1161 }
1162 }
1163 if (makeLatency > 0) {
1164 doWait(makeLatency);
1165 }
1166 return String.valueOf(makeCounter++);
1167 }
1168 public void destroyObject(Object obj) {
1169 if (destroyLatency > 0) {
1170 doWait(destroyLatency);
1171 }
1172 synchronized(this) {
1173 activeCount--;
1174 }
1175 }
1176 public boolean validateObject(Object obj) {
1177 if (enableValidation) {
1178 return validateCounter++%2 == 0 ? evenValid : oddValid;
1179 }
1180 else {
1181 return true;
1182 }
1183 }
1184 public void activateObject(Object obj) throws Exception {
1185 if (exceptionOnActivate) {
1186 if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) {
1187 throw new Exception();
1188 }
1189 }
1190 }
1191 public void passivateObject(Object obj) throws Exception {
1192 if(exceptionOnPassivate) {
1193 throw new Exception();
1194 }
1195 }
1196 int makeCounter = 0;
1197 int validateCounter = 0;
1198 int activeCount = 0;
1199 boolean evenValid = true;
1200 boolean oddValid = true;
1201 boolean exceptionOnPassivate = false;
1202 boolean exceptionOnActivate = false;
1203 boolean enableValidation = true;
1204 long destroyLatency = 0;
1205 long makeLatency = 0;
1206 int maxActive = Integer.MAX_VALUE;
1207
1208 public boolean isThrowExceptionOnActivate() {
1209 return exceptionOnActivate;
1210 }
1211
1212 public void setThrowExceptionOnActivate(boolean b) {
1213 exceptionOnActivate = b;
1214 }
1215
1216 public boolean isValidationEnabled() {
1217 return enableValidation;
1218 }
1219
1220 public void setValidationEnabled(boolean b) {
1221 enableValidation = b;
1222 }
1223
1224 private void doWait(long latency) {
1225 try {
1226 Thread.sleep(latency);
1227 } catch (InterruptedException ex) {
1228
1229 }
1230 }
1231 }
1232 protected boolean isLifo() {
1233 return true;
1234 }
1235
1236 protected boolean isFifo() {
1237 return false;
1238 }
1239 }
1240
1241