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 junit.framework.Test;
021 import junit.framework.TestSuite;
022 import org.apache.commons.pool.ObjectPool;
023 import org.apache.commons.pool.PoolableObjectFactory;
024 import org.apache.commons.pool.TestBaseObjectPool;
025
026 import java.util.ArrayList;
027 import java.util.BitSet;
028 import java.util.List;
029 import java.util.NoSuchElementException;
030
031 /**
032 * @author Rodney Waldhoff
033 * @author Dirk Verbeeck
034 * @author Sandy McArthur
035 * @version $Revision: 775703 $ $Date: 2009-05-17 12:39:51 -0400 (Sun, 17 May 2009) $
036 */
037 public class TestStackObjectPool extends TestBaseObjectPool {
038 public TestStackObjectPool(String testName) {
039 super(testName);
040 }
041
042 public static Test suite() {
043 return new TestSuite(TestStackObjectPool.class);
044 }
045
046 protected ObjectPool makeEmptyPool(int mincap) {
047 return new StackObjectPool(new SimpleFactory());
048 }
049
050 protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) {
051 return new StackObjectPool(factory);
052 }
053
054 protected Object getNthObject(int n) {
055 return String.valueOf(n);
056 }
057
058 public void testIdleCap() throws Exception {
059 ObjectPool pool = makeEmptyPool(8);
060 Object[] active = new Object[100];
061 for(int i=0;i<100;i++) {
062 active[i] = pool.borrowObject();
063 }
064 assertEquals(100,pool.getNumActive());
065 assertEquals(0,pool.getNumIdle());
066 for(int i=0;i<100;i++) {
067 pool.returnObject(active[i]);
068 assertEquals(99 - i,pool.getNumActive());
069 assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
070 }
071 }
072
073 public void testPoolWithNullFactory() throws Exception {
074 ObjectPool pool = new StackObjectPool(10);
075 for(int i=0;i<10;i++) {
076 pool.returnObject(new Integer(i));
077 }
078 for(int j=0;j<3;j++) {
079 Integer[] borrowed = new Integer[10];
080 BitSet found = new BitSet();
081 for(int i=0;i<10;i++) {
082 borrowed[i] = (Integer)(pool.borrowObject());
083 assertNotNull(borrowed);
084 assertTrue(!found.get(borrowed[i].intValue()));
085 found.set(borrowed[i].intValue());
086 }
087 for(int i=0;i<10;i++) {
088 pool.returnObject(borrowed[i]);
089 }
090 }
091 pool.invalidateObject(pool.borrowObject());
092 pool.invalidateObject(pool.borrowObject());
093 pool.clear();
094 }
095
096 public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
097 ObjectPool pool = new StackObjectPool();
098 try {
099 pool.borrowObject();
100 fail("Expected NoSuchElementException");
101 } catch(NoSuchElementException e) {
102 // expected
103 }
104 }
105
106 public void testSetFactory() throws Exception {
107 ObjectPool pool = new StackObjectPool();
108 try {
109 pool.borrowObject();
110 fail("Expected NoSuchElementException");
111 } catch(NoSuchElementException e) {
112 // expected
113 }
114 pool.setFactory(new SimpleFactory());
115 Object obj = pool.borrowObject();
116 assertNotNull(obj);
117 pool.returnObject(obj);
118 }
119
120 public void testCantResetFactoryWithActiveObjects() throws Exception {
121 ObjectPool pool = new StackObjectPool();
122 pool.setFactory(new SimpleFactory());
123 Object obj = pool.borrowObject();
124 assertNotNull(obj);
125
126 try {
127 pool.setFactory(new SimpleFactory());
128 fail("Expected IllegalStateException");
129 } catch(IllegalStateException e) {
130 // expected
131 }
132 }
133
134 public void testCanResetFactoryWithoutActiveObjects() throws Exception {
135 ObjectPool pool = new StackObjectPool();
136 {
137 pool.setFactory(new SimpleFactory());
138 Object obj = pool.borrowObject();
139 assertNotNull(obj);
140 pool.returnObject(obj);
141 }
142 {
143 pool.setFactory(new SimpleFactory());
144 Object obj = pool.borrowObject();
145 assertNotNull(obj);
146 pool.returnObject(obj);
147 }
148 }
149
150
151 public void testBorrowWithSometimesInvalidObjects() throws Exception {
152 ObjectPool pool = new StackObjectPool(20);
153 pool.setFactory(
154 new PoolableObjectFactory() {
155 // factory makes Integer objects
156 int counter = 0;
157 public Object makeObject() { return new Integer(counter++); }
158 public void destroyObject(Object obj) { }
159 public boolean validateObject(Object obj) {
160 // only odd objects are valid
161 if(obj instanceof Integer) {
162 return ((((Integer)obj).intValue() % 2) == 1);
163 } else {
164 return false;
165 }
166 }
167 public void activateObject(Object obj) { }
168 public void passivateObject(Object obj) {
169 final Integer integer = (Integer)obj;
170 if (integer.intValue() % 3 == 0) {
171 throw new RuntimeException("Couldn't passivate: " + integer);
172 }
173 }
174 }
175 );
176
177 Object[] obj = new Object[10];
178 for(int i=0;i<10;i++) {
179 Object object = null;
180 int k = 0;
181 while (object == null && k < 100) { // bound not really needed
182 try {
183 k++;
184 object = pool.borrowObject();
185 obj[i] = object;
186 } catch (NoSuchElementException ex) {
187 // Expected for evens, which fail validation
188 }
189 }
190 assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
191 }
192 // 1,3,5,...,19 pass validation, get checked out
193 for(int i=0;i<10;i++) {
194 pool.returnObject(obj[i]);
195 assertEquals("Each time we return, get one less active.", 9-i, pool.getNumActive());
196 }
197 // 3, 9, 15 fail passivation.
198 assertEquals(7,pool.getNumIdle());
199 assertEquals(new Integer(19), pool.borrowObject());
200 assertEquals(new Integer(17), pool.borrowObject());
201 assertEquals(new Integer(13), pool.borrowObject());
202 assertEquals(new Integer(11), pool.borrowObject());
203 assertEquals(new Integer(7), pool.borrowObject());
204 assertEquals(new Integer(5), pool.borrowObject());
205 assertEquals(new Integer(1), pool.borrowObject());
206 }
207
208 public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
209 ObjectPool pool = new StackObjectPool(20);
210
211 class TestingPoolableObjectFactory implements PoolableObjectFactory {
212 // factory makes Integer objects
213 int counter = 0;
214 boolean reject = false;
215 public Object makeObject() { return new Integer(counter++); }
216 public void destroyObject(Object obj) { }
217 public boolean validateObject(Object obj) {
218 if (reject) {
219 // only odd objects are valid
220 if(obj instanceof Integer) {
221 return ((((Integer)obj).intValue() % 2) == 1);
222 } else {
223 return false;
224 }
225 } else {
226 return true;
227 }
228
229 }
230 public void activateObject(Object obj) { }
231 public void passivateObject(Object obj) {
232 if(obj instanceof Integer) {
233 if((((Integer)obj).intValue() % 3) == 0) {
234 throw new RuntimeException("Couldn't passivate");
235 }
236 } else {
237 throw new RuntimeException("Couldn't passivate");
238 }
239 }
240 }
241
242 TestingPoolableObjectFactory factory = new TestingPoolableObjectFactory();
243
244 pool.setFactory(factory);
245
246 Object[] obj = new Object[10];
247 for(int i=0;i<10;i++) {
248 obj[i] = pool.borrowObject();
249 assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
250
251 }
252
253 // now reject even numbers
254 factory.reject = true;
255
256 for(int i=0;i<10;i++) {
257 pool.returnObject(obj[i]);
258 assertEquals("Each time we return, get one less active.", 9-i, pool.getNumActive());
259 }
260 // 0,2,4,6,8 fail validation, 3, 9 fail passivation - 3 left.
261 assertEquals(3,pool.getNumIdle());
262 }
263
264 public void testVariousConstructors() throws Exception {
265 {
266 StackObjectPool pool = new StackObjectPool();
267 assertNotNull(pool);
268 }
269 {
270 StackObjectPool pool = new StackObjectPool(10);
271 assertNotNull(pool);
272 }
273 {
274 StackObjectPool pool = new StackObjectPool(10,5);
275 assertNotNull(pool);
276 }
277 {
278 StackObjectPool pool = new StackObjectPool(null);
279 assertNotNull(pool);
280 }
281 {
282 StackObjectPool pool = new StackObjectPool(null,10);
283 assertNotNull(pool);
284 }
285 {
286 StackObjectPool pool = new StackObjectPool(null,10,5);
287 assertNotNull(pool);
288 }
289 }
290
291 private final List destroyed = new ArrayList();
292 public void testReturnObjectDiscardOrder() throws Exception {
293 // setup
294 // We need a factory that tracks what was discarded.
295 PoolableObjectFactory pof = new PoolableObjectFactory() {
296 int i = 0;
297 public Object makeObject() throws Exception {
298 return new Integer(i++);
299 }
300
301 public void destroyObject(Object obj) throws Exception {
302 destroyed.add(obj);
303 }
304
305 public boolean validateObject(Object obj) {
306 return obj instanceof Integer;
307 }
308
309 public void activateObject(Object obj) throws Exception {
310 }
311
312 public void passivateObject(Object obj) throws Exception {
313 }
314 };
315 ObjectPool pool = new StackObjectPool(pof, 3);
316
317 // borrow more objects than the pool can hold
318 Integer i0 = (Integer)pool.borrowObject();
319 Integer i1 = (Integer)pool.borrowObject();
320 Integer i2 = (Integer)pool.borrowObject();
321 Integer i3 = (Integer)pool.borrowObject();
322
323 // tests
324 // return as many as the pool will hold.
325 pool.returnObject(i0);
326 pool.returnObject(i1);
327 pool.returnObject(i2);
328
329 // the pool should now be full.
330 assertEquals("No returned objects should have been destroyed yet.",0, destroyed.size());
331
332 // cause the pool to discard a returned object.
333 pool.returnObject(i3);
334 assertEquals("One object should have been destroyed.", 1, destroyed.size());
335
336 // check to see what object was destroyed
337 Integer d = (Integer)destroyed.get(0);
338 assertEquals("Destoryed objects should have the stalest object.", i0, d);
339 }
340
341 static class SimpleFactory implements PoolableObjectFactory {
342 int counter = 0;
343 public Object makeObject() { return String.valueOf(counter++); }
344 public void destroyObject(Object obj) { }
345 public boolean validateObject(Object obj) { return true; }
346 public void activateObject(Object obj) { }
347 public void passivateObject(Object obj) { }
348 }
349
350 protected boolean isLifo() {
351 return true;
352 }
353
354 protected boolean isFifo() {
355 return false;
356 }
357 }
358