View Javadoc

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 org.apache.commons.pool.KeyedObjectPool;
25  import org.apache.commons.pool.KeyedPoolableObjectFactory;
26  import org.apache.commons.pool.TestBaseKeyedObjectPool;
27  
28  /**
29   * @author Rodney Waldhoff
30   * @version $Revision: 958393 $ $Date: 2010-06-27 09:32:43 -0700 (Sun, 27 Jun 2010) $
31   */
32  public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool {
33      public TestStackKeyedObjectPool(String testName) {
34          super(testName);
35      }
36  
37      protected KeyedObjectPool makeEmptyPool(int mincapacity) {
38          StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity);
39          return pool;
40      }
41  
42      protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) {
43          return new StackKeyedObjectPool(factory);
44      }
45  
46      protected Object getNthObject(Object key, int n) {
47          return String.valueOf(key) + String.valueOf(n);
48      }
49  
50      protected Object makeKey(int n) {
51          return String.valueOf(n);
52      }
53  
54      private StackKeyedObjectPool pool = null;
55  
56      public void setUp() throws Exception {
57          super.setUp();
58          pool = new StackKeyedObjectPool(
59              new KeyedPoolableObjectFactory()  {
60                  int counter = 0;
61                  public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); }
62                  public void destroyObject(Object key, Object obj) { }
63                  public boolean validateObject(Object key, Object obj) { return true; }
64                  public void activateObject(Object key, Object obj) { }
65                  public void passivateObject(Object key, Object obj) { }
66              }
67              );
68      }
69  
70  
71      public void tearDown() throws Exception {
72          super.tearDown();
73          pool = null;
74      }
75  
76      public void testCloseBug() throws Exception {
77          {
78              Object obj0 = pool.borrowObject("");
79              Object obj1 = pool.borrowObject("");
80              assertEquals(2,pool.getNumActive(""));
81              assertEquals(0,pool.getNumIdle(""));
82              pool.returnObject("",obj1);
83              pool.returnObject("",obj0);
84              assertEquals(0,pool.getNumActive(""));
85              assertEquals(2,pool.getNumIdle(""));
86          }
87          {
88              Object obj0 = pool.borrowObject("2");
89              Object obj1 = pool.borrowObject("2");
90              assertEquals(2,pool.getNumActive("2"));
91              assertEquals(0,pool.getNumIdle("2"));
92              pool.returnObject("2",obj1);
93              pool.returnObject("2",obj0);
94              assertEquals(0,pool.getNumActive("2"));
95              assertEquals(2,pool.getNumIdle("2"));
96          }
97          pool.close();
98      }
99  
100     public void testIdleCap() throws Exception {
101         Object[] active = new Object[100];
102         for(int i=0;i<100;i++) {
103             active[i] = pool.borrowObject("");
104         }
105         assertEquals(100,pool.getNumActive(""));
106         assertEquals(0,pool.getNumIdle(""));
107         for(int i=0;i<100;i++) {
108             pool.returnObject("",active[i]);
109             assertEquals(99 - i,pool.getNumActive(""));
110             assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
111         }
112     }
113     
114     /**
115      * Verifies maxSleeping contract: When returnObject triggers maxSleeping exceeded,
116      * the bottom (oldest) instance in the pool is destroyed to make room for the newly
117      * returning instance, which is pushed onto the idle object stack.
118      */
119     public void testRemoveOldest() throws Exception {
120         pool._maxSleeping = 2;
121         Object obj0 = pool.borrowObject("");
122         Object obj1 = pool.borrowObject("");
123         Object obj2 = pool.borrowObject("");
124         pool.returnObject("", obj0); // Push 0 onto bottom of stack
125         pool.returnObject("", obj1); // Push 1
126         pool.returnObject("", obj2); // maxSleeping exceeded -> 0 destroyed, 2 pushed
127         assertEquals("2", pool.borrowObject("")); // 2 was pushed on top
128         assertEquals("1", pool.borrowObject("")); // 1 still there
129         assertEquals("3", pool.borrowObject("")); // New instance created (0 is gone)
130     }
131 
132     public void testPoolWithNullFactory() throws Exception {
133         KeyedObjectPool pool = new StackKeyedObjectPool(10);
134         for(int i=0;i<10;i++) {
135             pool.returnObject("X",new Integer(i));
136         }
137         for(int j=0;j<3;j++) {
138             Integer[] borrowed = new Integer[10];
139             BitSet found = new BitSet();
140             for(int i=0;i<10;i++) {
141                 borrowed[i] = (Integer)(pool.borrowObject("X"));
142                 assertNotNull(borrowed);
143                 assertTrue(!found.get(borrowed[i].intValue()));
144                 found.set(borrowed[i].intValue());
145             }
146             for(int i=0;i<10;i++) {
147                 pool.returnObject("X",borrowed[i]);
148             }
149         }
150         pool.invalidateObject("X",pool.borrowObject("X"));
151         pool.invalidateObject("X",pool.borrowObject("X"));
152         pool.clear("X");
153         pool.clear();
154     }
155 
156     public void testVariousConstructors() throws Exception {
157         {
158             StackKeyedObjectPool pool = new StackKeyedObjectPool();
159             assertNotNull(pool);
160         }
161         {
162             StackKeyedObjectPool pool = new StackKeyedObjectPool(10);
163             assertNotNull(pool);
164         }
165         {
166             StackKeyedObjectPool pool = new StackKeyedObjectPool(10,5);
167             assertNotNull(pool);
168         }
169         {
170             StackKeyedObjectPool pool = new StackKeyedObjectPool(null);
171             assertNotNull(pool);
172         }
173         {
174             StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10);
175             assertNotNull(pool);
176         }
177         {
178             StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10,5);
179             assertNotNull(pool);
180         }
181     }
182 
183     public void testToString() throws Exception {
184         StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory());
185         assertNotNull(pool.toString());
186         Object obj = pool.borrowObject("key");
187         assertNotNull(pool.toString());
188         pool.returnObject("key",obj);
189         assertNotNull(pool.toString());
190     }
191 
192     public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
193         KeyedObjectPool pool = new StackKeyedObjectPool();
194         try {
195             pool.borrowObject("x");
196             fail("Expected NoSuchElementException");
197         } catch(NoSuchElementException e) {
198             // expected
199         }
200     }
201 
202     public void testSetFactory() throws Exception {
203         KeyedObjectPool pool = new StackKeyedObjectPool();
204         try {
205             pool.borrowObject("x");
206             fail("Expected NoSuchElementException");
207         } catch(NoSuchElementException e) {
208             // expected
209         }
210         pool.setFactory(new SimpleFactory());
211         Object obj = pool.borrowObject("x");
212         assertNotNull(obj);
213         pool.returnObject("x",obj);
214     }
215 
216     public void testCantResetFactoryWithActiveObjects() throws Exception {
217         KeyedObjectPool pool = new StackKeyedObjectPool();
218         pool.setFactory(new SimpleFactory());
219         Object obj = pool.borrowObject("x");
220         assertNotNull(obj);
221 
222         try {
223             pool.setFactory(new SimpleFactory());
224             fail("Expected IllegalStateException");
225         } catch(IllegalStateException e) {
226             // expected
227         }
228     }
229 
230     public void testCanResetFactoryWithoutActiveObjects() throws Exception {
231         KeyedObjectPool pool = new StackKeyedObjectPool();
232         {
233             pool.setFactory(new SimpleFactory());
234             Object obj = pool.borrowObject("x");
235             assertNotNull(obj);
236             pool.returnObject("x",obj);
237         }
238         {
239             pool.setFactory(new SimpleFactory());
240             Object obj = pool.borrowObject("x");
241             assertNotNull(obj);
242             pool.returnObject("x",obj);
243         }
244     }
245 
246     public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
247         KeyedObjectPool pool = new StackKeyedObjectPool(
248             new KeyedPoolableObjectFactory() {
249                 int counter = 0;
250                 public Object makeObject(Object key) { return new Integer(counter++); }
251                 public void destroyObject(Object key, Object obj) { }
252                 public boolean validateObject(Object key, Object obj) {
253                     if(obj instanceof Integer) {
254                         return ((((Integer)obj).intValue() % 2) == 1);
255                     } else {
256                         return false;
257                     }
258                 }
259                 public void activateObject(Object key, Object obj) { }
260                 public void passivateObject(Object key, Object obj) {
261                     if(obj instanceof Integer) {
262                         if((((Integer)obj).intValue() % 3) == 0) {
263                             throw new RuntimeException("Couldn't passivate");
264                         }
265                     } else {
266                         throw new RuntimeException("Couldn't passivate");
267                     }
268                 }
269             }
270         );
271 
272         Object[] obj = new Object[10];
273         for(int i=0;i<10;i++) {
274             Object object = null;
275             int k = 0;
276             while (object == null && k < 100) { // bound not really needed
277                 try {
278                     k++;
279                     object = pool.borrowObject("key");
280                     obj[i] = object;
281                 } catch (NoSuchElementException ex) {
282                     // Expected for evens, which fail validation
283                 }
284             }
285             assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
286         }
287         // 1,3,5,...,19 pass validation, get checked out
288         for(int i=0;i<10;i++) {
289             pool.returnObject("key",obj[i]);
290             assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
291         }
292         // 3, 9, 15 fail passivation.  
293         assertEquals(7,pool.getNumIdle());
294         assertEquals(new Integer(19), pool.borrowObject("key"));
295         assertEquals(new Integer(17), pool.borrowObject("key"));
296         assertEquals(new Integer(13), pool.borrowObject("key"));
297         assertEquals(new Integer(11), pool.borrowObject("key"));
298         assertEquals(new Integer(7), pool.borrowObject("key"));
299         assertEquals(new Integer(5), pool.borrowObject("key"));
300         assertEquals(new Integer(1), pool.borrowObject("key"));   
301     }
302 
303     class SimpleFactory implements KeyedPoolableObjectFactory {
304         HashMap map = new HashMap();
305         public Object makeObject(Object key) {
306             int counter = 0;
307             Integer Counter = (Integer)(map.get(key));
308             if(null != Counter) {
309                 counter = Counter.intValue();
310             }
311             map.put(key,new Integer(counter + 1));
312             return String.valueOf(key) + String.valueOf(counter);
313         }
314         public void destroyObject(Object key, Object obj) { }
315         public boolean validateObject(Object key, Object obj) { return true; }
316         public void activateObject(Object key, Object obj) { }
317         public void passivateObject(Object key, Object obj) { }
318     }
319 
320     protected boolean isLifo() {
321         return true;
322     }
323 
324     protected boolean isFifo() {
325         return false;
326     }
327 }