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 org.apache.commons.pool.KeyedObjectPool; 025 import org.apache.commons.pool.KeyedPoolableObjectFactory; 026 import org.apache.commons.pool.TestBaseKeyedObjectPool; 027 028 /** 029 * @author Rodney Waldhoff 030 * @version $Revision: 958393 $ $Date: 2010-06-27 09:32:43 -0700 (Sun, 27 Jun 2010) $ 031 */ 032 public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool { 033 public TestStackKeyedObjectPool(String testName) { 034 super(testName); 035 } 036 037 protected KeyedObjectPool makeEmptyPool(int mincapacity) { 038 StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity); 039 return pool; 040 } 041 042 protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) { 043 return new StackKeyedObjectPool(factory); 044 } 045 046 protected Object getNthObject(Object key, int n) { 047 return String.valueOf(key) + String.valueOf(n); 048 } 049 050 protected Object makeKey(int n) { 051 return String.valueOf(n); 052 } 053 054 private StackKeyedObjectPool pool = null; 055 056 public void setUp() throws Exception { 057 super.setUp(); 058 pool = new StackKeyedObjectPool( 059 new KeyedPoolableObjectFactory() { 060 int counter = 0; 061 public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); } 062 public void destroyObject(Object key, Object obj) { } 063 public boolean validateObject(Object key, Object obj) { return true; } 064 public void activateObject(Object key, Object obj) { } 065 public void passivateObject(Object key, Object obj) { } 066 } 067 ); 068 } 069 070 071 public void tearDown() throws Exception { 072 super.tearDown(); 073 pool = null; 074 } 075 076 public void testCloseBug() throws Exception { 077 { 078 Object obj0 = pool.borrowObject(""); 079 Object obj1 = pool.borrowObject(""); 080 assertEquals(2,pool.getNumActive("")); 081 assertEquals(0,pool.getNumIdle("")); 082 pool.returnObject("",obj1); 083 pool.returnObject("",obj0); 084 assertEquals(0,pool.getNumActive("")); 085 assertEquals(2,pool.getNumIdle("")); 086 } 087 { 088 Object obj0 = pool.borrowObject("2"); 089 Object obj1 = pool.borrowObject("2"); 090 assertEquals(2,pool.getNumActive("2")); 091 assertEquals(0,pool.getNumIdle("2")); 092 pool.returnObject("2",obj1); 093 pool.returnObject("2",obj0); 094 assertEquals(0,pool.getNumActive("2")); 095 assertEquals(2,pool.getNumIdle("2")); 096 } 097 pool.close(); 098 } 099 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 }