/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed 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.seasar.extension.dbcp.impl;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.XAConnection;
import javax.transaction.Synchronization;
import javax.transaction.TransactionManager;
import org.seasar.extension.dbcp.ConnectionPool;
import org.seasar.extension.dbcp.ConnectionWrapper;
import org.seasar.extension.timer.TimeoutManager;
import org.seasar.extension.unit.S2TestCase;
/**
* @author higa
*
*/
public class ConnectionPoolImplTest extends S2TestCase {
private static final String PATH = "connection.dicon";
private ConnectionPool pool_;
private ConnectionPool pool2_;
private TransactionManager tm_;
private boolean checkOuted_ = false;
/**
* @throws Exception
*/
public void testCheckOut() throws Exception {
Runnable r = new Runnable() {
public void run() {
try {
ConnectionWrapper con = pool_.checkOut();
checkOuted_ = true;
Thread.sleep(4000);
pool_.checkIn(con);
System.out.println("checkIn");
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
};
Thread th = new Thread(r);
th.start();
while (!checkOuted_ && th.isAlive()) {
Thread.sleep(100);
}
ConnectionWrapper con = pool_.checkOut();
pool_.checkIn(con);
assertTrue("1", con.isClosed());
}
/**
* @throws Exception
*/
public void testReuseConnection() throws Exception {
ConnectionWrapper con = pool_.checkOut();
pool_.checkIn(con);
ConnectionWrapper con2 = pool_.checkOut();
pool_.checkIn(con2);
assertSame(con.getXAConnection(), con2.getXAConnection());
assertSame(con.getPhysicalConnection(), con2.getPhysicalConnection());
}
/**
* @throws Exception
*/
public void testCloseLogicalConnection() throws Exception {
ConnectionWrapper con = pool_.checkOut();
assertEquals("1", 1, pool_.getActivePoolSize());
assertEquals("2", 0, pool_.getFreePoolSize());
con.close();
assertEquals("3", 0, pool_.getActivePoolSize());
assertEquals("4", 1, pool_.getFreePoolSize());
}
/**
*
* @throws Exception
*/
public void testCloseLogicalConnection_afterCompletion() throws Exception {
tm_.begin();
final Connection con = pool_.checkOut();
tm_.getTransaction().registerSynchronization(new Synchronization() {
public void beforeCompletion() {
}
public void afterCompletion(int status) {
try {
con.close();
} catch (SQLException e) {
fail();
}
}
});
assertEquals(1, pool_.getTxActivePoolSize());
assertEquals(0, pool_.getFreePoolSize());
tm_.commit();
assertTrue(con.isClosed());
assertNull(((ConnectionWrapperImpl) con).getXAConnection());
assertNull(((ConnectionWrapperImpl) con).getPhysicalConnection());
assertEquals(0, pool_.getTxActivePoolSize());
assertEquals(1, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testClose() throws Exception {
Thread.sleep(1500);
assertEquals(2, TimeoutManager.getInstance().getTimeoutTaskCount());
ConnectionWrapper wrapper = pool_.checkOut();
pool_.checkIn(wrapper);
assertEquals(3, TimeoutManager.getInstance().getTimeoutTaskCount());
pool_.close();
assertEquals(0, pool_.getActivePoolSize());
assertEquals(0, pool_.getFreePoolSize());
pool2_.close();
Thread.sleep(1500);
assertEquals(0, TimeoutManager.getInstance().getTimeoutTaskCount());
}
/**
* @throws Exception
*/
public void testTransaction() throws Exception {
tm_.begin();
ConnectionWrapper con = pool_.checkOut();
assertEquals("1", 0, pool_.getActivePoolSize());
assertEquals("2", 1, pool_.getTxActivePoolSize());
con.close();
assertEquals("3", 0, pool_.getActivePoolSize());
assertEquals("4", 1, pool_.getTxActivePoolSize());
ConnectionWrapper con2 = pool_.checkOut();
assertEquals("5", 1, pool_.getTxActivePoolSize());
assertEquals("6", 0, pool_.getActivePoolSize());
con2.close();
tm_.commit();
assertEquals("7", 0, pool_.getActivePoolSize());
assertEquals("8", 0, pool_.getTxActivePoolSize());
assertEquals("9", 1, pool_.getFreePoolSize());
assertSame("10", con, con2);
}
/**
* @throws Exception
*/
public void testTransaction2() throws Exception {
tm_.begin();
ConnectionWrapper con = pool_.checkOut();
ConnectionWrapper con2 = pool_.checkOut();
assertEquals("1", 0, pool_.getActivePoolSize());
assertEquals("2", 1, pool_.getTxActivePoolSize());
con.close();
con2.close();
assertEquals("3", 0, pool_.getActivePoolSize());
assertEquals("4", 1, pool_.getTxActivePoolSize());
tm_.commit();
assertEquals("5", 0, pool_.getActivePoolSize());
assertEquals("6", 0, pool_.getTxActivePoolSize());
assertEquals("7", 1, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testTransaction3() throws Exception {
((ConnectionPoolImpl) pool_).setMaxPoolSize(0);
tm_.begin();
ConnectionWrapper con = pool_.checkOut();
ConnectionWrapper con2 = pool_.checkOut();
assertEquals("1", 0, pool_.getActivePoolSize());
assertEquals("2", 1, pool_.getTxActivePoolSize());
con.close();
con2.close();
assertEquals("3", 0, pool_.getActivePoolSize());
assertEquals("4", 1, pool_.getTxActivePoolSize());
tm_.commit();
assertEquals("5", 0, pool_.getActivePoolSize());
assertEquals("6", 0, pool_.getTxActivePoolSize());
assertEquals("7", 0, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testIrregularUsecase() throws Exception {
ConnectionWrapper con = pool_.checkOut();
assertEquals("1", 1, pool_.getActivePoolSize());
assertEquals("2", 0, pool_.getTxActivePoolSize());
tm_.begin();
con.close();
assertEquals("3", 0, pool_.getActivePoolSize());
assertEquals("4", 0, pool_.getTxActivePoolSize());
assertEquals("5", 1, pool_.getFreePoolSize());
tm_.commit();
assertEquals("6", 0, pool_.getActivePoolSize());
assertEquals("7", 0, pool_.getTxActivePoolSize());
assertEquals("8", 1, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void test2PC() throws Exception {
tm_.begin();
ConnectionWrapper con = pool_.checkOut();
ConnectionWrapper con2 = pool2_.checkOut();
assertEquals("1", 0, pool_.getActivePoolSize());
assertEquals("2", 0, pool2_.getActivePoolSize());
assertEquals("3", 1, pool_.getTxActivePoolSize());
assertEquals("4", 1, pool2_.getTxActivePoolSize());
con.close();
con2.close();
assertEquals("5", 0, pool_.getActivePoolSize());
assertEquals("6", 0, pool2_.getActivePoolSize());
assertEquals("7", 1, pool_.getTxActivePoolSize());
assertEquals("8", 1, pool2_.getTxActivePoolSize());
tm_.commit();
assertEquals("9", 0, pool_.getActivePoolSize());
assertEquals("10", 0, pool2_.getActivePoolSize());
assertEquals("11", 0, pool_.getTxActivePoolSize());
assertEquals("12", 0, pool2_.getTxActivePoolSize());
assertEquals("13", 1, pool_.getFreePoolSize());
assertEquals("14", 1, pool2_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testTimeout() throws Exception {
ConnectionWrapper con = pool_.checkOut();
pool_.checkIn(con);
Thread.sleep(8000);
assertEquals("1", 0, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testTimeout2() throws Exception {
ConnectionWrapper con = pool_.checkOut();
pool_.checkIn(con);
con = pool_.checkOut();
Thread.sleep(8000);
con.getAutoCommit();
}
/**
* @throws Exception
*/
public void testRequiredTransaction() throws Exception {
((ConnectionPoolImpl) pool_).setAllowLocalTx(false);
try {
pool_.checkOut();
fail("1");
} catch (IllegalStateException expected) {
}
}
/**
* @throws Exception
*/
public void testMaxPoolSize0() throws Exception {
((ConnectionPoolImpl) pool_).setMaxPoolSize(0);
ConnectionWrapper con = pool_.checkOut();
pool_.checkIn(con);
assertEquals("1", 0, pool_.getFreePoolSize());
int size = 100;
ConnectionWrapper[] cons = new ConnectionWrapper[size];
for (int i = 0; i < size; ++i) {
cons[i] = pool_.checkOut();
}
for (int i = 0; i < size; ++i) {
pool_.checkIn(cons[i]);
}
assertEquals("2", 0, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testMinPoolSize() throws Exception {
((ConnectionPoolImpl) pool_).setMaxPoolSize(2);
((ConnectionPoolImpl) pool_).setMinPoolSize(1);
((ConnectionPoolImpl) pool_).setTimeout(1);
ConnectionWrapper con1 = pool_.checkOut();
Connection pc1 = ((ConnectionWrapperImpl) con1).getPhysicalConnection();
ConnectionWrapper con2 = pool_.checkOut();
Connection pc2 = ((ConnectionWrapperImpl) con2).getPhysicalConnection();
pool_.checkIn(con1);
pool_.checkIn(con2);
assertEquals(2, pool_.getFreePoolSize());
Thread.sleep(2000);
assertEquals(1, pool_.getFreePoolSize());
assertTrue(pc1.isClosed());
assertFalse(pc2.isClosed());
ConnectionWrapper con3 = pool_.checkOut();
assertFalse(con3.isClosed());
assertEquals(0, pool_.getFreePoolSize());
}
/**
* @throws Exception
*/
public void testCheckInTxNotify() throws Exception {
tm_.begin();
((ConnectionPoolImpl) pool_).setMaxPoolSize(1);
ConnectionWrapper con = pool_.checkOut();
Thread thread = new Thread() {
public void run() {
try {
pool_.checkOut();
synchronized (ConnectionPoolImplTest.this) {
checkOuted_ = true;
}
} catch (SQLException e) {
fail(e.toString());
}
}
};
thread.start();
con.close();
Thread.sleep(100);
assertFalse("1", checkOuted_);
tm_.commit();
Thread.sleep(100);
assertTrue("2", checkOuted_);
thread.interrupt();
}
/**
* @throws Exception
*/
public void testExpired() throws Exception {
((ConnectionPoolImpl) pool_).setTimeout(0);
synchronized (pool_) {
ConnectionWrapper con = pool_.checkOut();
con.close();
Thread.sleep(200);
con = pool_.checkOut();
con.close();
}
}
/**
* @throws Exception
*/
public void testConnectionStatus() throws Exception {
((ConnectionPoolImpl) pool_).setMaxPoolSize(1);
((ConnectionPoolImpl) pool_).setReadOnly(true);
((ConnectionPoolImpl) pool_)
.setTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED);
ConnectionWrapper con = pool_.checkOut();
assertTrue(con.getAutoCommit());
assertTrue(con.isReadOnly());
assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, con
.getTransactionIsolation());
con.setAutoCommit(false);
con.setReadOnly(false);
con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
con.close();
ConnectionWrapper con2 = pool_.checkOut();
assertTrue(con2.getAutoCommit());
assertTrue(con2.isReadOnly());
assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, con2
.getTransactionIsolation());
con2.close();
}
/**
*
* @throws Exception
*/
public void testValidationQuery() throws Exception {
((ConnectionPoolImpl) pool_).setValidationQuery("select * from dual");
((ConnectionPoolImpl) pool_).setValidationInterval(100);
((ConnectionPoolImpl) pool_).setTimeout(600 * 1000);
((ConnectionPoolImpl) pool_).setMaxPoolSize(2);
ConnectionWrapper con1 = pool_.checkOut();
XAConnection xaCon1 = con1.getXAConnection();
pool_.checkIn(con1);
Thread.sleep(200);
ConnectionWrapper con2 = pool_.checkOut();
XAConnection xaCon2 = con2.getXAConnection();
assertSame(xaCon1, xaCon2);
pool_.checkIn(con2);
((ConnectionPoolImpl) pool_)
.setValidationQuery("select * from hogehoge");
con2 = pool_.checkOut();
xaCon2 = con2.getXAConnection();
assertSame(xaCon1, xaCon2);
ConnectionWrapper con3 = pool_.checkOut();
pool_.checkIn(con3);
pool_.checkIn(con2);
Thread.sleep(200);
con2 = pool_.checkOut();
xaCon2 = con2.getXAConnection();
assertNotNull(con2);
assertNotSame(xaCon1, xaCon2);
pool_.checkIn(con2);
}
/**
*
* @throws Exception
*/
public void testMaxWait() throws Exception {
((ConnectionPoolImpl) pool_).setMaxPoolSize(1);
((ConnectionPoolImpl) pool_).setMaxWait(0L);
pool_.checkOut();
try {
pool_.checkOut();
fail();
} catch (SQLException e) {
System.out.println(e);
}
((ConnectionPoolImpl) pool_).setMaxWait(1000L);
final Thread currentThread = Thread.currentThread();
Thread otherThread = new Thread() {
public void run() {
try {
Thread.sleep(500L);
synchronized (pool_) {
pool_.notifyAll();
}
} catch (InterruptedException ignore) {
}
}
};
long t1 = System.currentTimeMillis();
try {
otherThread.start();
pool_.checkOut();
fail();
} catch (SQLException e) {
System.out.println(e);
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
assertTrue(t2 - t1 >= 1000);
((ConnectionPoolImpl) pool_).setMaxWait(-1L);
otherThread = new Thread() {
public void run() {
try {
for (int i = 0; i < 3; ++i) {
Thread.sleep(500L);
synchronized (pool_) {
pool_.notifyAll();
}
}
Thread.sleep(500L);
currentThread.interrupt();
} catch (InterruptedException ignore) {
}
}
};
t1 = System.currentTimeMillis();
try {
otherThread.start();
pool_.checkOut();
fail();
} catch (SQLException e) {
System.out.println(e);
}
t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
assertTrue(t2 - t1 >= 2000);
}
protected void setUp() throws Exception {
include(PATH);
}
}