1   /*
2    * Copyright 1999-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.pool.impl;
18  
19  import java.util.NoSuchElementException;
20  import java.util.List;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  
24  import junit.framework.Test;
25  import junit.framework.TestSuite;
26  
27  import org.apache.commons.pool.BasePoolableObjectFactory;
28  import org.apache.commons.pool.ObjectPool;
29  import org.apache.commons.pool.PoolableObjectFactory;
30  import org.apache.commons.pool.TestObjectPool;
31  
32  /***
33   * @author Rodney Waldhoff
34   * @author Dirk Verbeeck
35   * @version $Revision: 387103 $ $Date: 2006-03-19 20:48:49 -0500 (Sun, 19 Mar 2006) $
36   */
37  public class TestGenericObjectPool extends TestObjectPool {
38      public TestGenericObjectPool(String testName) {
39          super(testName);
40      }
41  
42      public static Test suite() {
43          return new TestSuite(TestGenericObjectPool.class);
44      }
45  
46      protected ObjectPool makeEmptyPool(int mincap) {
47         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
48         pool.setMaxActive(mincap);
49         pool.setMaxIdle(mincap);
50         return pool;
51      }
52      
53      protected Object getNthObject(int n) {
54          return String.valueOf(n);
55      }
56  
57      public void setUp() throws Exception {
58          super.setUp();
59          pool = new GenericObjectPool(new SimpleFactory());
60      }
61  
62      public void tearDown() throws Exception {
63          super.tearDown();
64          pool.close();
65          pool = null;
66      }
67  
68      /***
69       * Activation failure on existing object doesn't fail the borrow 
70       */
71      public void testActivationException() throws Exception {
72          SimpleFactory factory = new SimpleFactory(true, false);
73          factory.setThrowExceptionOnActivate(true);
74          factory.setValidationEnabled(false);
75          GenericObjectPool pool = new GenericObjectPool(factory);
76          
77          Object obj1 = pool.borrowObject();
78          pool.returnObject(obj1);
79  
80          // obj1 was returned to the pool but failed to activate the second borrow
81          // a new object obj2 needs te be created
82          Object obj2 = pool.borrowObject();
83          assertTrue(obj1 != obj2);        
84      }
85  
86      /***
87       * Activation failure on new object fails the borrow 
88       */
89      public void testActivationExceptionOnNewObject() throws Exception {
90          SimpleFactory factory = new SimpleFactory(true, false);
91          factory.setThrowExceptionOnActivate(true);
92          factory.setValidationEnabled(false);
93          GenericObjectPool pool = new GenericObjectPool(factory);
94          
95          Object obj1 = pool.borrowObject();
96          try {
97              Object obj2 = pool.borrowObject();
98              System.out.println("obj1: " + obj1);
99              System.out.println("obj2: " + obj2);
100             fail("a second object should have been created and failed to activate");
101         }
102         catch (Exception e) {}
103     }
104 
105     public void testWhenExhaustedGrow() throws Exception {
106         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
107         pool.setMaxActive(1);
108         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
109         Object obj1 = pool.borrowObject();
110         assertNotNull(obj1);
111         Object obj2 = pool.borrowObject();
112         assertNotNull(obj2);
113         pool.returnObject(obj2);
114         pool.returnObject(obj1);
115         pool.close();
116     }
117 
118     public void testWhenExhaustedFail() throws Exception {
119         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
120         pool.setMaxActive(1);
121         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
122         Object obj1 = pool.borrowObject();
123         assertNotNull(obj1);
124         try {
125             pool.borrowObject();
126             fail("Expected NoSuchElementException");
127         } catch(NoSuchElementException e) {
128             // expected
129         }
130         pool.returnObject(obj1);
131         pool.close();
132     }
133 
134     public void testWhenExhaustedBlock() throws Exception {
135         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
136         pool.setMaxActive(1);
137         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
138         pool.setMaxWait(10L);
139         Object obj1 = pool.borrowObject();
140         assertNotNull(obj1);
141         try {
142             pool.borrowObject();
143             fail("Expected NoSuchElementException");
144         } catch(NoSuchElementException e) {
145             // expected
146         }
147         pool.returnObject(obj1);
148         pool.close();
149     }
150 
151     public void testEvictWhileEmpty() throws Exception {
152         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(true,false));
153         pool.evict();
154         pool.evict();
155         pool.close();
156     }
157 
158     public void testExceptionOnPassivateDuringReturn() throws Exception {
159         SimpleFactory factory = new SimpleFactory();        
160         GenericObjectPool pool = new GenericObjectPool(factory);
161         Object obj = pool.borrowObject();
162         factory.setThrowExceptionOnPassivate(true);
163         pool.returnObject(obj);
164         assertEquals(0,pool.getNumIdle());
165         pool.close();
166     }
167 
168     public void testWithInitiallyInvalid() throws Exception {
169         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(false));
170         pool.setTestOnBorrow(true);
171         try {
172             pool.borrowObject();
173             fail("Expected NoSuchElementException");
174         } catch(NoSuchElementException e) {
175             // expected 
176         }
177     }
178 
179     public void testWithSometimesInvalid() throws Exception {
180         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(true,false));
181         pool.setMaxIdle(10);
182         pool.setTestOnBorrow(true);
183         pool.setTestOnReturn(true);
184         pool.returnObject(pool.borrowObject());  
185         assertEquals(0,pool.getNumIdle());      
186     }
187 
188     public void testSetFactoryWithActiveObjects() throws Exception {
189         GenericObjectPool pool = new GenericObjectPool();
190         pool.setMaxIdle(10);
191         pool.setFactory(new SimpleFactory());
192         Object obj = pool.borrowObject();
193         assertNotNull(obj);
194         try {
195             pool.setFactory(null);
196             fail("Expected IllegalStateException");
197         } catch(IllegalStateException e) {
198             // expected
199         }
200         try {
201             pool.setFactory(new SimpleFactory());
202             fail("Expected IllegalStateException");
203         } catch(IllegalStateException e) {
204             // expected
205         }
206     }
207 
208     public void testSetFactoryWithNoActiveObjects() throws Exception {
209         GenericObjectPool pool = new GenericObjectPool();
210         pool.setMaxIdle(10);
211         pool.setFactory(new SimpleFactory());
212         Object obj = pool.borrowObject();
213         pool.returnObject(obj);
214         assertEquals(1,pool.getNumIdle());
215         pool.setFactory(new SimpleFactory());
216         assertEquals(0,pool.getNumIdle());
217     }
218     
219     public void testNegativeMaxActive() throws Exception {
220         pool.setMaxActive(-1);
221         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
222         Object obj = pool.borrowObject();
223         assertEquals(getNthObject(0),obj);
224         pool.returnObject(obj);
225     }
226 
227     public void testMaxIdle() throws Exception {
228         pool.setMaxActive(100);
229         pool.setMaxIdle(8);
230         Object[] active = new Object[100];
231         for(int i=0;i<100;i++) {
232             active[i] = pool.borrowObject();
233         }
234         assertEquals(100,pool.getNumActive());
235         assertEquals(0,pool.getNumIdle());
236         for(int i=0;i<100;i++) {
237             pool.returnObject(active[i]);
238             assertEquals(99 - i,pool.getNumActive());
239             assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
240         }
241     }
242 
243     public void testMaxIdleZero() throws Exception {
244         pool.setMaxActive(100);
245         pool.setMaxIdle(0);
246         Object[] active = new Object[100];
247         for(int i=0;i<100;i++) {
248             active[i] = pool.borrowObject();
249         }
250         assertEquals(100,pool.getNumActive());
251         assertEquals(0,pool.getNumIdle());
252         for(int i=0;i<100;i++) {
253             pool.returnObject(active[i]);
254             assertEquals(99 - i,pool.getNumActive());
255             assertEquals(0, pool.getNumIdle());
256         }
257     }
258 
259     public void testMaxActive() throws Exception {
260         pool.setMaxActive(3);
261         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
262 
263         pool.borrowObject();
264         pool.borrowObject();
265         pool.borrowObject();
266         try {
267             pool.borrowObject();
268             fail("Expected NoSuchElementException");
269         } catch(NoSuchElementException e) {
270             // expected
271         }
272     }
273 
274     public void testMaxActiveZero() throws Exception {
275         pool.setMaxActive(0);
276         pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
277 
278         try {
279             pool.borrowObject();
280             fail("Expected NoSuchElementException");
281         } catch(NoSuchElementException e) {
282             // expected
283         }
284     }
285 
286     public void testInvalidWhenExhaustedAction() throws Exception {
287         try {
288             pool.setWhenExhaustedAction(Byte.MAX_VALUE);
289             fail("Expected IllegalArgumentException");
290         } catch(IllegalArgumentException e) {
291             // expected
292         }
293 
294         try {
295             ObjectPool pool = new GenericObjectPool(
296                 new SimpleFactory(),
297                 GenericObjectPool.DEFAULT_MAX_ACTIVE, 
298                 Byte.MAX_VALUE,
299                 GenericObjectPool.DEFAULT_MAX_WAIT, 
300                 GenericObjectPool.DEFAULT_MAX_IDLE,
301                 false,
302                 false,
303                 GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
304                 GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
305                 GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
306                 false
307             );
308             assertNotNull(pool);
309             fail("Expected IllegalArgumentException");
310         } catch(IllegalArgumentException e) {
311             // expected
312         }
313     }
314 
315     public void testSettersAndGetters() throws Exception {
316         GenericObjectPool pool = new GenericObjectPool();
317         {
318             pool.setFactory(new SimpleFactory());
319         }
320         {
321             pool.setMaxActive(123);
322             assertEquals(123,pool.getMaxActive());
323         }
324         {
325             pool.setMaxIdle(12);
326             assertEquals(12,pool.getMaxIdle());
327         }
328         {
329             pool.setMaxWait(1234L);
330             assertEquals(1234L,pool.getMaxWait());
331         }
332         {
333             pool.setMinEvictableIdleTimeMillis(12345L);
334             assertEquals(12345L,pool.getMinEvictableIdleTimeMillis());
335         }
336         {
337             pool.setNumTestsPerEvictionRun(11);
338             assertEquals(11,pool.getNumTestsPerEvictionRun());
339         }
340         {
341             pool.setTestOnBorrow(true);
342             assertTrue(pool.getTestOnBorrow());
343             pool.setTestOnBorrow(false);
344             assertTrue(!pool.getTestOnBorrow());
345         }
346         {
347             pool.setTestOnReturn(true);
348             assertTrue(pool.getTestOnReturn());
349             pool.setTestOnReturn(false);
350             assertTrue(!pool.getTestOnReturn());
351         }
352         {
353             pool.setTestWhileIdle(true);
354             assertTrue(pool.getTestWhileIdle());
355             pool.setTestWhileIdle(false);
356             assertTrue(!pool.getTestWhileIdle());
357         }
358         {
359             pool.setTimeBetweenEvictionRunsMillis(11235L);
360             assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis());
361         }
362         {
363             pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
364             assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction());
365             pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
366             assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction());
367             pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
368             assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction());
369         }
370     }
371     
372     public void testDefaultConfiguration() throws Exception {
373         GenericObjectPool pool = new GenericObjectPool();
374         assertConfiguration(new GenericObjectPool.Config(),pool);
375     }
376 
377     public void testConstructors() throws Exception {
378         {
379             GenericObjectPool pool = new GenericObjectPool();
380             assertConfiguration(new GenericObjectPool.Config(),pool);
381         }
382         {
383             GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
384             assertConfiguration(new GenericObjectPool.Config(),pool);
385         }
386         {
387             GenericObjectPool.Config expected = new GenericObjectPool.Config();
388             expected.maxActive = 2;
389             expected.maxIdle = 3;
390             expected.maxWait = 5L;
391             expected.minEvictableIdleTimeMillis = 7L;
392             expected.numTestsPerEvictionRun = 9;
393             expected.testOnBorrow = true;
394             expected.testOnReturn = true;
395             expected.testWhileIdle = true;
396             expected.timeBetweenEvictionRunsMillis = 11L;
397             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
398             GenericObjectPool pool = new GenericObjectPool(null,expected);
399             assertConfiguration(expected,pool);
400         }
401         {
402             GenericObjectPool.Config expected = new GenericObjectPool.Config();
403             expected.maxActive = 2;
404             GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive);
405             assertConfiguration(expected,pool);
406         }
407         {
408             GenericObjectPool.Config expected = new GenericObjectPool.Config();
409             expected.maxActive = 2;
410             expected.maxWait = 5L;
411             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
412             GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait);
413             assertConfiguration(expected,pool);
414         }
415         {
416             GenericObjectPool.Config expected = new GenericObjectPool.Config();
417             expected.maxActive = 2;
418             expected.maxWait = 5L;
419             expected.testOnBorrow = true;
420             expected.testOnReturn = true;
421             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
422             GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.testOnBorrow,expected.testOnReturn);
423             assertConfiguration(expected,pool);
424         }
425         {
426             GenericObjectPool.Config expected = new GenericObjectPool.Config();
427             expected.maxActive = 2;
428             expected.maxIdle = 3;
429             expected.maxWait = 5L;
430             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
431             GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle);
432             assertConfiguration(expected,pool);
433         }
434         {
435             GenericObjectPool.Config expected = new GenericObjectPool.Config();
436             expected.maxActive = 2;
437             expected.maxIdle = 3;
438             expected.maxWait = 5L;
439             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
440             expected.testOnBorrow = true;
441             expected.testOnReturn = true;
442             GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle,expected.testOnBorrow,expected.testOnReturn);
443             assertConfiguration(expected,pool);
444         }
445         {
446             GenericObjectPool.Config expected = new GenericObjectPool.Config();
447             expected.maxActive = 2;
448             expected.maxIdle = 3;
449             expected.maxWait = 5L;
450             expected.minEvictableIdleTimeMillis = 7L;
451             expected.numTestsPerEvictionRun = 9;
452             expected.testOnBorrow = true;
453             expected.testOnReturn = true;
454             expected.testWhileIdle = true;
455             expected.timeBetweenEvictionRunsMillis = 11L;
456             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
457             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);
458             assertConfiguration(expected,pool);
459         }
460         {
461             GenericObjectPool.Config expected = new GenericObjectPool.Config();
462             expected.maxActive = 2;
463             expected.maxIdle = 3;
464             expected.minIdle = 1;
465             expected.maxWait = 5L;
466             expected.minEvictableIdleTimeMillis = 7L;
467             expected.numTestsPerEvictionRun = 9;
468             expected.testOnBorrow = true;
469             expected.testOnReturn = true;
470             expected.testWhileIdle = true;
471             expected.timeBetweenEvictionRunsMillis = 11L;
472             expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
473             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);
474             assertConfiguration(expected,pool);
475         }
476     }
477 
478     public void testSetConfig() throws Exception {
479         GenericObjectPool.Config expected = new GenericObjectPool.Config();
480         GenericObjectPool pool = new GenericObjectPool();
481         assertConfiguration(expected,pool);
482         expected.maxActive = 2;
483         expected.maxIdle = 3;
484         expected.maxWait = 5L;
485         expected.minEvictableIdleTimeMillis = 7L;
486         expected.numTestsPerEvictionRun = 9;
487         expected.testOnBorrow = true;
488         expected.testOnReturn = true;
489         expected.testWhileIdle = true;
490         expected.timeBetweenEvictionRunsMillis = 11L;
491         expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
492         pool.setConfig(expected);
493         assertConfiguration(expected,pool);
494     }
495 
496     public void testDebugInfo() throws Exception {
497         GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
498         pool.setMaxIdle(3);
499         assertNotNull(pool.debugInfo());
500         Object obj = pool.borrowObject();
501         assertNotNull(pool.debugInfo());
502         pool.returnObject(obj);
503         assertNotNull(pool.debugInfo());
504     }
505 
506     public void testStartAndStopEvictor() throws Exception {
507         // set up pool without evictor
508         pool.setMaxIdle(6);
509         pool.setMaxActive(6);
510         pool.setNumTestsPerEvictionRun(6);
511         pool.setMinEvictableIdleTimeMillis(100L);
512 
513         for(int j=0;j<2;j++) {
514             // populate the pool
515             {
516                 Object[] active = new Object[6];
517                 for(int i=0;i<6;i++) {
518                     active[i] = pool.borrowObject();
519                 }
520                 for(int i=0;i<6;i++) {
521                     pool.returnObject(active[i]);
522                 }
523             }
524     
525             // note that it stays populated
526             assertEquals("Should have 6 idle",6,pool.getNumIdle());
527     
528             // start the evictor
529             pool.setTimeBetweenEvictionRunsMillis(50L);
530             
531             // wait a second (well, .2 seconds)
532             try { Thread.sleep(200L); } catch(Exception e) { }
533             
534             // assert that the evictor has cleared out the pool
535             assertEquals("Should have 0 idle",0,pool.getNumIdle());
536     
537             // stop the evictor 
538             pool.startEvictor(0L);
539         }
540     }
541 
542     public void testEvictionWithNegativeNumTests() throws Exception {
543         // when numTestsPerEvictionRun is negative, it represents a fraction of the idle objects to test
544         pool.setMaxIdle(6);
545         pool.setMaxActive(6);
546         pool.setNumTestsPerEvictionRun(-2);
547         pool.setMinEvictableIdleTimeMillis(50L);
548         pool.setTimeBetweenEvictionRunsMillis(100L);
549 
550         Object[] active = new Object[6];
551         for(int i=0;i<6;i++) {
552             active[i] = pool.borrowObject();
553         }
554         for(int i=0;i<6;i++) {
555             pool.returnObject(active[i]);
556         }
557 
558         try { Thread.sleep(100L); } catch(Exception e) { }
559         assertTrue("Should at most 6 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 6);
560         try { Thread.sleep(100L); } catch(Exception e) { }
561         assertTrue("Should at most 3 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 3);
562         try { Thread.sleep(100L); } catch(Exception e) { }
563         assertTrue("Should be at most 2 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 2);
564         try { Thread.sleep(100L); } catch(Exception e) { }
565         assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
566     }
567 
568     public void testEviction() throws Exception {
569         pool.setMaxIdle(500);
570         pool.setMaxActive(500);
571         pool.setNumTestsPerEvictionRun(100);
572         pool.setMinEvictableIdleTimeMillis(250L);
573         pool.setTimeBetweenEvictionRunsMillis(500L);
574         pool.setTestWhileIdle(true);
575 
576         Object[] active = new Object[500];
577         for(int i=0;i<500;i++) {
578             active[i] = pool.borrowObject();
579         }
580         for(int i=0;i<500;i++) {
581             pool.returnObject(active[i]);
582         }
583 
584         try { Thread.sleep(1000L); } catch(Exception e) { }
585         assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
586         try { Thread.sleep(600L); } catch(Exception e) { }
587         assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
588         try { Thread.sleep(600L); } catch(Exception e) { }
589         assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
590         try { Thread.sleep(600L); } catch(Exception e) { }
591         assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
592         try { Thread.sleep(600L); } catch(Exception e) { }
593         assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
594         try { Thread.sleep(600L); } catch(Exception e) { }
595         assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
596 
597         for(int i=0;i<500;i++) {
598             active[i] = pool.borrowObject();
599         }
600         for(int i=0;i<500;i++) {
601             pool.returnObject(active[i]);
602         }
603 
604         try { Thread.sleep(1000L); } catch(Exception e) { }
605         assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
606         try { Thread.sleep(600L); } catch(Exception e) { }
607         assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
608         try { Thread.sleep(600L); } catch(Exception e) { }
609         assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
610         try { Thread.sleep(600L); } catch(Exception e) { }
611         assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
612         try { Thread.sleep(600L); } catch(Exception e) { }
613         assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
614         try { Thread.sleep(600L); } catch(Exception e) { }
615         assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
616     }
617 
618     public void testEvictionSoftMinIdle() throws Exception {
619         GenericObjectPool pool = null;
620         
621         class TimeTest extends BasePoolableObjectFactory {
622             private final long createTime;
623             public TimeTest() {
624                 createTime = System.currentTimeMillis();
625             }
626             public Object makeObject() throws Exception {
627                 return new TimeTest();
628             }
629             public long getCreateTime() {
630                 return createTime;
631             }
632         }
633         
634         pool = new GenericObjectPool(new TimeTest());
635         
636         pool.setMaxIdle(5);
637         pool.setMaxActive(5);
638         pool.setNumTestsPerEvictionRun(5);
639         pool.setMinEvictableIdleTimeMillis(3000L);
640         pool.setSoftMinEvictableIdleTimeMillis(1000L);
641         pool.setMinIdle(2);
642 
643         Object[] active = new Object[5];
644         Long[] creationTime = new Long[5] ;
645         for(int i=0;i<5;i++) {
646             active[i] = pool.borrowObject();
647             creationTime[i] = new Long(((TimeTest)active[i]).getCreateTime());
648         }
649         
650         for(int i=0;i<5;i++) {
651             pool.returnObject(active[i]);
652         }
653 
654         // Soft evict all but minIdle(2)
655         Thread.sleep(1500L);
656         pool.evict();
657         assertEquals("Idle count different than expected.", 2, pool.getNumIdle());
658 
659         // Hard evict the rest.
660         Thread.sleep(2000L);
661         pool.evict();
662         assertEquals("Idle count different than expected.", 0, pool.getNumIdle());
663     }
664 
665     public void testMinIdle() throws Exception {
666         pool.setMaxIdle(500);
667         pool.setMinIdle(5);
668         pool.setMaxActive(10);
669         pool.setNumTestsPerEvictionRun(0);
670         pool.setMinEvictableIdleTimeMillis(50L);
671         pool.setTimeBetweenEvictionRunsMillis(100L);
672         pool.setTestWhileIdle(true);
673 
674         try { Thread.sleep(150L); } catch(Exception e) { }
675         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
676 
677         Object[] active = new Object[5];
678         active[0] = pool.borrowObject();
679 
680         try { Thread.sleep(150L); } catch(Exception e) { }
681         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
682 
683         for(int i=1 ; i<5 ; i++) {
684             active[i] = pool.borrowObject();
685         }
686 
687         try { Thread.sleep(150L); } catch(Exception e) { }
688         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
689 
690         for(int i=0 ; i<5 ; i++) {
691             pool.returnObject(active[i]);
692         }
693 
694         try { Thread.sleep(150L); } catch(Exception e) { }
695         assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
696     }
697 
698     public void testMinIdleMaxActive() throws Exception {
699         pool.setMaxIdle(500);
700         pool.setMinIdle(5);
701         pool.setMaxActive(10);
702         pool.setNumTestsPerEvictionRun(0);
703         pool.setMinEvictableIdleTimeMillis(50L);
704         pool.setTimeBetweenEvictionRunsMillis(100L);
705         pool.setTestWhileIdle(true);
706 
707         try { Thread.sleep(150L); } catch(Exception e) { }
708         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
709 
710         Object[] active = new Object[10];
711 
712         try { Thread.sleep(150L); } catch(Exception e) { }
713         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
714 
715         for(int i=0 ; i<5 ; i++) {
716             active[i] = pool.borrowObject();
717         }
718 
719         try { Thread.sleep(150L); } catch(Exception e) { }
720         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
721 
722         for(int i=0 ; i<5 ; i++) {
723             pool.returnObject(active[i]);
724         }
725 
726         try { Thread.sleep(150L); } catch(Exception e) { }
727         assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
728 
729         for(int i=0 ; i<10 ; i++) {
730             active[i] = pool.borrowObject();
731         }
732 
733         try { Thread.sleep(150L); } catch(Exception e) { }
734         assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
735 
736         for(int i=0 ; i<10 ; i++) {
737             pool.returnObject(active[i]);
738         }
739 
740         try { Thread.sleep(150L); } catch(Exception e) { }
741         assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
742     }
743 
744     public void testThreaded1() throws Exception {
745         pool.setMaxActive(15);
746         pool.setMaxIdle(15);
747         pool.setMaxWait(1000L);
748         TestThread[] threads = new TestThread[20];
749         for(int i=0;i<20;i++) {
750             threads[i] = new TestThread(pool,100,50);
751             Thread t = new Thread(threads[i]);
752             t.start();
753         }
754         for(int i=0;i<20;i++) {
755             while(!(threads[i]).complete()) {
756                 try {
757                     Thread.sleep(500L);
758                 } catch(Exception e) {
759                     // ignored
760                 }
761             }
762             if(threads[i].failed()) {
763                 fail();
764             }
765         }
766     }
767 
768     class TestThread implements Runnable {
769         java.util.Random _random = new java.util.Random();
770         ObjectPool _pool = null;
771         boolean _complete = false;
772         boolean _failed = false;
773         int _iter = 100;
774         int _delay = 50;
775 
776         public TestThread(ObjectPool pool) {
777             _pool = pool;
778         }
779 
780         public TestThread(ObjectPool pool, int iter) {
781             _pool = pool;
782             _iter = iter;
783         }
784 
785         public TestThread(ObjectPool pool, int iter, int delay) {
786             _pool = pool;
787             _iter = iter;
788             _delay = delay;
789         }
790 
791         public boolean complete() {
792             return _complete;
793         }
794 
795         public boolean failed() {
796             return _failed;
797         }
798 
799         public void run() {
800             for(int i=0;i<_iter;i++) {
801                 try {
802                     Thread.sleep((long)_random.nextInt(_delay));
803                 } catch(Exception e) {
804                     // ignored
805                 }
806                 Object obj = null;
807                 try {
808                     obj = _pool.borrowObject();
809                 } catch(Exception e) {
810                     _failed = true;
811                     _complete = true;
812                     break;
813                 }
814 
815                 try {
816                     Thread.sleep((long)_random.nextInt(_delay));
817                 } catch(Exception e) {
818                     // ignored
819                 }
820                 try {
821                     _pool.returnObject(obj);
822                 } catch(Exception e) {
823                     _failed = true;
824                     _complete = true;
825                     break;
826                 }
827             }
828             _complete = true;
829         }
830     }
831 
832     public void testFIFO() throws Exception {
833         pool.addObject(); // "0"
834         pool.addObject(); // "1"
835         pool.addObject(); // "2"
836         assertEquals("Oldest", "0", pool.borrowObject());
837         assertEquals("Middle", "1", pool.borrowObject());
838         assertEquals("Youngest", "2", pool.borrowObject());
839         assertEquals("new-3", "3", pool.borrowObject());
840         pool.returnObject("r");
841         assertEquals("returned", "r", pool.borrowObject());
842         assertEquals("new-4", "4", pool.borrowObject());
843     }
844 
845     public void testAddObject() throws Exception {
846         assertEquals("should be zero idle", 0, pool.getNumIdle());
847     	pool.addObject();
848 		assertEquals("should be one idle", 1, pool.getNumIdle());
849 		assertEquals("should be zero active", 0, pool.getNumActive());
850 		Object obj = pool.borrowObject();
851 		assertEquals("should be zero idle", 0, pool.getNumIdle());
852 		assertEquals("should be one active", 1, pool.getNumActive());
853 		pool.returnObject(obj);
854 		assertEquals("should be one idle", 1, pool.getNumIdle());
855 		assertEquals("should be zero active", 0, pool.getNumActive());
856     }
857     
858     private List testFactorySequenceStates = new ArrayList(5);
859     public void testFactorySequence() throws Exception {
860         // setup
861         // We need a factory that tracks method call sequence.
862         PoolableObjectFactory pof = new PoolableObjectFactory() {
863             public Object makeObject() throws Exception {
864                 testFactorySequenceStates.add("makeObject");
865                 return new Object();
866             }
867 
868             public void activateObject(Object obj) throws Exception {
869                 testFactorySequenceStates.add("activateObject");
870             }
871 
872             public boolean validateObject(Object obj) {
873                 testFactorySequenceStates.add("validateObject");
874                 return true;
875             }
876 
877             public void passivateObject(Object obj) throws Exception {
878                 testFactorySequenceStates.add("passivateObject");
879             }
880 
881             public void destroyObject(Object obj) throws Exception {
882                 testFactorySequenceStates.add("destroyObject");
883             }
884         };
885 
886         GenericObjectPool pool = new GenericObjectPool(pof);
887         pool.setTestOnBorrow(true);
888         pool.setTestOnReturn(true);
889 
890         // check the order in which the factory is called during borrow
891         testFactorySequenceStates.clear();
892         Object o = pool.borrowObject();
893         List desiredSequence = Arrays.asList(new String[] {
894                 "makeObject",
895                 "activateObject",
896                 "validateObject"
897         });
898         assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
899 
900         // check the order in which the factory is called when returning an object
901         testFactorySequenceStates.clear();
902         pool.returnObject(o);
903         desiredSequence = Arrays.asList(new String[] {
904                 "validateObject",
905                 "passivateObject"
906         });
907         assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
908 
909         // check the order in which the factory is called during borrow again
910         testFactorySequenceStates.clear();
911         o = pool.borrowObject();
912         desiredSequence = Arrays.asList(new String[] {
913                 "activateObject",
914                 "validateObject"
915         });
916         assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
917 
918         // check the order in which the factory is called when invalidating an object
919         testFactorySequenceStates.clear();
920         pool.invalidateObject(o);
921         desiredSequence = Arrays.asList(new String[] {
922                 "destroyObject"
923         });
924         assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
925     }
926 
927     private GenericObjectPool pool = null;
928 
929     private void assertConfiguration(GenericObjectPool.Config expected, GenericObjectPool actual) throws Exception {
930         assertEquals("testOnBorrow",expected.testOnBorrow,actual.getTestOnBorrow());
931         assertEquals("testOnReturn",expected.testOnReturn,actual.getTestOnReturn());
932         assertEquals("testWhileIdle",expected.testWhileIdle,actual.getTestWhileIdle());
933         assertEquals("whenExhaustedAction",expected.whenExhaustedAction,actual.getWhenExhaustedAction());
934         assertEquals("maxActive",expected.maxActive,actual.getMaxActive());
935         assertEquals("maxIdle",expected.maxIdle,actual.getMaxIdle());
936         assertEquals("maxWait",expected.maxWait,actual.getMaxWait());
937         assertEquals("minEvictableIdleTimeMillis",expected.minEvictableIdleTimeMillis,actual.getMinEvictableIdleTimeMillis());
938         assertEquals("numTestsPerEvictionRun",expected.numTestsPerEvictionRun,actual.getNumTestsPerEvictionRun());
939         assertEquals("timeBetweenEvictionRunsMillis",expected.timeBetweenEvictionRunsMillis,actual.getTimeBetweenEvictionRunsMillis());
940     }
941 
942     public class SimpleFactory implements PoolableObjectFactory {
943         public SimpleFactory() {
944             this(true);
945         }
946         public SimpleFactory(boolean valid) {
947             this(valid,valid);
948         }
949         public SimpleFactory(boolean evalid, boolean ovalid) {
950             evenValid = evalid;
951             oddValid = ovalid;
952         }
953         void setValid(boolean valid) {
954             setEvenValid(valid);
955             setOddValid(valid);            
956         }
957         void setEvenValid(boolean valid) {
958             evenValid = valid;
959         }
960         void setOddValid(boolean valid) {
961             oddValid = valid;
962         }
963         public void setThrowExceptionOnPassivate(boolean bool) {
964             exceptionOnPassivate = bool;
965         }
966     
967         public Object makeObject() { return String.valueOf(makeCounter++); }
968         public void destroyObject(Object obj) { }
969         public boolean validateObject(Object obj) {
970             if (enableValidation) { 
971                 return validateCounter++%2 == 0 ? evenValid : oddValid; 
972             }
973             else {
974                 return true;
975             }
976         }
977         public void activateObject(Object obj) throws Exception {
978             if (exceptionOnActivate) {
979                 if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) {
980                     throw new Exception();
981                 }
982             }
983         }
984         public void passivateObject(Object obj) throws Exception {
985             if(exceptionOnPassivate) {
986                 throw new Exception();
987             }
988         }
989         int makeCounter = 0;
990         int validateCounter = 0;
991         boolean evenValid = true;
992         boolean oddValid = true;
993         boolean exceptionOnPassivate = false;
994         boolean exceptionOnActivate = false;
995         boolean enableValidation = true;
996 
997         public boolean isThrowExceptionOnActivate() {
998             return exceptionOnActivate;
999         }
1000 
1001         public void setThrowExceptionOnActivate(boolean b) {
1002             exceptionOnActivate = b;
1003         }
1004 
1005         public boolean isValidationEnabled() {
1006             return enableValidation;
1007         }
1008 
1009         public void setValidationEnabled(boolean b) {
1010             enableValidation = b;
1011         }
1012     }
1013 
1014     protected boolean isLifo() {
1015  
1016         return false;
1017     }
1018 
1019     protected boolean isFifo() {
1020         return true;
1021     }
1022 }
1023 
1024