/* * 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); } }