001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.pool.impl;
019    
020    import java.util.BitSet;
021    import java.util.HashMap;
022    import java.util.NoSuchElementException;
023    
024    import junit.framework.Test;
025    import junit.framework.TestSuite;
026    
027    import org.apache.commons.pool.KeyedObjectPool;
028    import org.apache.commons.pool.KeyedPoolableObjectFactory;
029    import org.apache.commons.pool.TestBaseKeyedObjectPool;
030    
031    /**
032     * @author Rodney Waldhoff
033     * @version $Revision: 775703 $ $Date: 2009-05-17 12:39:51 -0400 (Sun, 17 May 2009) $
034     */
035    public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool {
036        public TestStackKeyedObjectPool(String testName) {
037            super(testName);
038        }
039    
040        public static Test suite() {
041            return new TestSuite(TestStackKeyedObjectPool.class);
042        }
043    
044        protected KeyedObjectPool makeEmptyPool(int mincapacity) {
045            StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity);
046            return pool;
047        }
048    
049        protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) {
050            return new StackKeyedObjectPool(factory);
051        }
052    
053        protected Object getNthObject(Object key, int n) {
054            return String.valueOf(key) + String.valueOf(n);
055        }
056    
057        protected Object makeKey(int n) {
058            return String.valueOf(n);
059        }
060    
061        private StackKeyedObjectPool pool = null;
062    
063        public void setUp() throws Exception {
064            super.setUp();
065            pool = new StackKeyedObjectPool(
066                new KeyedPoolableObjectFactory()  {
067                    int counter = 0;
068                    public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); }
069                    public void destroyObject(Object key, Object obj) { }
070                    public boolean validateObject(Object key, Object obj) { return true; }
071                    public void activateObject(Object key, Object obj) { }
072                    public void passivateObject(Object key, Object obj) { }
073                }
074                );
075        }
076    
077    
078        public void tearDown() throws Exception {
079            super.tearDown();
080            pool = null;
081        }
082    
083        public void testCloseBug() throws Exception {
084            {
085                Object obj0 = pool.borrowObject("");
086                Object obj1 = pool.borrowObject("");
087                assertEquals(2,pool.getNumActive(""));
088                assertEquals(0,pool.getNumIdle(""));
089                pool.returnObject("",obj1);
090                pool.returnObject("",obj0);
091                assertEquals(0,pool.getNumActive(""));
092                assertEquals(2,pool.getNumIdle(""));
093            }
094            {
095                Object obj0 = pool.borrowObject("2");
096                Object obj1 = pool.borrowObject("2");
097                assertEquals(2,pool.getNumActive("2"));
098                assertEquals(0,pool.getNumIdle("2"));
099                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    }