1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.pool.impl;
19  
20  import java.util.BitSet;
21  import java.util.HashMap;
22  import java.util.NoSuchElementException;
23  
24  import junit.framework.Test;
25  import junit.framework.TestSuite;
26  
27  import org.apache.commons.pool.KeyedObjectPool;
28  import org.apache.commons.pool.KeyedPoolableObjectFactory;
29  import org.apache.commons.pool.TestBaseKeyedObjectPool;
30  
31  /**
32   * @author Rodney Waldhoff
33   * @version $Revision: 775703 $ $Date: 2009-05-17 12:39:51 -0400 (Sun, 17 May 2009) $
34   */
35  public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool {
36      public TestStackKeyedObjectPool(String testName) {
37          super(testName);
38      }
39  
40      public static Test suite() {
41          return new TestSuite(TestStackKeyedObjectPool.class);
42      }
43  
44      protected KeyedObjectPool makeEmptyPool(int mincapacity) {
45          StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity);
46          return pool;
47      }
48  
49      protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) {
50          return new StackKeyedObjectPool(factory);
51      }
52  
53      protected Object getNthObject(Object key, int n) {
54          return String.valueOf(key) + String.valueOf(n);
55      }
56  
57      protected Object makeKey(int n) {
58          return String.valueOf(n);
59      }
60  
61      private StackKeyedObjectPool pool = null;
62  
63      public void setUp() throws Exception {
64          super.setUp();
65          pool = new StackKeyedObjectPool(
66              new KeyedPoolableObjectFactory()  {
67                  int counter = 0;
68                  public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); }
69                  public void destroyObject(Object key, Object obj) { }
70                  public boolean validateObject(Object key, Object obj) { return true; }
71                  public void activateObject(Object key, Object obj) { }
72                  public void passivateObject(Object key, Object obj) { }
73              }
74              );
75      }
76  
77  
78      public void tearDown() throws Exception {
79          super.tearDown();
80          pool = null;
81      }
82  
83      public void testCloseBug() throws Exception {
84          {
85              Object obj0 = pool.borrowObject("");
86              Object obj1 = pool.borrowObject("");
87              assertEquals(2,pool.getNumActive(""));
88              assertEquals(0,pool.getNumIdle(""));
89              pool.returnObject("",obj1);
90              pool.returnObject("",obj0);
91              assertEquals(0,pool.getNumActive(""));
92              assertEquals(2,pool.getNumIdle(""));
93          }
94          {
95              Object obj0 = pool.borrowObject("2");
96              Object obj1 = pool.borrowObject("2");
97              assertEquals(2,pool.getNumActive("2"));
98              assertEquals(0,pool.getNumIdle("2"));
99              pool.returnObject("2",obj1);
100             pool.returnObject("2",obj0);
101             assertEquals(0,pool.getNumActive("2"));
102             assertEquals(2,pool.getNumIdle("2"));
103         }
104         pool.close();
105     }
106 
107     public void testIdleCap() throws Exception {
108         Object[] active = new Object[100];
109         for(int i=0;i<100;i++) {
110             active[i] = pool.borrowObject("");
111         }
112         assertEquals(100,pool.getNumActive(""));
113         assertEquals(0,pool.getNumIdle(""));
114         for(int i=0;i<100;i++) {
115             pool.returnObject("",active[i]);
116             assertEquals(99 - i,pool.getNumActive(""));
117             assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
118         }
119     }
120 
121     public void testPoolWithNullFactory() throws Exception {
122         KeyedObjectPool pool = new StackKeyedObjectPool(10);
123         for(int i=0;i<10;i++) {
124             pool.returnObject("X",new Integer(i));
125         }
126         for(int j=0;j<3;j++) {
127             Integer[] borrowed = new Integer[10];
128             BitSet found = new BitSet();
129             for(int i=0;i<10;i++) {
130                 borrowed[i] = (Integer)(pool.borrowObject("X"));
131                 assertNotNull(borrowed);
132                 assertTrue(!found.get(borrowed[i].intValue()));
133                 found.set(borrowed[i].intValue());
134             }
135             for(int i=0;i<10;i++) {
136                 pool.returnObject("X",borrowed[i]);
137             }
138         }
139         pool.invalidateObject("X",pool.borrowObject("X"));
140         pool.invalidateObject("X",pool.borrowObject("X"));
141         pool.clear("X");
142         pool.clear();
143     }
144 
145     public void testVariousConstructors() throws Exception {
146         {
147             StackKeyedObjectPool pool = new StackKeyedObjectPool();
148             assertNotNull(pool);
149         }
150         {
151             StackKeyedObjectPool pool = new StackKeyedObjectPool(10);
152             assertNotNull(pool);
153         }
154         {
155             StackKeyedObjectPool pool = new StackKeyedObjectPool(10,5);
156             assertNotNull(pool);
157         }
158         {
159             StackKeyedObjectPool pool = new StackKeyedObjectPool(null);
160             assertNotNull(pool);
161         }
162         {
163             StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10);
164             assertNotNull(pool);
165         }
166         {
167             StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10,5);
168             assertNotNull(pool);
169         }
170     }
171 
172     public void testToString() throws Exception {
173         StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory());
174         assertNotNull(pool.toString());
175         Object obj = pool.borrowObject("key");
176         assertNotNull(pool.toString());
177         pool.returnObject("key",obj);
178         assertNotNull(pool.toString());
179     }
180 
181     public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
182         KeyedObjectPool pool = new StackKeyedObjectPool();
183         try {
184             pool.borrowObject("x");
185             fail("Expected NoSuchElementException");
186         } catch(NoSuchElementException e) {
187             // expected
188         }
189     }
190 
191     public void testSetFactory() throws Exception {
192         KeyedObjectPool pool = new StackKeyedObjectPool();
193         try {
194             pool.borrowObject("x");
195             fail("Expected NoSuchElementException");
196         } catch(NoSuchElementException e) {
197             // expected
198         }
199         pool.setFactory(new SimpleFactory());
200         Object obj = pool.borrowObject("x");
201         assertNotNull(obj);
202         pool.returnObject("x",obj);
203     }
204 
205     public void testCantResetFactoryWithActiveObjects() throws Exception {
206         KeyedObjectPool pool = new StackKeyedObjectPool();
207         pool.setFactory(new SimpleFactory());
208         Object obj = pool.borrowObject("x");
209         assertNotNull(obj);
210 
211         try {
212             pool.setFactory(new SimpleFactory());
213             fail("Expected IllegalStateException");
214         } catch(IllegalStateException e) {
215             // expected
216         }
217     }
218 
219     public void testCanResetFactoryWithoutActiveObjects() throws Exception {
220         KeyedObjectPool pool = new StackKeyedObjectPool();
221         {
222             pool.setFactory(new SimpleFactory());
223             Object obj = pool.borrowObject("x");
224             assertNotNull(obj);
225             pool.returnObject("x",obj);
226         }
227         {
228             pool.setFactory(new SimpleFactory());
229             Object obj = pool.borrowObject("x");
230             assertNotNull(obj);
231             pool.returnObject("x",obj);
232         }
233     }
234 
235     public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
236         KeyedObjectPool pool = new StackKeyedObjectPool(
237             new KeyedPoolableObjectFactory() {
238                 int counter = 0;
239                 public Object makeObject(Object key) { return new Integer(counter++); }
240                 public void destroyObject(Object key, Object obj) { }
241                 public boolean validateObject(Object key, Object obj) {
242                     if(obj instanceof Integer) {
243                         return ((((Integer)obj).intValue() % 2) == 1);
244                     } else {
245                         return false;
246                     }
247                 }
248                 public void activateObject(Object key, Object obj) { }
249                 public void passivateObject(Object key, Object obj) {
250                     if(obj instanceof Integer) {
251                         if((((Integer)obj).intValue() % 3) == 0) {
252                             throw new RuntimeException("Couldn't passivate");
253                         }
254                     } else {
255                         throw new RuntimeException("Couldn't passivate");
256                     }
257                 }
258             }
259         );
260 
261         Object[] obj = new Object[10];
262         for(int i=0;i<10;i++) {
263             Object object = null;
264             int k = 0;
265             while (object == null && k < 100) { // bound not really needed
266                 try {
267                     k++;
268                     object = pool.borrowObject("key");
269                     obj[i] = object;
270                 } catch (NoSuchElementException ex) {
271                     // Expected for evens, which fail validation
272                 }
273             }
274             assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
275         }
276         // 1,3,5,...,19 pass validation, get checked out
277         for(int i=0;i<10;i++) {
278             pool.returnObject("key",obj[i]);
279             assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
280         }
281         // 3, 9, 15 fail passivation.  
282         assertEquals(7,pool.getNumIdle());
283         assertEquals(new Integer(19), pool.borrowObject("key"));
284         assertEquals(new Integer(17), pool.borrowObject("key"));
285         assertEquals(new Integer(13), pool.borrowObject("key"));
286         assertEquals(new Integer(11), pool.borrowObject("key"));
287         assertEquals(new Integer(7), pool.borrowObject("key"));
288         assertEquals(new Integer(5), pool.borrowObject("key"));
289         assertEquals(new Integer(1), pool.borrowObject("key"));   
290     }
291 
292     class SimpleFactory implements KeyedPoolableObjectFactory {
293         HashMap map = new HashMap();
294         public Object makeObject(Object key) {
295             int counter = 0;
296             Integer Counter = (Integer)(map.get(key));
297             if(null != Counter) {
298                 counter = Counter.intValue();
299             }
300             map.put(key,new Integer(counter + 1));
301             return String.valueOf(key) + String.valueOf(counter);
302         }
303         public void destroyObject(Object key, Object obj) { }
304         public boolean validateObject(Object key, Object obj) { return true; }
305         public void activateObject(Object key, Object obj) { }
306         public void passivateObject(Object key, Object obj) { }
307     }
308 
309     protected boolean isLifo() {
310         return true;
311     }
312 
313     protected boolean isFifo() {
314         return false;
315     }
316 }