/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.pool.impl;
import java.util.BitSet;
import java.util.HashMap;
import java.util.NoSuchElementException;
import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.apache.commons.pool.TestBaseKeyedObjectPool;
/**
* @author Rodney Waldhoff
* @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $
*/
public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool<String, String> {
public TestStackKeyedObjectPool(String testName) {
super(testName);
}
@Override
protected KeyedObjectPool<String, String> makeEmptyPool(int mincapacity) {
StackKeyedObjectPool<String, String> pool = new StackKeyedObjectPool<String, String>(new SimpleFactory(),mincapacity);
return pool;
}
@Override
protected KeyedObjectPool<Object, Integer> makeEmptyPool(KeyedPoolableObjectFactory<Object, Integer> factory) {
return new StackKeyedObjectPool<Object, Integer>(factory);
}
@Override
protected String getNthObject(Object key, int n) {
return String.valueOf(key) + String.valueOf(n);
}
@Override
protected String makeKey(int n) {
return String.valueOf(n);
}
private StackKeyedObjectPool<String, String> pool = null;
@Override
public void setUp() throws Exception {
super.setUp();
pool = new StackKeyedObjectPool<String, String>(
new KeyedPoolableObjectFactory<String, String>() {
int counter = 0;
public String makeObject(String key) { return String.valueOf(key) + String.valueOf(counter++); }
public void destroyObject(String key, String obj) { }
public boolean validateObject(String key, String obj) { return true; }
public void activateObject(String key, String obj) { }
public void passivateObject(String key, String obj) { }
}
);
}
@Override
public void tearDown() throws Exception {
super.tearDown();
pool = null;
}
public void testCloseBug() throws Exception {
{
String obj0 = pool.borrowObject("");
String obj1 = pool.borrowObject("");
assertEquals(2,pool.getNumActive(""));
assertEquals(0,pool.getNumIdle(""));
pool.returnObject("",obj1);
pool.returnObject("",obj0);
assertEquals(0,pool.getNumActive(""));
assertEquals(2,pool.getNumIdle(""));
}
{
String obj0 = pool.borrowObject("2");
String obj1 = pool.borrowObject("2");
assertEquals(2,pool.getNumActive("2"));
assertEquals(0,pool.getNumIdle("2"));
pool.returnObject("2",obj1);
pool.returnObject("2",obj0);
assertEquals(0,pool.getNumActive("2"));
assertEquals(2,pool.getNumIdle("2"));
}
pool.close();
}
public void testIdleCap() throws Exception {
String[] active = new String[100];
for(int i=0;i<100;i++) {
active[i] = pool.borrowObject("");
}
assertEquals(100,pool.getNumActive(""));
assertEquals(0,pool.getNumIdle(""));
for(int i=0;i<100;i++) {
pool.returnObject("",active[i]);
assertEquals(99 - i,pool.getNumActive(""));
assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
}
}
/**
* Verifies maxSleeping contract: When returnObject triggers maxSleeping exceeded,
* the bottom (oldest) instance in the pool is destroyed to make room for the newly
* returning instance, which is pushed onto the idle object stack.
*/
public void testRemoveOldest() throws Exception {
pool._maxSleeping = 2;
String obj0 = pool.borrowObject("");
String obj1 = pool.borrowObject("");
String obj2 = pool.borrowObject("");
pool.returnObject("", obj0); // Push 0 onto bottom of stack
pool.returnObject("", obj1); // Push 1
pool.returnObject("", obj2); // maxSleeping exceeded -> 0 destroyed, 2 pushed
assertEquals("2", pool.borrowObject("")); // 2 was pushed on top
assertEquals("1", pool.borrowObject("")); // 1 still there
assertEquals("3", pool.borrowObject("")); // New instance created (0 is gone)
}
public void testPoolWithNullFactory() throws Exception {
KeyedObjectPool<String, Integer> pool = new StackKeyedObjectPool<String, Integer>(10);
for(int i=0;i<10;i++) {
pool.returnObject("X",new Integer(i));
}
for(int j=0;j<3;j++) {
Integer[] borrowed = new Integer[10];
BitSet found = new BitSet();
for(int i=0;i<10;i++) {
borrowed[i] = pool.borrowObject("X");
assertNotNull(borrowed);
assertTrue(!found.get(borrowed[i].intValue()));
found.set(borrowed[i].intValue());
}
for(int i=0;i<10;i++) {
pool.returnObject("X",borrowed[i]);
}
}
pool.invalidateObject("X",pool.borrowObject("X"));
pool.invalidateObject("X",pool.borrowObject("X"));
pool.clear("X");
pool.clear();
}
public void testVariousConstructors() throws Exception {
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>();
assertNotNull(pool);
}
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>(10);
assertNotNull(pool);
}
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>(10,5);
assertNotNull(pool);
}
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>(null);
assertNotNull(pool);
}
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>(null,10);
assertNotNull(pool);
}
{
StackKeyedObjectPool<Object, Object> pool = new StackKeyedObjectPool<Object, Object>(null,10,5);
assertNotNull(pool);
}
}
@Override
public void testToString() throws Exception {
StackKeyedObjectPool<String, String> pool = new StackKeyedObjectPool<String, String>(new SimpleFactory());
assertNotNull(pool.toString());
String obj = pool.borrowObject("key");
assertNotNull(pool.toString());
pool.returnObject("key",obj);
assertNotNull(pool.toString());
}
public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
KeyedObjectPool<String, Object> pool = new StackKeyedObjectPool<String, Object>();
try {
pool.borrowObject("x");
fail("Expected NoSuchElementException");
} catch(NoSuchElementException e) {
// expected
}
}
public void testSetFactory() throws Exception {
KeyedObjectPool<String, String> pool = new StackKeyedObjectPool<String, String>();
try {
pool.borrowObject("x");
fail("Expected NoSuchElementException");
} catch(NoSuchElementException e) {
// expected
}
pool.setFactory(new SimpleFactory());
String obj = pool.borrowObject("x");
assertNotNull(obj);
pool.returnObject("x",obj);
}
public void testCantResetFactoryWithActiveObjects() throws Exception {
KeyedObjectPool<String, String> pool = new StackKeyedObjectPool<String, String>();
pool.setFactory(new SimpleFactory());
Object obj = pool.borrowObject("x");
assertNotNull(obj);
try {
pool.setFactory(new SimpleFactory());
fail("Expected IllegalStateException");
} catch(IllegalStateException e) {
// expected
}
}
public void testCanResetFactoryWithoutActiveObjects() throws Exception {
KeyedObjectPool<String, String> pool = new StackKeyedObjectPool<String, String>();
{
pool.setFactory(new SimpleFactory());
String obj = pool.borrowObject("x");
assertNotNull(obj);
pool.returnObject("x",obj);
}
{
pool.setFactory(new SimpleFactory());
String obj = pool.borrowObject("x");
assertNotNull(obj);
pool.returnObject("x",obj);
}
}
public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
KeyedObjectPool<String, Integer> pool = new StackKeyedObjectPool<String, Integer>(
new KeyedPoolableObjectFactory<String, Integer>() {
int counter = 0;
public Integer makeObject(String key) { return new Integer(counter++); }
public void destroyObject(String key, Integer obj) { }
public boolean validateObject(String key, Integer obj) {
return ((obj.intValue() % 2) == 1);
}
public void activateObject(String key, Integer obj) { }
public void passivateObject(String key, Integer obj) {
if((obj.intValue() % 3) == 0) {
throw new RuntimeException("Couldn't passivate");
}
}
}
);
Integer[] obj = new Integer[10];
for(int i=0;i<10;i++) {
Integer object = null;
int k = 0;
while (object == null && k < 100) { // bound not really needed
try {
k++;
object = pool.borrowObject("key");
obj[i] = object;
} catch (NoSuchElementException ex) {
// Expected for evens, which fail validation
}
}
assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
}
// 1,3,5,...,19 pass validation, get checked out
for(int i=0;i<10;i++) {
pool.returnObject("key",obj[i]);
assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
}
// 3, 9, 15 fail passivation.
assertEquals(7,pool.getNumIdle());
assertEquals(new Integer(19), pool.borrowObject("key"));
assertEquals(new Integer(17), pool.borrowObject("key"));
assertEquals(new Integer(13), pool.borrowObject("key"));
assertEquals(new Integer(11), pool.borrowObject("key"));
assertEquals(new Integer(7), pool.borrowObject("key"));
assertEquals(new Integer(5), pool.borrowObject("key"));
assertEquals(new Integer(1), pool.borrowObject("key"));
}
class SimpleFactory implements KeyedPoolableObjectFactory<String, String> {
HashMap<String, Integer> map = new HashMap<String, Integer>();
public String makeObject(String key) {
int counter = 0;
Integer Counter = map.get(key);
if(null != Counter) {
counter = Counter.intValue();
}
map.put(key,new Integer(counter + 1));
return String.valueOf(key) + String.valueOf(counter);
}
public void destroyObject(String key, String obj) { }
public boolean validateObject(String key, String obj) { return true; }
public void activateObject(String key, String obj) { }
public void passivateObject(String key, String obj) { }
}
@Override
protected boolean isLifo() {
return true;
}
@Override
protected boolean isFifo() {
return false;
}
}