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