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; 019 020 import junit.framework.TestCase; 021 import junit.framework.AssertionFailedError; 022 import junit.framework.Test; 023 import junit.framework.TestSuite; 024 025 import java.lang.reflect.Proxy; 026 import java.lang.reflect.InvocationHandler; 027 import java.lang.reflect.Method; 028 import java.util.List; 029 import java.util.ArrayList; 030 import java.util.Set; 031 import java.util.HashSet; 032 import java.util.TimerTask; 033 import java.util.Collection; 034 import java.util.Map; 035 import java.util.Iterator; 036 import java.util.Arrays; 037 038 import org.apache.commons.pool.impl.GenericObjectPool; 039 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 040 041 /** 042 * Unit tests for {@link PoolUtils}. 043 * 044 * @author Sandy McArthur 045 * @version $Revision: 780290 $ $Date: 2009-05-30 11:51:37 -0400 (Sat, 30 May 2009) $ 046 */ 047 public class TestPoolUtils extends TestCase { 048 049 /** Period between checks for minIdle tests. Increase this if you happen to get too many false failures. */ 050 private static final int CHECK_PERIOD = 300; 051 052 /** Times to let the minIdle check run. */ 053 private static final int CHECK_COUNT = 4; 054 055 /** Sleep time to let the minIdle tests run CHECK_COUNT times. */ 056 private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT - 1) + CHECK_PERIOD / 2; 057 058 public static Test suite() { 059 return new TestSuite(TestPoolUtils.class); 060 } 061 062 public void testJavaBeanInstantiation() { 063 new PoolUtils(); 064 } 065 066 public void testAdaptKeyedPoolableObjectFactory() throws Exception { 067 try { 068 PoolUtils.adapt((KeyedPoolableObjectFactory)null); 069 fail("PoolUtils.adapt(KeyedPoolableObjectFactory) must not allow null factory."); 070 } catch (IllegalArgumentException iae) { 071 // expected 072 } 073 } 074 075 public void testAdaptKeyedPoolableObjectFactoryKey() throws Exception { 076 try { 077 PoolUtils.adapt((KeyedPoolableObjectFactory)null, new Object()); 078 fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null factory."); 079 } catch (IllegalArgumentException iae) { 080 // expected 081 } 082 try { 083 PoolUtils.adapt((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, (List)null), null); 084 fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null key."); 085 } catch (IllegalArgumentException iae) { 086 // expected 087 } 088 089 final List calledMethods = new ArrayList(); 090 final KeyedPoolableObjectFactory kpof = 091 (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods); 092 093 final PoolableObjectFactory pof = PoolUtils.adapt(kpof); 094 final List expectedMethods = invokeEveryMethod(pof); 095 assertEquals(expectedMethods, calledMethods); 096 } 097 098 public void testAdaptPoolableObjectFactory() throws Exception { 099 try { 100 PoolUtils.adapt((PoolableObjectFactory)null); 101 fail("PoolUtils.adapt(PoolableObjectFactory) must not allow null factory."); 102 } catch (IllegalArgumentException iae) { 103 // expected 104 } 105 106 final List calledMethods = new ArrayList(); 107 final PoolableObjectFactory pof = 108 (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods); 109 110 final KeyedPoolableObjectFactory kpof = PoolUtils.adapt(pof); 111 final List expectedMethods = invokeEveryMethod(kpof); 112 assertEquals(expectedMethods, calledMethods); 113 } 114 115 public void testAdaptKeyedObjectPool() throws Exception { 116 try { 117 PoolUtils.adapt((KeyedObjectPool)null); 118 fail("PoolUtils.adapt(KeyedObjectPool) must not allow a null pool."); 119 } catch(IllegalArgumentException iae) { 120 // expected 121 } 122 } 123 124 public void testAdaptKeyedObjectPoolKey() throws Exception { 125 try { 126 PoolUtils.adapt((KeyedObjectPool)null, new Object()); 127 fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null pool."); 128 } catch(IllegalArgumentException iae) { 129 // expected 130 } 131 try { 132 PoolUtils.adapt((KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null), null); 133 fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null key."); 134 } catch(IllegalArgumentException iae) { 135 // expected 136 } 137 138 final List calledMethods = new ArrayList(); 139 final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 140 141 final ObjectPool op = PoolUtils.adapt(kop, new Object()); 142 final List expectedMethods = invokeEveryMethod(op); 143 assertEquals(expectedMethods, calledMethods); 144 } 145 146 public void testAdaptObjectPool() throws Exception { 147 try { 148 PoolUtils.adapt((ObjectPool)null); 149 fail("PoolUtils.adapt(ObjectPool) must not allow a null pool."); 150 } catch(IllegalArgumentException iae) { 151 // expected 152 } 153 154 final List calledMethods = new ArrayList(); 155 final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods); 156 157 final KeyedObjectPool kop = PoolUtils.adapt(op); 158 final List expectedMethods = invokeEveryMethod(kop); 159 assertEquals(expectedMethods, calledMethods); 160 } 161 162 public void testCheckedPoolObjectPool() throws Exception { 163 try { 164 PoolUtils.checkedPool((ObjectPool)null, Object.class); 165 fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null pool."); 166 } catch(IllegalArgumentException iae) { 167 // expected 168 } 169 try { 170 PoolUtils.checkedPool((ObjectPool)createProxy(ObjectPool.class, (List)null), null); 171 fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null type."); 172 } catch(IllegalArgumentException iae) { 173 // expected 174 } 175 176 final List calledMethods = new ArrayList(); 177 ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods); 178 179 ObjectPool cop = PoolUtils.checkedPool(op, Object.class); 180 final List expectedMethods = invokeEveryMethod(cop); 181 assertEquals(expectedMethods, calledMethods); 182 183 op = new BaseObjectPool() { 184 public Object borrowObject() throws Exception { 185 return new Integer(0); 186 } 187 public void returnObject(Object obj) {} 188 public void invalidateObject(Object obj) {} 189 }; 190 cop = PoolUtils.checkedPool(op, String.class); 191 192 try { 193 cop.borrowObject(); 194 fail("borrowObject should have failed as Integer !instanceof String."); 195 } catch (ClassCastException cce) { 196 // expected 197 } 198 try { 199 cop.returnObject(new Integer(1)); 200 fail("returnObject should have failed as Integer !instanceof String."); 201 } catch (ClassCastException cce) { 202 // expected 203 } 204 try { 205 cop.invalidateObject(new Integer(2)); 206 fail("invalidateObject should have failed as Integer !instanceof String."); 207 } catch (ClassCastException cce) { 208 // expected 209 } 210 } 211 212 public void testCheckedPoolKeyedObjectPool() throws Exception { 213 try { 214 PoolUtils.checkedPool((KeyedObjectPool)null, Object.class); 215 fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null pool."); 216 } catch(IllegalArgumentException iae) { 217 // expected 218 } 219 try { 220 PoolUtils.checkedPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null), null); 221 fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null type."); 222 } catch(IllegalArgumentException iae) { 223 // expected 224 } 225 226 final List calledMethods = new ArrayList(); 227 KeyedObjectPool op = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 228 229 KeyedObjectPool cop = PoolUtils.checkedPool(op, Object.class); 230 final List expectedMethods = invokeEveryMethod(cop); 231 assertEquals(expectedMethods, calledMethods); 232 233 234 op = new BaseKeyedObjectPool() { 235 public Object borrowObject(Object key) { 236 return new Integer(0); 237 } 238 239 public void returnObject(Object key, Object obj) {} 240 241 public void invalidateObject(Object key, Object obj) {} 242 }; 243 cop = PoolUtils.checkedPool(op, String.class); 244 245 try { 246 cop.borrowObject(null); 247 fail("borrowObject should have failed as Integer !instanceof String."); 248 } catch (ClassCastException cce) { 249 // expected 250 } 251 try { 252 cop.returnObject(null, new Integer(1)); 253 fail("returnObject should have failed as Integer !instanceof String."); 254 } catch (ClassCastException cce) { 255 // expected 256 } 257 try { 258 cop.invalidateObject(null, new Integer(2)); 259 fail("invalidateObject should have failed as Integer !instanceof String."); 260 } catch (ClassCastException cce) { 261 // expected 262 } 263 } 264 265 public void testCheckMinIdleObjectPool() throws Exception { 266 try { 267 PoolUtils.checkMinIdle(null, 1, 1); 268 fail("PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool."); 269 } catch (IllegalArgumentException iae) { 270 // expected 271 } 272 try { 273 final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, (List)null); 274 PoolUtils.checkMinIdle(pool, -1, 1); 275 fail("PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values."); 276 } catch (IllegalArgumentException iae) { 277 // expected 278 } 279 280 final List calledMethods = new ArrayList(); 281 282 // Test that the minIdle check doesn't add too many idle objects 283 final PoolableObjectFactory pof = (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods); 284 final ObjectPool op = new GenericObjectPool(pof); 285 PoolUtils.checkMinIdle(op, 2, 100); 286 Thread.sleep(400); 287 assertEquals(2, op.getNumIdle()); 288 op.close(); 289 int makeObjectCount = 0; 290 final Iterator iter = calledMethods.iterator(); 291 while (iter.hasNext()) { 292 final String methodName = (String)iter.next(); 293 if ("makeObject".equals(methodName)) { 294 makeObjectCount++; 295 } 296 } 297 assertEquals("makeObject should have been called two time", 2, makeObjectCount); 298 299 // Because this isn't deterministic and you can get false failures, try more than once. 300 AssertionFailedError afe = null; 301 int triesLeft = 3; 302 do { 303 afe = null; 304 try { 305 calledMethods.clear(); 306 final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods); 307 final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately 308 309 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. 310 task.cancel(); 311 task.toString(); 312 313 final List expectedMethods = new ArrayList(); 314 for (int i=0; i < CHECK_COUNT; i++) { 315 expectedMethods.add("getNumIdle"); 316 expectedMethods.add("addObject"); 317 } 318 expectedMethods.add("toString"); 319 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler 320 } catch (AssertionFailedError e) { 321 afe = e; 322 } 323 } while (--triesLeft > 0 && afe != null); 324 if (afe != null) { 325 throw afe; 326 } 327 } 328 329 public void testCheckMinIdleKeyedObjectPool() throws Exception { 330 try { 331 PoolUtils.checkMinIdle(null, new Object(), 1, 1); 332 fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool."); 333 } catch (IllegalArgumentException iae) { 334 // expected 335 } 336 try { 337 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null); 338 PoolUtils.checkMinIdle(pool, (Object)null, 1, 1); 339 fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys."); 340 } catch (IllegalArgumentException iae) { 341 // expected 342 } 343 try { 344 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null); 345 PoolUtils.checkMinIdle(pool, new Object(), -1, 1); 346 fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values."); 347 } catch (IllegalArgumentException iae) { 348 // expected 349 } 350 351 final List calledMethods = new ArrayList(); 352 final Object key = new Object(); 353 354 // Test that the minIdle check doesn't add too many idle objects 355 final KeyedPoolableObjectFactory kpof = (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods); 356 final KeyedObjectPool kop = new GenericKeyedObjectPool(kpof); 357 PoolUtils.checkMinIdle(kop, key, 2, 100); 358 Thread.sleep(400); 359 assertEquals(2, kop.getNumIdle(key)); 360 assertEquals(2, kop.getNumIdle()); 361 kop.close(); 362 int makeObjectCount = 0; 363 final Iterator iter = calledMethods.iterator(); 364 while (iter.hasNext()) { 365 final String methodName = (String)iter.next(); 366 if ("makeObject".equals(methodName)) { 367 makeObjectCount++; 368 } 369 } 370 assertEquals("makeObject should have been called two time", 2, makeObjectCount); 371 372 // Because this isn't deterministic and you can get false failures, try more than once. 373 AssertionFailedError afe = null; 374 int triesLeft = 3; 375 do { 376 afe = null; 377 try { 378 calledMethods.clear(); 379 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 380 final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD); // checks minIdle immediately 381 382 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. 383 task.cancel(); 384 task.toString(); 385 386 final List expectedMethods = new ArrayList(); 387 for (int i=0; i < CHECK_COUNT; i++) { 388 expectedMethods.add("getNumIdle"); 389 expectedMethods.add("addObject"); 390 } 391 expectedMethods.add("toString"); 392 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler 393 } catch (AssertionFailedError e) { 394 afe = e; 395 } 396 } while (--triesLeft > 0 && afe != null); 397 if (afe != null) { 398 throw afe; 399 } 400 } 401 402 public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception { 403 try { 404 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null); 405 PoolUtils.checkMinIdle(pool, null, 1, 1); 406 fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys."); 407 } catch (IllegalArgumentException iae) { 408 // expected 409 } 410 411 // Because this isn't determinist and you can get false failures, try more than once. 412 AssertionFailedError afe = null; 413 int triesLeft = 3; 414 do { 415 afe = null; 416 try { 417 final List calledMethods = new ArrayList(); 418 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 419 final Collection keys = new ArrayList(2); 420 keys.add("one"); 421 keys.add("two"); 422 final Map tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD); // checks minIdle immediately 423 424 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. 425 final Iterator iter = tasks.values().iterator(); 426 while (iter.hasNext()) { 427 final TimerTask task = (TimerTask)iter.next(); 428 task.cancel(); 429 } 430 431 final List expectedMethods = new ArrayList(); 432 for (int i=0; i < CHECK_COUNT * keys.size(); i++) { 433 expectedMethods.add("getNumIdle"); 434 expectedMethods.add("addObject"); 435 } 436 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler 437 } catch (AssertionFailedError e) { 438 afe = e; 439 } 440 } while (--triesLeft > 0 && afe != null); 441 if (afe != null) { 442 throw afe; 443 } 444 } 445 446 public void testPrefillObjectPool() throws Exception { 447 try { 448 PoolUtils.prefill(null, 1); 449 fail("PoolUtils.prefill(ObjectPool,int) must not allow null pool."); 450 } catch (IllegalArgumentException iae) { 451 // expected 452 } 453 454 final List calledMethods = new ArrayList(); 455 final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods); 456 457 PoolUtils.prefill(pool, 0); 458 final List expectedMethods = new ArrayList(); 459 assertEquals(expectedMethods, calledMethods); 460 461 calledMethods.clear(); 462 PoolUtils.prefill(pool, 3); 463 for (int i=0; i < 3; i++) { 464 expectedMethods.add("addObject"); 465 } 466 assertEquals(expectedMethods, calledMethods); 467 } 468 469 public void testPrefillKeyedObjectPool() throws Exception { 470 try { 471 PoolUtils.prefill(null, new Object(), 1); 472 fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool."); 473 } catch (IllegalArgumentException iae) { 474 // expected 475 } 476 try { 477 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null); 478 PoolUtils.prefill(pool, (Object)null, 1); 479 fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key."); 480 } catch (IllegalArgumentException iae) { 481 // expected 482 } 483 484 final List calledMethods = new ArrayList(); 485 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 486 487 PoolUtils.prefill(pool, new Object(), 0); 488 final List expectedMethods = new ArrayList(); 489 assertEquals(expectedMethods, calledMethods); 490 491 calledMethods.clear(); 492 PoolUtils.prefill(pool, new Object(), 3); 493 for (int i=0; i < 3; i++) { 494 expectedMethods.add("addObject"); 495 } 496 assertEquals(expectedMethods, calledMethods); 497 } 498 499 public void testPrefillKeyedObjectPoolCollection() throws Exception { 500 try { 501 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null); 502 PoolUtils.prefill(pool, null, 1); 503 fail("PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys."); 504 } catch (IllegalArgumentException iae) { 505 // expected 506 } 507 508 final List calledMethods = new ArrayList(); 509 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 510 511 final Set keys = new HashSet(); 512 PoolUtils.prefill(pool, keys, 0); 513 final List expectedMethods = new ArrayList(); 514 assertEquals(expectedMethods, calledMethods); 515 516 calledMethods.clear(); 517 keys.add(new Integer(1)); 518 keys.add("two"); 519 keys.add(new Double(3.1415926)); 520 PoolUtils.prefill(pool, keys, 3); 521 for (int i=0; i < keys.size() * 3; i++) { 522 expectedMethods.add("addObject"); 523 } 524 assertEquals(expectedMethods, calledMethods); 525 } 526 527 public void testSynchronizedPoolObjectPool() throws Exception { 528 try { 529 PoolUtils.synchronizedPool((ObjectPool)null); 530 fail("PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool."); 531 } catch(IllegalArgumentException iae) { 532 // expected 533 } 534 535 final List calledMethods = new ArrayList(); 536 final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods); 537 538 final ObjectPool sop = PoolUtils.synchronizedPool(op); 539 final List expectedMethods = invokeEveryMethod(sop); 540 assertEquals(expectedMethods, calledMethods); 541 542 // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? 543 } 544 545 public void testSynchronizedPoolKeyedObjectPool() throws Exception { 546 try { 547 PoolUtils.synchronizedPool((KeyedObjectPool)null); 548 fail("PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool."); 549 } catch(IllegalArgumentException iae) { 550 // expected 551 } 552 553 final List calledMethods = new ArrayList(); 554 final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods); 555 556 final KeyedObjectPool skop = PoolUtils.synchronizedPool(kop); 557 final List expectedMethods = invokeEveryMethod(skop); 558 assertEquals(expectedMethods, calledMethods); 559 560 // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? 561 } 562 563 public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception { 564 try { 565 PoolUtils.synchronizedPoolableFactory((PoolableObjectFactory)null); 566 fail("PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory."); 567 } catch(IllegalArgumentException iae) { 568 // expected 569 } 570 571 final List calledMethods = new ArrayList(); 572 final PoolableObjectFactory pof = 573 (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods); 574 575 final PoolableObjectFactory spof = PoolUtils.synchronizedPoolableFactory(pof); 576 final List expectedMethods = invokeEveryMethod(spof); 577 assertEquals(expectedMethods, calledMethods); 578 579 // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? 580 } 581 582 public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() throws Exception { 583 try { 584 PoolUtils.synchronizedPoolableFactory((KeyedPoolableObjectFactory)null); 585 fail("PoolUtils.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not allow a null factory."); 586 } catch(IllegalArgumentException iae) { 587 // expected 588 } 589 590 final List calledMethods = new ArrayList(); 591 final KeyedPoolableObjectFactory kpof = 592 (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods); 593 594 final KeyedPoolableObjectFactory skpof = PoolUtils.synchronizedPoolableFactory(kpof); 595 final List expectedMethods = invokeEveryMethod(skpof); 596 assertEquals(expectedMethods, calledMethods); 597 598 // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? 599 } 600 601 public void testErodingPoolObjectPool() throws Exception { 602 try { 603 PoolUtils.erodingPool((ObjectPool)null); 604 fail("PoolUtils.erodingPool(ObjectPool) must not allow a null pool."); 605 } catch(IllegalArgumentException iae) { 606 // expected 607 } 608 609 try { 610 PoolUtils.erodingPool((ObjectPool)null, 1f); 611 fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a null pool."); 612 } catch(IllegalArgumentException iae) { 613 // expected 614 } 615 616 try { 617 PoolUtils.erodingPool((ObjectPool)null, 0); 618 fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); 619 } catch(IllegalArgumentException iae) { 620 // expected 621 } 622 623 final List calledMethods = new ArrayList(); 624 final InvocationHandler handler = new MethodCallLogger(calledMethods) { 625 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 626 Object o = super.invoke(proxy, method, args); 627 if (o instanceof Integer) { 628 // so getNumActive/getNumIdle are not zero. 629 o = new Integer(1); 630 } 631 return o; 632 } 633 }; 634 635 // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. 636 float factor = 0.01f; // about ~9 seconds until first discard 637 final ObjectPool pool = PoolUtils.erodingPool((ObjectPool)createProxy(ObjectPool.class, handler), factor); 638 639 final List expectedMethods = new ArrayList(); 640 assertEquals(expectedMethods, calledMethods); 641 642 Object o = pool.borrowObject(); 643 expectedMethods.add("borrowObject"); 644 645 assertEquals(expectedMethods, calledMethods); 646 647 pool.returnObject(o); 648 expectedMethods.add("returnObject"); 649 assertEquals(expectedMethods, calledMethods); 650 651 for (int i=0; i < 5; i ++) { 652 o = pool.borrowObject(); 653 expectedMethods.add("borrowObject"); 654 655 Thread.sleep(50); 656 657 pool.returnObject(o); 658 expectedMethods.add("returnObject"); 659 660 assertEquals(expectedMethods, calledMethods); 661 662 expectedMethods.clear(); 663 calledMethods.clear(); 664 } 665 666 Thread.sleep(10000); // 10 seconds 667 668 669 o = pool.borrowObject(); 670 expectedMethods.add("borrowObject"); 671 pool.returnObject(o); 672 expectedMethods.add("getNumIdle"); 673 expectedMethods.add("invalidateObject"); 674 assertEquals(expectedMethods, calledMethods); 675 } 676 677 public void testErodingPoolKeyedObjectPool() throws Exception { 678 try { 679 PoolUtils.erodingPool((KeyedObjectPool)null); 680 fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); 681 } catch(IllegalArgumentException iae) { 682 // expected 683 } 684 685 try { 686 PoolUtils.erodingPool((KeyedObjectPool)null, 1f); 687 fail("PoolUtils.erodingPool(KeyedObjectPool, float) must not allow a null pool."); 688 } catch(IllegalArgumentException iae) { 689 // expected 690 } 691 692 try { 693 PoolUtils.erodingPool((KeyedObjectPool)null, 0); 694 fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); 695 } catch(IllegalArgumentException iae) { 696 // expected 697 } 698 699 try { 700 PoolUtils.erodingPool((KeyedObjectPool)null, 1f, true); 701 fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool."); 702 } catch(IllegalArgumentException iae) { 703 // expected 704 } 705 706 try { 707 PoolUtils.erodingPool((KeyedObjectPool)null, 0, false); 708 fail("PoolUtils.erodingPool(ObjectPool, float, boolean) must not allow a non-positive factor."); 709 } catch(IllegalArgumentException iae) { 710 // expected 711 } 712 713 final List calledMethods = new ArrayList(); 714 final InvocationHandler handler = new MethodCallLogger(calledMethods) { 715 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 716 Object o = super.invoke(proxy, method, args); 717 if (o instanceof Integer) { 718 // so getNumActive/getNumIdle are not zero. 719 o = new Integer(1); 720 } 721 return o; 722 } 723 }; 724 725 // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. 726 float factor = 0.01f; // about ~9 seconds until first discard 727 final KeyedObjectPool pool = PoolUtils.erodingPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, handler), factor); 728 729 final List expectedMethods = new ArrayList(); 730 assertEquals(expectedMethods, calledMethods); 731 732 final Object key = "key"; 733 734 Object o = pool.borrowObject(key); 735 expectedMethods.add("borrowObject"); 736 737 assertEquals(expectedMethods, calledMethods); 738 739 pool.returnObject(key, o); 740 expectedMethods.add("returnObject"); 741 assertEquals(expectedMethods, calledMethods); 742 743 for (int i=0; i < 5; i ++) { 744 o = pool.borrowObject(key); 745 expectedMethods.add("borrowObject"); 746 747 Thread.sleep(50); 748 749 pool.returnObject(key, o); 750 expectedMethods.add("returnObject"); 751 752 assertEquals(expectedMethods, calledMethods); 753 754 expectedMethods.clear(); 755 calledMethods.clear(); 756 } 757 758 Thread.sleep(10000); // 10 seconds 759 760 761 o = pool.borrowObject(key); 762 expectedMethods.add("borrowObject"); 763 pool.returnObject(key, o); 764 expectedMethods.add("getNumIdle"); 765 expectedMethods.add("invalidateObject"); 766 assertEquals(expectedMethods, calledMethods); 767 } 768 769 public void testErodingPerKeyKeyedObjectPool() throws Exception { 770 try { 771 PoolUtils.erodingPool((KeyedObjectPool)null, 1, true); 772 fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); 773 } catch(IllegalArgumentException iae) { 774 // expected 775 } 776 777 try { 778 PoolUtils.erodingPool((KeyedObjectPool)null, 0, true); 779 fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); 780 } catch(IllegalArgumentException iae) { 781 // expected 782 } 783 784 try { 785 PoolUtils.erodingPool((KeyedObjectPool)null, 1f, true); 786 fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool."); 787 } catch(IllegalArgumentException iae) { 788 // expected 789 } 790 791 final List calledMethods = new ArrayList(); 792 final InvocationHandler handler = new MethodCallLogger(calledMethods) { 793 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 794 Object o = super.invoke(proxy, method, args); 795 if (o instanceof Integer) { 796 // so getNumActive/getNumIdle are not zero. 797 o = new Integer(1); 798 } 799 return o; 800 } 801 }; 802 803 // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. 804 float factor = 0.01f; // about ~9 seconds until first discard 805 final KeyedObjectPool pool = PoolUtils.erodingPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, handler), factor, true); 806 807 final List expectedMethods = new ArrayList(); 808 assertEquals(expectedMethods, calledMethods); 809 810 final Object key = "key"; 811 812 Object o = pool.borrowObject(key); 813 expectedMethods.add("borrowObject"); 814 815 assertEquals(expectedMethods, calledMethods); 816 817 pool.returnObject(key, o); 818 expectedMethods.add("returnObject"); 819 assertEquals(expectedMethods, calledMethods); 820 821 for (int i=0; i < 5; i ++) { 822 o = pool.borrowObject(key); 823 expectedMethods.add("borrowObject"); 824 825 Thread.sleep(50); 826 827 pool.returnObject(key, o); 828 expectedMethods.add("returnObject"); 829 830 assertEquals(expectedMethods, calledMethods); 831 832 expectedMethods.clear(); 833 calledMethods.clear(); 834 } 835 836 Thread.sleep(10000); // 10 seconds 837 838 839 o = pool.borrowObject(key); 840 expectedMethods.add("borrowObject"); 841 pool.returnObject(key, o); 842 expectedMethods.add("getNumIdle"); 843 expectedMethods.add("invalidateObject"); 844 assertEquals(expectedMethods, calledMethods); 845 } 846 847 private static List invokeEveryMethod(ObjectPool op) throws Exception { 848 op.addObject(); 849 op.borrowObject(); 850 op.clear(); 851 op.close(); 852 op.getNumActive(); 853 op.getNumIdle(); 854 op.invalidateObject(new Object()); 855 op.returnObject(new Object()); 856 op.setFactory((PoolableObjectFactory)createProxy(PoolableObjectFactory.class, (List)null)); 857 op.toString(); 858 859 final List expectedMethods = Arrays.asList(new String[] { 860 "addObject", "borrowObject", "clear", "close", 861 "getNumActive", "getNumIdle", "invalidateObject", 862 "returnObject", "setFactory", "toString" 863 }); 864 return expectedMethods; 865 } 866 867 private static List invokeEveryMethod(KeyedObjectPool kop) throws Exception { 868 kop.addObject(null); 869 kop.borrowObject(null); 870 kop.clear(); 871 kop.clear(null); 872 kop.close(); 873 kop.getNumActive(); 874 kop.getNumActive(null); 875 kop.getNumIdle(); 876 kop.getNumIdle(null); 877 kop.invalidateObject(null, new Object()); 878 kop.returnObject(null, new Object()); 879 kop.setFactory((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, (List)null)); 880 kop.toString(); 881 882 final List expectedMethods = Arrays.asList(new String[] { 883 "addObject", "borrowObject", "clear", "clear", "close", 884 "getNumActive", "getNumActive", "getNumIdle", "getNumIdle", "invalidateObject", 885 "returnObject", "setFactory", "toString" 886 }); 887 return expectedMethods; 888 } 889 890 private static List invokeEveryMethod(PoolableObjectFactory pof) throws Exception { 891 pof.activateObject(null); 892 pof.destroyObject(null); 893 pof.makeObject(); 894 pof.passivateObject(null); 895 pof.validateObject(null); 896 pof.toString(); 897 898 final List expectedMethods = Arrays.asList(new String[] { 899 "activateObject", "destroyObject", "makeObject", 900 "passivateObject", "validateObject", "toString", 901 }); 902 return expectedMethods; 903 } 904 905 private static List invokeEveryMethod(KeyedPoolableObjectFactory kpof) throws Exception { 906 kpof.activateObject(null, null); 907 kpof.destroyObject(null, null); 908 kpof.makeObject(null); 909 kpof.passivateObject(null, null); 910 kpof.validateObject(null, null); 911 kpof.toString(); 912 913 final List expectedMethods = Arrays.asList(new String[] { 914 "activateObject", "destroyObject", "makeObject", 915 "passivateObject", "validateObject", "toString", 916 }); 917 return expectedMethods; 918 } 919 920 private static Object createProxy(final Class clazz, final List logger) { 921 return createProxy(clazz, new MethodCallLogger(logger)); 922 } 923 924 private static Object createProxy(final Class clazz, final InvocationHandler handler) { 925 return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler); 926 } 927 928 private static class MethodCallLogger implements InvocationHandler { 929 private final List calledMethods; 930 931 MethodCallLogger(final List calledMethods) { 932 this.calledMethods = calledMethods; 933 } 934 935 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 936 calledMethods.add(method.getName()); 937 if (boolean.class.equals(method.getReturnType())) { 938 return Boolean.FALSE; 939 } else if (int.class.equals(method.getReturnType())) { 940 return new Integer(0); 941 } else if (long.class.equals(method.getReturnType())) { 942 return new Long(0); 943 } else if (Object.class.equals(method.getReturnType())) { 944 return new Object(); 945 } else { 946 return null; 947 } 948 } 949 } 950 }