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