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.KeyedObjectPool; 023 import org.apache.commons.pool.KeyedPoolableObjectFactory; 024 import org.apache.commons.pool.TestBaseKeyedObjectPool; 025 import org.apache.commons.pool.VisitTracker; 026 import org.apache.commons.pool.VisitTrackerFactory; 027 028 import java.io.PrintWriter; 029 import java.io.StringWriter; 030 import java.util.HashMap; 031 import java.util.NoSuchElementException; 032 import java.util.Random; 033 034 /** 035 * @author Rodney Waldhoff 036 * @version $Revision: 791860 $ $Date: 2009-07-07 11:10:30 -0400 (Tue, 07 Jul 2009) $ 037 */ 038 public class TestGenericKeyedObjectPool extends TestBaseKeyedObjectPool { 039 public TestGenericKeyedObjectPool(String testName) { 040 super(testName); 041 } 042 043 public static Test suite() { 044 return new TestSuite(TestGenericKeyedObjectPool.class); 045 } 046 047 protected KeyedObjectPool makeEmptyPool(int mincapacity) { 048 GenericKeyedObjectPool pool = new GenericKeyedObjectPool( 049 new KeyedPoolableObjectFactory() { 050 HashMap map = new HashMap(); 051 public Object makeObject(Object key) { 052 int counter = 0; 053 Integer Counter = (Integer)(map.get(key)); 054 if(null != Counter) { 055 counter = Counter.intValue(); 056 } 057 map.put(key,new Integer(counter + 1)); 058 return String.valueOf(key) + String.valueOf(counter); 059 } 060 public void destroyObject(Object key, Object obj) { } 061 public boolean validateObject(Object key, Object obj) { return true; } 062 public void activateObject(Object key, Object obj) { } 063 public void passivateObject(Object key, Object obj) { } 064 } 065 ); 066 pool.setMaxActive(mincapacity); 067 pool.setMaxIdle(mincapacity); 068 return pool; 069 } 070 071 protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) { 072 return new GenericKeyedObjectPool(factory); 073 } 074 075 protected Object getNthObject(Object key, int n) { 076 return String.valueOf(key) + String.valueOf(n); 077 } 078 079 protected Object makeKey(int n) { 080 return String.valueOf(n); 081 } 082 083 private GenericKeyedObjectPool pool = null; 084 private final Integer zero = new Integer(0); 085 private final Integer one = new Integer(1); 086 private final Integer two = new Integer(2); 087 088 public void setUp() throws Exception { 089 super.setUp(); 090 pool = new GenericKeyedObjectPool(new SimpleFactory()); 091 } 092 093 public void tearDown() throws Exception { 094 super.tearDown(); 095 pool.clear(); 096 pool.close(); 097 pool = null; 098 } 099 100 public void testNegativeMaxActive() throws Exception { 101 pool.setMaxActive(-1); 102 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); 103 Object obj = pool.borrowObject(""); 104 assertEquals("0",obj); 105 pool.returnObject("",obj); 106 } 107 108 public void testNumActiveNumIdle2() throws Exception { 109 assertEquals(0,pool.getNumActive()); 110 assertEquals(0,pool.getNumIdle()); 111 assertEquals(0,pool.getNumActive("A")); 112 assertEquals(0,pool.getNumIdle("A")); 113 assertEquals(0,pool.getNumActive("B")); 114 assertEquals(0,pool.getNumIdle("B")); 115 116 Object objA0 = pool.borrowObject("A"); 117 Object objB0 = pool.borrowObject("B"); 118 119 assertEquals(2,pool.getNumActive()); 120 assertEquals(0,pool.getNumIdle()); 121 assertEquals(1,pool.getNumActive("A")); 122 assertEquals(0,pool.getNumIdle("A")); 123 assertEquals(1,pool.getNumActive("B")); 124 assertEquals(0,pool.getNumIdle("B")); 125 126 Object objA1 = pool.borrowObject("A"); 127 Object objB1 = pool.borrowObject("B"); 128 129 assertEquals(4,pool.getNumActive()); 130 assertEquals(0,pool.getNumIdle()); 131 assertEquals(2,pool.getNumActive("A")); 132 assertEquals(0,pool.getNumIdle("A")); 133 assertEquals(2,pool.getNumActive("B")); 134 assertEquals(0,pool.getNumIdle("B")); 135 136 pool.returnObject("A",objA0); 137 pool.returnObject("B",objB0); 138 139 assertEquals(2,pool.getNumActive()); 140 assertEquals(2,pool.getNumIdle()); 141 assertEquals(1,pool.getNumActive("A")); 142 assertEquals(1,pool.getNumIdle("A")); 143 assertEquals(1,pool.getNumActive("B")); 144 assertEquals(1,pool.getNumIdle("B")); 145 146 pool.returnObject("A",objA1); 147 pool.returnObject("B",objB1); 148 149 assertEquals(0,pool.getNumActive()); 150 assertEquals(4,pool.getNumIdle()); 151 assertEquals(0,pool.getNumActive("A")); 152 assertEquals(2,pool.getNumIdle("A")); 153 assertEquals(0,pool.getNumActive("B")); 154 assertEquals(2,pool.getNumIdle("B")); 155 } 156 157 public void testMaxIdle() throws Exception { 158 pool.setMaxActive(100); 159 pool.setMaxIdle(8); 160 Object[] active = new Object[100]; 161 for(int i=0;i<100;i++) { 162 active[i] = pool.borrowObject(""); 163 } 164 assertEquals(100,pool.getNumActive("")); 165 assertEquals(0,pool.getNumIdle("")); 166 for(int i=0;i<100;i++) { 167 pool.returnObject("",active[i]); 168 assertEquals(99 - i,pool.getNumActive("")); 169 assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("")); 170 } 171 172 for(int i=0;i<100;i++) { 173 active[i] = pool.borrowObject("a"); 174 } 175 assertEquals(100,pool.getNumActive("a")); 176 assertEquals(0,pool.getNumIdle("a")); 177 for(int i=0;i<100;i++) { 178 pool.returnObject("a",active[i]); 179 assertEquals(99 - i,pool.getNumActive("a")); 180 assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("a")); 181 } 182 183 // total number of idle instances is twice maxIdle 184 assertEquals(16, pool.getNumIdle()); 185 // Each pool is at the sup 186 assertEquals(8, pool.getNumIdle("")); 187 assertEquals(8, pool.getNumIdle("a")); 188 189 } 190 191 public void testMaxActive() throws Exception { 192 pool.setMaxActive(3); 193 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); 194 195 pool.borrowObject(""); 196 pool.borrowObject(""); 197 pool.borrowObject(""); 198 try { 199 pool.borrowObject(""); 200 fail("Expected NoSuchElementException"); 201 } catch(NoSuchElementException e) { 202 // expected 203 } 204 } 205 206 public void testMaxActiveZero() throws Exception { 207 pool.setMaxActive(0); 208 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); 209 210 try { 211 pool.borrowObject("a"); 212 fail("Expected NoSuchElementException"); 213 } catch(NoSuchElementException e) { 214 // expected 215 } 216 } 217 218 public void testWhenExhaustedGrow() throws Exception { 219 pool.setMaxActive(1); 220 pool.setMaxTotal(1); 221 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW); 222 for (int i = 0; i < 10; i++) { 223 pool.borrowObject("a"); 224 } 225 } 226 227 public void testMaxTotal() throws Exception { 228 pool.setMaxActive(2); 229 pool.setMaxTotal(3); 230 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); 231 232 Object o1 = pool.borrowObject("a"); 233 assertNotNull(o1); 234 Object o2 = pool.borrowObject("a"); 235 assertNotNull(o2); 236 Object o3 = pool.borrowObject("b"); 237 assertNotNull(o3); 238 try { 239 pool.borrowObject("c"); 240 fail("Expected NoSuchElementException"); 241 } catch(NoSuchElementException e) { 242 // expected 243 } 244 245 assertEquals(0, pool.getNumIdle()); 246 247 pool.returnObject("b", o3); 248 assertEquals(1, pool.getNumIdle()); 249 assertEquals(1, pool.getNumIdle("b")); 250 251 Object o4 = pool.borrowObject("b"); 252 assertNotNull(o4); 253 assertEquals(0, pool.getNumIdle()); 254 assertEquals(0, pool.getNumIdle("b")); 255 256 pool.setMaxTotal(4); 257 Object o5 = pool.borrowObject("b"); 258 assertNotNull(o5); 259 260 assertEquals(2, pool.getNumActive("a")); 261 assertEquals(2, pool.getNumActive("b")); 262 assertEquals(pool.getMaxTotal(), 263 pool.getNumActive("b") + pool.getNumActive("b")); 264 assertEquals(pool.getNumActive(), 265 pool.getMaxTotal()); 266 } 267 268 public void testMaxTotalZero() throws Exception { 269 pool.setMaxTotal(0); 270 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); 271 272 try { 273 pool.borrowObject("a"); 274 fail("Expected NoSuchElementException"); 275 } catch(NoSuchElementException e) { 276 // expected 277 } 278 } 279 280 public void testMaxTotalLRU() throws Exception { 281 pool.setMaxActive(2); 282 pool.setMaxTotal(3); 283 // pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW); 284 285 Object o1 = pool.borrowObject("a"); 286 assertNotNull(o1); 287 pool.returnObject("a", o1); 288 Thread.sleep(25); 289 290 Object o2 = pool.borrowObject("b"); 291 assertNotNull(o2); 292 pool.returnObject("b", o2); 293 Thread.sleep(25); 294 295 Object o3 = pool.borrowObject("c"); 296 assertNotNull(o3); 297 pool.returnObject("c", o3); 298 Thread.sleep(25); 299 300 Object o4 = pool.borrowObject("a"); 301 assertNotNull(o4); 302 pool.returnObject("a", o4); 303 Thread.sleep(25); 304 305 assertSame(o1, o4); 306 307 // this should cause b to be bumped out of the pool 308 Object o5 = pool.borrowObject("d"); 309 assertNotNull(o5); 310 pool.returnObject("d", o5); 311 Thread.sleep(25); 312 313 // now re-request b, we should get a different object because it should 314 // have been expelled from pool (was oldest because a was requested after b) 315 Object o6 = pool.borrowObject("b"); 316 assertNotNull(o6); 317 pool.returnObject("b", o6); 318 319 assertNotSame(o1, o6); 320 321 // second a is still in there 322 Object o7 = pool.borrowObject("a"); 323 assertNotNull(o7); 324 pool.returnObject("a", o7); 325 326 assertSame(o4, o7); 327 } 328 329 public void testSettersAndGetters() throws Exception { 330 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(); 331 { 332 pool.setFactory(new SimpleFactory()); 333 } 334 { 335 pool.setMaxActive(123); 336 assertEquals(123,pool.getMaxActive()); 337 } 338 { 339 pool.setMaxIdle(12); 340 assertEquals(12,pool.getMaxIdle()); 341 } 342 { 343 pool.setMaxWait(1234L); 344 assertEquals(1234L,pool.getMaxWait()); 345 } 346 { 347 pool.setMinEvictableIdleTimeMillis(12345L); 348 assertEquals(12345L,pool.getMinEvictableIdleTimeMillis()); 349 } 350 { 351 pool.setNumTestsPerEvictionRun(11); 352 assertEquals(11,pool.getNumTestsPerEvictionRun()); 353 } 354 { 355 pool.setTestOnBorrow(true); 356 assertTrue(pool.getTestOnBorrow()); 357 pool.setTestOnBorrow(false); 358 assertTrue(!pool.getTestOnBorrow()); 359 } 360 { 361 pool.setTestOnReturn(true); 362 assertTrue(pool.getTestOnReturn()); 363 pool.setTestOnReturn(false); 364 assertTrue(!pool.getTestOnReturn()); 365 } 366 { 367 pool.setTestWhileIdle(true); 368 assertTrue(pool.getTestWhileIdle()); 369 pool.setTestWhileIdle(false); 370 assertTrue(!pool.getTestWhileIdle()); 371 } 372 { 373 pool.setTimeBetweenEvictionRunsMillis(11235L); 374 assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis()); 375 } 376 { 377 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK); 378 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction()); 379 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); 380 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction()); 381 pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW); 382 assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction()); 383 } 384 } 385 386 public void testEviction() throws Exception { 387 pool.setMaxIdle(500); 388 pool.setMaxActive(500); 389 pool.setNumTestsPerEvictionRun(100); 390 pool.setMinEvictableIdleTimeMillis(250L); 391 pool.setTimeBetweenEvictionRunsMillis(500L); 392 393 Object[] active = new Object[500]; 394 for(int i=0;i<500;i++) { 395 active[i] = pool.borrowObject(""); 396 } 397 for(int i=0;i<500;i++) { 398 pool.returnObject("",active[i]); 399 } 400 401 try { Thread.sleep(1000L); } catch(InterruptedException e) { } 402 assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500); 403 try { Thread.sleep(600L); } catch(InterruptedException e) { } 404 assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400); 405 try { Thread.sleep(600L); } catch(InterruptedException e) { } 406 assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300); 407 try { Thread.sleep(600L); } catch(InterruptedException e) { } 408 assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200); 409 try { Thread.sleep(600L); } catch(InterruptedException e) { } 410 assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100); 411 try { Thread.sleep(600L); } catch(InterruptedException e) { } 412 assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle("")); 413 414 for(int i=0;i<500;i++) { 415 active[i] = pool.borrowObject(""); 416 } 417 for(int i=0;i<500;i++) { 418 pool.returnObject("",active[i]); 419 } 420 421 try { Thread.sleep(1000L); } catch(InterruptedException e) { } 422 assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500); 423 try { Thread.sleep(600L); } catch(InterruptedException e) { } 424 assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400); 425 try { Thread.sleep(600L); } catch(InterruptedException e) { } 426 assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300); 427 try { Thread.sleep(600L); } catch(InterruptedException e) { } 428 assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200); 429 try { Thread.sleep(600L); } catch(InterruptedException e) { } 430 assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100); 431 try { Thread.sleep(600L); } catch(InterruptedException e) { } 432 assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle("")); 433 } 434 435 public void testEviction2() throws Exception { 436 pool.setMaxIdle(500); 437 pool.setMaxActive(500); 438 pool.setNumTestsPerEvictionRun(100); 439 pool.setMinEvictableIdleTimeMillis(500L); 440 pool.setTimeBetweenEvictionRunsMillis(500L); 441 442 Object[] active = new Object[500]; 443 Object[] active2 = new Object[500]; 444 for(int i=0;i<500;i++) { 445 active[i] = pool.borrowObject(""); 446 active2[i] = pool.borrowObject("2"); 447 } 448 for(int i=0;i<500;i++) { 449 pool.returnObject("",active[i]); 450 pool.returnObject("2",active2[i]); 451 } 452 453 try { Thread.sleep(1100L); } catch(InterruptedException e) { } 454 assertTrue("Should be less than 1000 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 1000); 455 try { Thread.sleep(600L); } catch(InterruptedException e) { } 456 assertTrue("Should be less than 900 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 900); 457 try { Thread.sleep(600L); } catch(InterruptedException e) { } 458 assertTrue("Should be less than 800 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 800); 459 try { Thread.sleep(600L); } catch(InterruptedException e) { } 460 assertTrue("Should be less than 700 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 700); 461 try { Thread.sleep(600L); } catch(InterruptedException e) { } 462 assertTrue("Should be less than 600 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 600); 463 try { Thread.sleep(600L); } catch(InterruptedException e) { } 464 assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500); 465 try { Thread.sleep(600L); } catch(InterruptedException e) { } 466 assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400); 467 try { Thread.sleep(600L); } catch(InterruptedException e) { } 468 assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300); 469 try { Thread.sleep(600L); } catch(InterruptedException e) { } 470 assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200); 471 try { Thread.sleep(600L); } catch(InterruptedException e) { } 472 assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100); 473 try { Thread.sleep(600L); } catch(InterruptedException e) { } 474 assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle()); 475 } 476 477 /** 478 * Kicks off <numThreads> test threads, each of which will go through 479 * <iterations> borrow-return cycles with random delay times <= delay 480 * in between. 481 */ 482 public void runTestThreads(int numThreads, int iterations, int delay) { 483 TestThread[] threads = new TestThread[numThreads]; 484 for(int i=0;i<numThreads;i++) { 485 threads[i] = new TestThread(pool,iterations,delay); 486 Thread t = new Thread(threads[i]); 487 t.start(); 488 } 489 for(int i=0;i<numThreads;i++) { 490 while(!(threads[i]).complete()) { 491 try { 492 Thread.sleep(500L); 493 } catch(InterruptedException e) { 494 // ignored 495 } 496 } 497 if(threads[i].failed()) { 498 fail("Thread failed: "+i+"\n"+getExceptionTrace(threads[i]._exception)); 499 } 500 } 501 } 502 503 public void testThreaded1() throws Exception { 504 pool.setMaxActive(15); 505 pool.setMaxIdle(15); 506 pool.setMaxWait(1000L); 507 runTestThreads(20, 100, 50); 508 } 509 510 /** 511 * Verifies that maxTotal is not exceeded when factory destroyObject 512 * has high latency, testOnReturn is set and there is high incidence of 513 * validation failures. 514 */ 515 public void testMaxTotalInvariant() throws Exception { 516 int maxTotal = 15; 517 SimpleFactory factory = new SimpleFactory(); 518 factory.setEvenValid(false); // Every other validation fails 519 factory.setDestroyLatency(100); // Destroy takes 100 ms 520 factory.setMaxActive(maxTotal); // (makes - destroys) bound 521 factory.setValidationEnabled(true); 522 pool = new GenericKeyedObjectPool(factory); 523 pool.setMaxTotal(maxTotal); 524 pool.setMaxIdle(-1); 525 pool.setTestOnReturn(true); 526 pool.setMaxWait(10000L); 527 runTestThreads(5, 10, 50); 528 } 529 530 public void testMinIdle() throws Exception { 531 pool.setMaxIdle(500); 532 pool.setMinIdle(5); 533 pool.setMaxActive(10); 534 pool.setNumTestsPerEvictionRun(0); 535 pool.setMinEvictableIdleTimeMillis(50L); 536 pool.setTimeBetweenEvictionRunsMillis(100L); 537 pool.setTestWhileIdle(true); 538 539 540 //Generate a random key 541 String key = "A"; 542 543 pool.preparePool(key, true); 544 545 try { Thread.sleep(150L); } catch(InterruptedException e) { } 546 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 547 548 Object[] active = new Object[5]; 549 active[0] = pool.borrowObject(key); 550 551 try { Thread.sleep(150L); } catch(InterruptedException e) { } 552 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 553 554 for(int i=1 ; i<5 ; i++) { 555 active[i] = pool.borrowObject(key); 556 } 557 558 try { Thread.sleep(150L); } catch(InterruptedException e) { } 559 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 560 561 for(int i=0 ; i<5 ; i++) { 562 pool.returnObject(key, active[i]); 563 } 564 565 try { Thread.sleep(150L); } catch(InterruptedException e) { } 566 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); 567 } 568 569 public void testMinIdleMaxActive() throws Exception { 570 pool.setMaxIdle(500); 571 pool.setMinIdle(5); 572 pool.setMaxActive(10); 573 pool.setNumTestsPerEvictionRun(0); 574 pool.setMinEvictableIdleTimeMillis(50L); 575 pool.setTimeBetweenEvictionRunsMillis(100L); 576 pool.setTestWhileIdle(true); 577 578 String key = "A"; 579 580 pool.preparePool(key, true); 581 assertTrue("Should be 5 idle, found " + 582 pool.getNumIdle(),pool.getNumIdle() == 5); 583 584 try { Thread.sleep(150L); } catch(InterruptedException e) { } 585 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 586 587 Object[] active = new Object[10]; 588 589 try { Thread.sleep(150L); } catch(InterruptedException e) { } 590 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 591 592 for(int i=0 ; i<5 ; i++) { 593 active[i] = pool.borrowObject(key); 594 } 595 596 try { Thread.sleep(150L); } catch(InterruptedException e) { } 597 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 598 599 for(int i=0 ; i<5 ; i++) { 600 pool.returnObject(key, active[i]); 601 } 602 603 try { Thread.sleep(150L); } catch(InterruptedException e) { } 604 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); 605 606 for(int i=0 ; i<10 ; i++) { 607 active[i] = pool.borrowObject(key); 608 } 609 610 try { Thread.sleep(150L); } catch(InterruptedException e) { } 611 assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); 612 613 for(int i=0 ; i<10 ; i++) { 614 pool.returnObject(key, active[i]); 615 } 616 617 try { Thread.sleep(150L); } catch(InterruptedException e) { } 618 assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); 619 } 620 621 public void testMinIdleNoPopulateImmediately() throws Exception { 622 pool.setMaxIdle(500); 623 pool.setMinIdle(5); 624 pool.setMaxActive(10); 625 pool.setNumTestsPerEvictionRun(0); 626 pool.setMinEvictableIdleTimeMillis(50L); 627 pool.setTimeBetweenEvictionRunsMillis(1000L); 628 pool.setTestWhileIdle(true); 629 630 631 //Generate a random key 632 String key = "A"; 633 634 pool.preparePool(key, false); 635 636 assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); 637 638 try { Thread.sleep(1500L); } catch(InterruptedException e) { } 639 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 640 } 641 642 public void testMinIdleNoPreparePool() throws Exception { 643 pool.setMaxIdle(500); 644 pool.setMinIdle(5); 645 pool.setMaxActive(10); 646 pool.setNumTestsPerEvictionRun(0); 647 pool.setMinEvictableIdleTimeMillis(50L); 648 pool.setTimeBetweenEvictionRunsMillis(100L); 649 pool.setTestWhileIdle(true); 650 651 652 //Generate a random key 653 String key = "A"; 654 655 try { Thread.sleep(150L); } catch(InterruptedException e) { } 656 assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); 657 658 Object active = pool.borrowObject(key); 659 assertNotNull(active); 660 661 try { Thread.sleep(150L); } catch(InterruptedException e) { } 662 assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); 663 } 664 665 public void testFIFO() throws Exception { 666 pool.setLifo(false); 667 final Object key = "key"; 668 pool.addObject(key); // "key0" 669 pool.addObject(key); // "key1" 670 pool.addObject(key); // "key2" 671 assertEquals("Oldest", "key0", pool.borrowObject(key)); 672 assertEquals("Middle", "key1", pool.borrowObject(key)); 673 assertEquals("Youngest", "key2", pool.borrowObject(key)); 674 assertEquals("new-3", "key3", pool.borrowObject(key)); 675 pool.returnObject(key, "r"); 676 assertEquals("returned", "r", pool.borrowObject(key)); 677 assertEquals("new-4", "key4", pool.borrowObject(key)); 678 } 679 680 public void testLIFO() throws Exception { 681 pool.setLifo(true); 682 final Object key = "key"; 683 pool.addObject(key); // "key0" 684 pool.addObject(key); // "key1" 685 pool.addObject(key); // "key2" 686 assertEquals("Youngest", "key2", pool.borrowObject(key)); 687 assertEquals("Middle", "key1", pool.borrowObject(key)); 688 assertEquals("Oldest", "key0", pool.borrowObject(key)); 689 assertEquals("new-3", "key3", pool.borrowObject(key)); 690 pool.returnObject(key, "r"); 691 assertEquals("returned", "r", pool.borrowObject(key)); 692 assertEquals("new-4", "key4", pool.borrowObject(key)); 693 } 694 695 /** 696 * Test to make sure evictor visits least recently used objects first, 697 * regardless of FIFO/LIFO 698 * 699 * JIRA: POOL-86 700 */ 701 public void testEvictionOrder() throws Exception { 702 checkEvictionOrder(false); 703 checkEvictionOrder(true); 704 } 705 706 private void checkEvictionOrder(boolean lifo) throws Exception { 707 SimpleFactory factory = new SimpleFactory(); 708 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 709 pool.setNumTestsPerEvictionRun(2); 710 pool.setMinEvictableIdleTimeMillis(100); 711 pool.setLifo(lifo); 712 713 for (int i = 0; i < 3; i ++) { 714 Integer key = new Integer(i); 715 for (int j = 0; j < 5; j++) { 716 pool.addObject(key); 717 } 718 } 719 720 // Make all evictable 721 Thread.sleep(200); 722 723 /* 724 * Initial state (Key, Object) pairs in order of age: 725 * 726 * (0,0), (0,1), (0,2), (0,3), (0,4) 727 * (1,5), (1,6), (1,7), (1,8), (1,9) 728 * (2,10), (2,11), (2,12), (2,13), (2,14) 729 */ 730 731 pool.evict(); // Kill (0,0),(0,1) 732 assertEquals(3, pool.getNumIdle(zero)); 733 Object obj = pool.borrowObject(zero); 734 assertTrue(lifo ? obj.equals("04") : obj.equals("02")); 735 assertEquals(2, pool.getNumIdle(zero)); 736 obj = pool.borrowObject(zero); 737 assertTrue(obj.equals("03")); 738 assertEquals(1, pool.getNumIdle(zero)); 739 740 pool.evict(); // Kill remaining 0 survivor and (1,5) 741 assertEquals(0, pool.getNumIdle(zero)); 742 assertEquals(4, pool.getNumIdle(one)); 743 obj = pool.borrowObject(one); 744 assertTrue(lifo ? obj.equals("19") : obj.equals("16")); 745 assertEquals(3, pool.getNumIdle(one)); 746 obj = pool.borrowObject(one); 747 assertTrue(lifo ? obj.equals("18") : obj.equals("17")); 748 assertEquals(2, pool.getNumIdle(one)); 749 750 pool.evict(); // Kill remaining 1 survivors 751 assertEquals(0, pool.getNumIdle(one)); 752 pool.evict(); // Kill (2,10), (2,11) 753 assertEquals(3, pool.getNumIdle(two)); 754 obj = pool.borrowObject(two); 755 assertTrue(lifo ? obj.equals("214") : obj.equals("212")); 756 assertEquals(2, pool.getNumIdle(two)); 757 pool.evict(); // All dead now 758 assertEquals(0, pool.getNumIdle(two)); 759 760 pool.evict(); // Should do nothing - make sure no exception 761 pool.evict(); 762 763 // Reload 764 pool.setMinEvictableIdleTimeMillis(500); 765 factory.counter = 0; // Reset counter 766 for (int i = 0; i < 3; i ++) { 767 Integer key = new Integer(i); 768 for (int j = 0; j < 5; j++) { 769 pool.addObject(key); 770 } 771 Thread.sleep(200); 772 } 773 774 // 0's are evictable, others not 775 pool.evict(); // Kill (0,0),(0,1) 776 assertEquals(3, pool.getNumIdle(zero)); 777 pool.evict(); // Kill (0,2),(0,3) 778 assertEquals(1, pool.getNumIdle(zero)); 779 pool.evict(); // Kill (0,4), leave (1,5) 780 assertEquals(0, pool.getNumIdle(zero)); 781 assertEquals(5, pool.getNumIdle(one)); 782 assertEquals(5, pool.getNumIdle(two)); 783 pool.evict(); // (1,6), (1,7) 784 assertEquals(5, pool.getNumIdle(one)); 785 assertEquals(5, pool.getNumIdle(two)); 786 pool.evict(); // (1,8), (1,9) 787 assertEquals(5, pool.getNumIdle(one)); 788 assertEquals(5, pool.getNumIdle(two)); 789 pool.evict(); // (2,10), (2,11) 790 assertEquals(5, pool.getNumIdle(one)); 791 assertEquals(5, pool.getNumIdle(two)); 792 pool.evict(); // (2,12), (2,13) 793 assertEquals(5, pool.getNumIdle(one)); 794 assertEquals(5, pool.getNumIdle(two)); 795 pool.evict(); // (2,14), (1,5) 796 assertEquals(5, pool.getNumIdle(one)); 797 assertEquals(5, pool.getNumIdle(two)); 798 Thread.sleep(200); // Ones now timed out 799 pool.evict(); // kill (1,6), (1,7) - (1,5) missed 800 assertEquals(3, pool.getNumIdle(one)); 801 assertEquals(5, pool.getNumIdle(two)); 802 obj = pool.borrowObject(one); 803 assertTrue(lifo ? obj.equals("19") : obj.equals("15")); 804 } 805 806 807 /** 808 * Verifies that the evictor visits objects in expected order 809 * and frequency. 810 */ 811 public void testEvictorVisiting() throws Exception { 812 checkEvictorVisiting(true); 813 checkEvictorVisiting(false); 814 } 815 816 private void checkEvictorVisiting(boolean lifo) throws Exception { 817 VisitTrackerFactory factory = new VisitTrackerFactory(); 818 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 819 pool.setNumTestsPerEvictionRun(2); 820 pool.setMinEvictableIdleTimeMillis(-1); 821 pool.setTestWhileIdle(true); 822 pool.setLifo(lifo); 823 pool.setTestOnReturn(false); 824 pool.setTestOnBorrow(false); 825 for (int i = 0; i < 3; i ++) { 826 factory.resetId(); 827 Integer key = new Integer(i); 828 for (int j = 0; j < 8; j++) { 829 pool.addObject(key); 830 } 831 } 832 pool.evict(); // Visit oldest 2 - 00 and 01 833 Object obj = pool.borrowObject(zero); 834 pool.returnObject(zero, obj); 835 obj = pool.borrowObject(zero); 836 pool.returnObject(zero, obj); 837 // borrow, return, borrow, return 838 // FIFO will move 0 and 1 to end - 2,3,4,5,6,7,0,1 839 // LIFO, 7 out, then in, then out, then in - 7,6,5,4,3,2,1,0 840 pool.evict(); // Should visit 02 and 03 in either case 841 for (int i = 0; i < 8; i++) { 842 VisitTracker tracker = (VisitTracker) pool.borrowObject(zero); 843 if (tracker.getId() >= 4) { 844 assertEquals("Unexpected instance visited " + tracker.getId(), 845 0, tracker.getValidateCount()); 846 } else { 847 assertEquals("Instance " + tracker.getId() + 848 " visited wrong number of times.", 849 1, tracker.getValidateCount()); 850 } 851 } 852 // 0's are all out 853 854 pool.setNumTestsPerEvictionRun(3); 855 856 pool.evict(); // 10, 11, 12 857 pool.evict(); // 13, 14, 15 858 859 obj = pool.borrowObject(one); 860 pool.returnObject(one, obj); 861 obj = pool.borrowObject(one); 862 pool.returnObject(one, obj); 863 obj = pool.borrowObject(one); 864 pool.returnObject(one, obj); 865 // borrow, return, borrow, return 866 // FIFO 3,4,5,^,6,7,0,1,2 867 // LIFO 7,6,^,5,4,3,2,1,0 868 // In either case, pointer should be at 6 869 pool.evict(); 870 // LIFO - 16, 17, 20 871 // FIFO - 16, 17, 10 872 pool.evict(); 873 // LIFO - 21, 22, 23 874 // FIFO - 11, 12, 20 875 pool.evict(); 876 // LIFO - 24, 25, 26 877 // FIFO - 21, 22, 23 878 pool.evict(); 879 // LIFO - 27, skip, 10 880 // FIFO - 24, 25, 26 881 for (int i = 0; i < 8; i++) { 882 VisitTracker tracker = (VisitTracker) pool.borrowObject(one); 883 if ((lifo && tracker.getId() > 0) || 884 (!lifo && tracker.getId() > 2)) { 885 assertEquals("Instance " + tracker.getId() + 886 " visited wrong number of times.", 887 1, tracker.getValidateCount()); 888 } else { 889 assertEquals("Instance " + tracker.getId() + 890 " visited wrong number of times.", 891 2, tracker.getValidateCount()); 892 } 893 } 894 895 // Randomly generate some pools with random numTests 896 // and make sure evictor cycles through elements appropriately 897 int[] smallPrimes = {2, 3, 5, 7}; 898 Random random = new Random(); 899 random.setSeed(System.currentTimeMillis()); 900 pool.setMaxIdle(-1); 901 for (int i = 0; i < smallPrimes.length; i++) { 902 pool.setNumTestsPerEvictionRun(smallPrimes[i]); 903 for (int j = 0; j < 5; j++) {// Try the tests a few times 904 pool.clear(); 905 assertEquals("NumIdle should be zero after clearing the pool",0,pool.getNumIdle()); 906 int zeroLength = 10 + random.nextInt(20); 907 for (int k = 0; k < zeroLength; k++) { 908 pool.addObject(zero); 909 } 910 int oneLength = 10 + random.nextInt(20); 911 for (int k = 0; k < oneLength; k++) { 912 pool.addObject(one); 913 } 914 int twoLength = 10 + random.nextInt(20); 915 for (int k = 0; k < twoLength; k++) { 916 pool.addObject(two); 917 } 918 919 // Choose a random number of evictor runs 920 int runs = 10 + random.nextInt(50); 921 for (int k = 0; k < runs; k++) { 922 pool.evict(); 923 } 924 925 // Total instances in pool 926 int totalInstances = zeroLength + oneLength + twoLength; 927 928 // Number of times evictor should have cycled through pools 929 int cycleCount = (runs * pool.getNumTestsPerEvictionRun()) 930 / totalInstances; 931 932 // Look at elements and make sure they are visited cycleCount 933 // or cycleCount + 1 times 934 VisitTracker tracker = null; 935 int visitCount = 0; 936 for (int k = 0; k < zeroLength; k++) { 937 tracker = (VisitTracker) pool.borrowObject(zero); 938 visitCount = tracker.getValidateCount(); 939 if (visitCount < cycleCount || visitCount > cycleCount + 1){ 940 fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j, 941 "k", k, "visitCount", visitCount, "cycleCount", cycleCount, 942 "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); 943 } 944 } 945 for (int k = 0; k < oneLength; k++) { 946 tracker = (VisitTracker) pool.borrowObject(one); 947 visitCount = tracker.getValidateCount(); 948 if (visitCount < cycleCount || visitCount > cycleCount + 1){ 949 fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j, 950 "k", k, "visitCount", visitCount, "cycleCount", cycleCount, 951 "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); 952 } 953 } 954 int visits[] = new int[twoLength]; 955 for (int k = 0; k < twoLength; k++) { 956 tracker = (VisitTracker) pool.borrowObject(two); 957 visitCount = tracker.getValidateCount(); 958 visits[k] = visitCount; 959 if (visitCount < cycleCount || visitCount > cycleCount + 1){ 960 StringBuffer sb = new StringBuffer("Visits:"); 961 for (int l = 0; l <= k; l++){ 962 sb.append(visits[l]).append(' '); 963 } 964 fail(formatSettings("TWO "+sb.toString(), "runs", runs, "lifo", lifo, "i", i, "j", j, 965 "k", k, "visitCount", visitCount, "cycleCount", cycleCount, 966 "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); 967 } 968 } 969 } 970 } 971 } 972 973 public void testConstructors() { 974 975 // Make constructor arguments all different from defaults 976 int maxActive = 1; 977 int maxIdle = 2; 978 long maxWait = 3; 979 int minIdle = 4; 980 int maxTotal = 5; 981 long minEvictableIdleTimeMillis = 6; 982 int numTestsPerEvictionRun = 7; 983 boolean testOnBorrow = true; 984 boolean testOnReturn = true; 985 boolean testWhileIdle = true; 986 long timeBetweenEvictionRunsMillis = 8; 987 byte whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; 988 boolean lifo = false; 989 990 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(); 991 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE, pool.getMaxActive()); 992 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); 993 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait()); 994 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 995 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 996 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 997 pool.getMinEvictableIdleTimeMillis()); 998 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 999 pool.getNumTestsPerEvictionRun()); 1000 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, 1001 pool.getTestOnBorrow()); 1002 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, 1003 pool.getTestOnReturn()); 1004 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1005 pool.getTestWhileIdle()); 1006 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1007 pool.getTimeBetweenEvictionRunsMillis()); 1008 assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION, 1009 pool.getWhenExhaustedAction()); 1010 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1011 1012 GenericKeyedObjectPool.Config config = new GenericKeyedObjectPool.Config(); 1013 config.lifo = lifo; 1014 config.maxActive = maxActive; 1015 config.maxIdle = maxIdle; 1016 config.minIdle = minIdle; 1017 config.maxTotal = maxTotal; 1018 config.maxWait = maxWait; 1019 config.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 1020 config.numTestsPerEvictionRun = numTestsPerEvictionRun; 1021 config.testOnBorrow = testOnBorrow; 1022 config.testOnReturn = testOnReturn; 1023 config.testWhileIdle = testWhileIdle; 1024 config.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 1025 config.whenExhaustedAction = whenExhaustedAction; 1026 pool = new GenericKeyedObjectPool(null, config); 1027 assertEquals(maxActive, pool.getMaxActive()); 1028 assertEquals(maxIdle, pool.getMaxIdle()); 1029 assertEquals(maxWait, pool.getMaxWait()); 1030 assertEquals(minIdle, pool.getMinIdle()); 1031 assertEquals(maxTotal, pool.getMaxTotal()); 1032 assertEquals(minEvictableIdleTimeMillis, 1033 pool.getMinEvictableIdleTimeMillis()); 1034 assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); 1035 assertEquals(testOnBorrow,pool.getTestOnBorrow()); 1036 assertEquals(testOnReturn,pool.getTestOnReturn()); 1037 assertEquals(testWhileIdle,pool.getTestWhileIdle()); 1038 assertEquals(timeBetweenEvictionRunsMillis, 1039 pool.getTimeBetweenEvictionRunsMillis()); 1040 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1041 assertEquals(lifo, pool.getLifo()); 1042 1043 pool = new GenericKeyedObjectPool(null, maxActive); 1044 assertEquals(maxActive, pool.getMaxActive()); 1045 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); 1046 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait()); 1047 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1048 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1049 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 1050 pool.getMinEvictableIdleTimeMillis()); 1051 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 1052 pool.getNumTestsPerEvictionRun()); 1053 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, 1054 pool.getTestOnBorrow()); 1055 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, 1056 pool.getTestOnReturn()); 1057 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1058 pool.getTestWhileIdle()); 1059 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1060 pool.getTimeBetweenEvictionRunsMillis()); 1061 assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION, 1062 pool.getWhenExhaustedAction()); 1063 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1064 1065 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait); 1066 assertEquals(maxActive, pool.getMaxActive()); 1067 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); 1068 assertEquals(maxWait, pool.getMaxWait()); 1069 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1070 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1071 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 1072 pool.getMinEvictableIdleTimeMillis()); 1073 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 1074 pool.getNumTestsPerEvictionRun()); 1075 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, 1076 pool.getTestOnBorrow()); 1077 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, 1078 pool.getTestOnReturn()); 1079 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1080 pool.getTestWhileIdle()); 1081 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1082 pool.getTimeBetweenEvictionRunsMillis()); 1083 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1084 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1085 1086 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1087 maxWait, testOnBorrow, testOnReturn); 1088 assertEquals(maxActive, pool.getMaxActive()); 1089 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); 1090 assertEquals(maxWait, pool.getMaxWait()); 1091 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1092 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1093 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 1094 pool.getMinEvictableIdleTimeMillis()); 1095 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 1096 pool.getNumTestsPerEvictionRun()); 1097 assertEquals(testOnBorrow,pool.getTestOnBorrow()); 1098 assertEquals(testOnReturn,pool.getTestOnReturn()); 1099 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1100 pool.getTestWhileIdle()); 1101 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1102 pool.getTimeBetweenEvictionRunsMillis()); 1103 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1104 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1105 1106 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1107 maxWait, maxIdle); 1108 assertEquals(maxActive, pool.getMaxActive()); 1109 assertEquals(maxIdle, pool.getMaxIdle()); 1110 assertEquals(maxWait, pool.getMaxWait()); 1111 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1112 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1113 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 1114 pool.getMinEvictableIdleTimeMillis()); 1115 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 1116 pool.getNumTestsPerEvictionRun()); 1117 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, 1118 pool.getTestOnBorrow()); 1119 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, 1120 pool.getTestOnReturn()); 1121 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1122 pool.getTestWhileIdle()); 1123 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1124 pool.getTimeBetweenEvictionRunsMillis()); 1125 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1126 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1127 1128 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1129 maxWait, maxIdle, testOnBorrow, testOnReturn); 1130 assertEquals(maxActive, pool.getMaxActive()); 1131 assertEquals(maxIdle, pool.getMaxIdle()); 1132 assertEquals(maxWait, pool.getMaxWait()); 1133 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1134 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1135 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, 1136 pool.getMinEvictableIdleTimeMillis()); 1137 assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, 1138 pool.getNumTestsPerEvictionRun()); 1139 assertEquals(testOnBorrow, pool.getTestOnBorrow()); 1140 assertEquals(testOnReturn, pool.getTestOnReturn()); 1141 assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, 1142 pool.getTestWhileIdle()); 1143 assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, 1144 pool.getTimeBetweenEvictionRunsMillis()); 1145 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1146 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1147 1148 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1149 maxWait, maxIdle, testOnBorrow, testOnReturn, 1150 timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, 1151 minEvictableIdleTimeMillis, testWhileIdle); 1152 assertEquals(maxActive, pool.getMaxActive()); 1153 assertEquals(maxIdle, pool.getMaxIdle()); 1154 assertEquals(maxWait, pool.getMaxWait()); 1155 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1156 assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); 1157 assertEquals(minEvictableIdleTimeMillis, 1158 pool.getMinEvictableIdleTimeMillis()); 1159 assertEquals(numTestsPerEvictionRun, 1160 pool.getNumTestsPerEvictionRun()); 1161 assertEquals(testOnBorrow, pool.getTestOnBorrow()); 1162 assertEquals(testOnReturn, pool.getTestOnReturn()); 1163 assertEquals(testWhileIdle, 1164 pool.getTestWhileIdle()); 1165 assertEquals(timeBetweenEvictionRunsMillis, 1166 pool.getTimeBetweenEvictionRunsMillis()); 1167 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1168 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1169 1170 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1171 maxWait, maxIdle, maxTotal, testOnBorrow, testOnReturn, 1172 timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, 1173 minEvictableIdleTimeMillis, testWhileIdle); 1174 assertEquals(maxActive, pool.getMaxActive()); 1175 assertEquals(maxIdle, pool.getMaxIdle()); 1176 assertEquals(maxWait, pool.getMaxWait()); 1177 assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); 1178 assertEquals(maxTotal, pool.getMaxTotal()); 1179 assertEquals(minEvictableIdleTimeMillis, 1180 pool.getMinEvictableIdleTimeMillis()); 1181 assertEquals(numTestsPerEvictionRun, 1182 pool.getNumTestsPerEvictionRun()); 1183 assertEquals(testOnBorrow, pool.getTestOnBorrow()); 1184 assertEquals(testOnReturn, pool.getTestOnReturn()); 1185 assertEquals(testWhileIdle, 1186 pool.getTestWhileIdle()); 1187 assertEquals(timeBetweenEvictionRunsMillis, 1188 pool.getTimeBetweenEvictionRunsMillis()); 1189 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1190 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1191 1192 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1193 maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, 1194 timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, 1195 minEvictableIdleTimeMillis, testWhileIdle); 1196 assertEquals(maxActive, pool.getMaxActive()); 1197 assertEquals(maxIdle, pool.getMaxIdle()); 1198 assertEquals(maxWait, pool.getMaxWait()); 1199 assertEquals(minIdle, pool.getMinIdle()); 1200 assertEquals(maxTotal, pool.getMaxTotal()); 1201 assertEquals(minEvictableIdleTimeMillis, 1202 pool.getMinEvictableIdleTimeMillis()); 1203 assertEquals(numTestsPerEvictionRun, 1204 pool.getNumTestsPerEvictionRun()); 1205 assertEquals(testOnBorrow, pool.getTestOnBorrow()); 1206 assertEquals(testOnReturn, pool.getTestOnReturn()); 1207 assertEquals(testWhileIdle, 1208 pool.getTestWhileIdle()); 1209 assertEquals(timeBetweenEvictionRunsMillis, 1210 pool.getTimeBetweenEvictionRunsMillis()); 1211 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1212 assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); 1213 1214 pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, 1215 maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, 1216 timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, 1217 minEvictableIdleTimeMillis, testWhileIdle, lifo); 1218 assertEquals(maxActive, pool.getMaxActive()); 1219 assertEquals(maxIdle, pool.getMaxIdle()); 1220 assertEquals(maxWait, pool.getMaxWait()); 1221 assertEquals(minIdle, pool.getMinIdle()); 1222 assertEquals(maxTotal, pool.getMaxTotal()); 1223 assertEquals(minEvictableIdleTimeMillis, 1224 pool.getMinEvictableIdleTimeMillis()); 1225 assertEquals(numTestsPerEvictionRun, 1226 pool.getNumTestsPerEvictionRun()); 1227 assertEquals(testOnBorrow, pool.getTestOnBorrow()); 1228 assertEquals(testOnReturn, pool.getTestOnReturn()); 1229 assertEquals(testWhileIdle, 1230 pool.getTestWhileIdle()); 1231 assertEquals(timeBetweenEvictionRunsMillis, 1232 pool.getTimeBetweenEvictionRunsMillis()); 1233 assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); 1234 assertEquals(lifo, pool.getLifo()); 1235 } 1236 1237 public void testExceptionOnPassivateDuringReturn() throws Exception { 1238 SimpleFactory factory = new SimpleFactory(); 1239 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 1240 Object obj = pool.borrowObject("one"); 1241 factory.setThrowExceptionOnPassivate(true); 1242 pool.returnObject("one", obj); 1243 assertEquals(0,pool.getNumIdle()); 1244 pool.close(); 1245 } 1246 1247 public void testExceptionOnDestroyDuringBorrow() throws Exception { 1248 SimpleFactory factory = new SimpleFactory(); 1249 factory.setThrowExceptionOnDestroy(true); 1250 factory.setValidationEnabled(true); 1251 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 1252 pool.setTestOnBorrow(true); 1253 pool.borrowObject("one"); 1254 factory.setValid(false); // Make validation fail on next borrow attempt 1255 try { 1256 pool.borrowObject("one"); 1257 fail("Expecting NoSuchElementException"); 1258 } catch (NoSuchElementException ex) { 1259 // expected 1260 } 1261 assertEquals(1, pool.getNumActive("one")); 1262 assertEquals(0, pool.getNumIdle("one")); 1263 assertEquals(1, pool.getNumActive()); 1264 assertEquals(0, pool.getNumIdle()); 1265 } 1266 1267 public void testExceptionOnDestroyDuringReturn() throws Exception { 1268 SimpleFactory factory = new SimpleFactory(); 1269 factory.setThrowExceptionOnDestroy(true); 1270 factory.setValidationEnabled(true); 1271 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 1272 pool.setTestOnReturn(true); 1273 Object obj1 = pool.borrowObject("one"); 1274 pool.borrowObject("one"); 1275 factory.setValid(false); // Make validation fail 1276 pool.returnObject("one", obj1); 1277 assertEquals(1, pool.getNumActive("one")); 1278 assertEquals(0, pool.getNumIdle("one")); 1279 assertEquals(1, pool.getNumActive()); 1280 assertEquals(0, pool.getNumIdle()); 1281 } 1282 1283 public void testExceptionOnActivateDuringBorrow() throws Exception { 1284 SimpleFactory factory = new SimpleFactory(); 1285 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 1286 Object obj1 = pool.borrowObject("one"); 1287 Object obj2 = pool.borrowObject("one"); 1288 pool.returnObject("one", obj1); 1289 pool.returnObject("one", obj2); 1290 factory.setThrowExceptionOnActivate(true); 1291 factory.setEvenValid(false); 1292 // Activation will now throw every other time 1293 // First attempt throws, but loop continues and second succeeds 1294 Object obj = pool.borrowObject("one"); 1295 assertEquals(1, pool.getNumActive("one")); 1296 assertEquals(0, pool.getNumIdle("one")); 1297 assertEquals(1, pool.getNumActive()); 1298 assertEquals(0, pool.getNumIdle()); 1299 1300 pool.returnObject("one", obj); 1301 factory.setValid(false); 1302 // Validation will now fail on activation when borrowObject returns 1303 // an idle instance, and then when attempting to create a new instance 1304 try { 1305 pool.borrowObject("one"); 1306 fail("Expecting NoSuchElementException"); 1307 } catch (NoSuchElementException ex) { 1308 // expected 1309 } 1310 assertEquals(0, pool.getNumActive("one")); 1311 assertEquals(0, pool.getNumIdle("one")); 1312 assertEquals(0, pool.getNumActive()); 1313 assertEquals(0, pool.getNumIdle()); 1314 } 1315 1316 public void testBlockedKeyDoesNotBlockPool() throws Exception { 1317 SimpleFactory factory = new SimpleFactory(); 1318 GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); 1319 pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); 1320 pool.setMaxWait(5000); 1321 pool.setMaxActive(1); 1322 pool.setMaxTotal(-1); 1323 pool.borrowObject("one"); 1324 long start = System.currentTimeMillis(); 1325 // Needs to be in a separate thread as this will block 1326 Runnable simple = new SimpleTestThread(pool, "one"); 1327 (new Thread(simple)).start(); 1328 // This should be almost instant. If it isn't it means this thread got 1329 // stuck behind the thread created above which is bad. 1330 // Give other thread a chance to start 1331 Thread.sleep(1000); 1332 pool.borrowObject("two"); 1333 long end = System.currentTimeMillis(); 1334 // If it fails it will be more than 4000ms (5000 less the 1000 sleep) 1335 // If it passes it should be almost instant 1336 // Use 3000ms as the threshold - should avoid timing issues on most 1337 // (all? platforms) 1338 assertTrue ((end-start) < 4000); 1339 1340 } 1341 1342 /* 1343 * Very simple test thread that just tries to borrow an object from 1344 * the provided pool with the specified key and returns it 1345 */ 1346 static class SimpleTestThread implements Runnable { 1347 private final KeyedObjectPool _pool; 1348 private final String _key; 1349 1350 public SimpleTestThread(KeyedObjectPool pool, String key) { 1351 _pool = pool; 1352 _key = key; 1353 } 1354 1355 public void run() { 1356 try { 1357 Object obj = _pool.borrowObject(_key); 1358 _pool.returnObject(_key, obj); 1359 } catch (Exception e) { 1360 // Ignore 1361 } 1362 } 1363 } 1364 1365 static class TestThread implements Runnable { 1366 private final java.util.Random _random = new java.util.Random(); 1367 1368 // Thread config items 1369 private final KeyedObjectPool _pool; 1370 private final int _iter; 1371 private final int _delay; 1372 1373 private volatile boolean _complete = false; 1374 private volatile boolean _failed = false; 1375 private volatile Exception _exception; 1376 1377 public TestThread(KeyedObjectPool pool) { 1378 this(pool, 100, 50); 1379 } 1380 1381 public TestThread(KeyedObjectPool pool, int iter) { 1382 this(pool, iter, 50); 1383 } 1384 1385 public TestThread(KeyedObjectPool pool, int iter, int delay) { 1386 _pool = pool; 1387 _iter = iter; 1388 _delay = delay; 1389 } 1390 1391 public boolean complete() { 1392 return _complete; 1393 } 1394 1395 public boolean failed() { 1396 return _failed; 1397 } 1398 1399 public void run() { 1400 for(int i=0;i<_iter;i++) { 1401 String key = String.valueOf(_random.nextInt(3)); 1402 try { 1403 Thread.sleep(_random.nextInt(_delay)); 1404 } catch(InterruptedException e) { 1405 // ignored 1406 } 1407 Object obj = null; 1408 try { 1409 obj = _pool.borrowObject(key); 1410 } catch(Exception e) { 1411 _exception = e; 1412 _failed = true; 1413 _complete = true; 1414 break; 1415 } 1416 1417 try { 1418 Thread.sleep(_random.nextInt(_delay)); 1419 } catch(InterruptedException e) { 1420 // ignored 1421 } 1422 try { 1423 _pool.returnObject(key,obj); 1424 } catch(Exception e) { 1425 _exception = e; 1426 _failed = true; 1427 _complete = true; 1428 break; 1429 } 1430 } 1431 _complete = true; 1432 } 1433 } 1434 1435 static class SimpleFactory implements KeyedPoolableObjectFactory { 1436 public SimpleFactory() { 1437 this(true); 1438 } 1439 public SimpleFactory(boolean valid) { 1440 this.valid = valid; 1441 } 1442 public Object makeObject(Object key) { 1443 synchronized(this) { 1444 activeCount++; 1445 if (activeCount > maxActive) { 1446 throw new IllegalStateException( 1447 "Too many active instances: " + activeCount); 1448 } 1449 } 1450 return String.valueOf(key) + String.valueOf(counter++); 1451 } 1452 public void destroyObject(Object key, Object obj) throws Exception { 1453 doWait(destroyLatency); 1454 synchronized(this) { 1455 activeCount--; 1456 } 1457 if (exceptionOnDestroy) { 1458 throw new Exception(); 1459 } 1460 } 1461 public boolean validateObject(Object key, Object obj) { 1462 if (enableValidation) { 1463 return validateCounter++%2 == 0 ? evenValid : oddValid; 1464 } else { 1465 return valid; 1466 } 1467 } 1468 public void activateObject(Object key, Object obj) throws Exception { 1469 if (exceptionOnActivate) { 1470 if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) { 1471 throw new Exception(); 1472 } 1473 } 1474 } 1475 public void passivateObject(Object key, Object obj) throws Exception { 1476 if (exceptionOnPassivate) { 1477 throw new Exception(); 1478 } 1479 } 1480 1481 public void setMaxActive(int maxActive) { 1482 this.maxActive = maxActive; 1483 } 1484 public void setDestroyLatency(long destroyLatency) { 1485 this.destroyLatency = destroyLatency; 1486 } 1487 public void setValidationEnabled(boolean b) { 1488 enableValidation = b; 1489 } 1490 void setEvenValid(boolean valid) { 1491 evenValid = valid; 1492 } 1493 void setValid(boolean valid) { 1494 evenValid = valid; 1495 oddValid = valid; 1496 } 1497 1498 public void setThrowExceptionOnActivate(boolean b) { 1499 exceptionOnActivate = b; 1500 } 1501 1502 public void setThrowExceptionOnDestroy(boolean b) { 1503 exceptionOnDestroy = b; 1504 } 1505 1506 public void setThrowExceptionOnPassivate(boolean b) { 1507 exceptionOnPassivate = b; 1508 } 1509 1510 int counter = 0; 1511 boolean valid; 1512 1513 int activeCount = 0; 1514 int validateCounter = 0; 1515 boolean evenValid = true; 1516 boolean oddValid = true; 1517 boolean enableValidation = false; 1518 long destroyLatency = 0; 1519 int maxActive = Integer.MAX_VALUE; 1520 boolean exceptionOnPassivate = false; 1521 boolean exceptionOnActivate = false; 1522 boolean exceptionOnDestroy = false; 1523 1524 private void doWait(long latency) { 1525 try { 1526 Thread.sleep(latency); 1527 } catch (InterruptedException ex) { 1528 // ignore 1529 } 1530 } 1531 } 1532 1533 protected boolean isLifo() { 1534 return true; 1535 } 1536 1537 protected boolean isFifo() { 1538 return false; 1539 } 1540 1541 private String getExceptionTrace(Throwable t){ 1542 StringWriter sw = new StringWriter(); 1543 t.printStackTrace(new PrintWriter(sw)); 1544 return sw.toString(); 1545 } 1546 1547 private String formatSettings(String title, String s, int i, String s0, boolean b0, String s1, int i1, String s2, int i2, String s3, int i3, 1548 String s4, int i4, String s5, int i5, String s6, int i6, int zeroLength, int oneLength, int twoLength){ 1549 StringBuffer sb = new StringBuffer(80); 1550 sb.append(title).append(' '); 1551 sb.append(s).append('=').append(i).append(' '); 1552 sb.append(s0).append('=').append(b0).append(' '); 1553 sb.append(s1).append('=').append(i1).append(' '); 1554 sb.append(s2).append('=').append(i2).append(' '); 1555 sb.append(s3).append('=').append(i3).append(' '); 1556 sb.append(s4).append('=').append(i4).append(' '); 1557 sb.append(s5).append('=').append(i5).append(' '); 1558 sb.append(s6).append('=').append(i6).append(' '); 1559 sb.append("Lengths=").append(zeroLength).append(',').append(oneLength).append(',').append(twoLength).append(' '); 1560 return sb.toString(); 1561 } 1562 1563 } 1564 1565