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.dbcp.datasources;
019
020 import java.sql.Connection;
021 import java.sql.SQLException;
022
023 import javax.sql.PooledConnection;
024
025 import junit.framework.Test;
026 import junit.framework.TestCase;
027 import junit.framework.TestSuite;
028
029 import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS;
030
031 import org.apache.commons.pool.impl.GenericObjectPool;
032
033 /**
034 * @version $Revision$ $Date$
035 */
036 public class TestCPDSConnectionFactory extends TestCase {
037
038 protected ConnectionPoolDataSourceProxy cpds = null;
039
040 public TestCPDSConnectionFactory(String testName) {
041 super(testName);
042 }
043
044 public static Test suite() {
045 return new TestSuite(TestCPDSConnectionFactory.class);
046 }
047
048 public void setUp() throws Exception {
049 cpds = new ConnectionPoolDataSourceProxy(new DriverAdapterCPDS());
050 DriverAdapterCPDS delegate = (DriverAdapterCPDS) cpds.getDelegate();
051 delegate.setDriver("org.apache.commons.dbcp.TesterDriver");
052 delegate.setUrl("jdbc:apache:commons:testdriver");
053 delegate.setUser("username");
054 delegate.setPassword("password");
055 }
056
057 /**
058 * JIRA DBCP-216
059 *
060 * Check PoolableConnection close triggered by destroy is handled
061 * properly. PooledConnectionProxy (dubiously) fires connectionClosed
062 * when PooledConnection itself is closed.
063 */
064 public void testSharedPoolDSDestroyOnReturn() throws Exception {
065 PerUserPoolDataSource ds = new PerUserPoolDataSource();
066 ds.setConnectionPoolDataSource(cpds);
067 ds.setPerUserMaxActive("username",new Integer(10));// Integer.valueOf() is Java 1.5
068 ds.setPerUserMaxWait("username",new Integer(50));
069 ds.setPerUserMaxIdle("username",new Integer(2));
070 Connection conn1 = ds.getConnection("username", "password");
071 Connection conn2 = ds.getConnection("username", "password");
072 Connection conn3 = ds.getConnection("username", "password");
073 assertEquals(3, ds.getNumActive("username", "password"));
074 conn1.close();
075 assertEquals(1, ds.getNumIdle("username", "password"));
076 conn2.close();
077 assertEquals(2, ds.getNumIdle("username", "password"));
078 conn3.close(); // Return to pool will trigger destroy -> close sequence
079 assertEquals(2, ds.getNumIdle("username", "password"));
080 }
081
082 /**
083 * JIRA DBCP-216
084 *
085 * Verify that pool counters are maintained properly and listeners are
086 * cleaned up when a PooledConnection throws a connectionError event.
087 */
088 public void testConnectionErrorCleanup() throws Exception {
089 // Setup factory
090 GenericObjectPool pool = new GenericObjectPool(null);
091 CPDSConnectionFactory factory =
092 new CPDSConnectionFactory(cpds, pool, null, "username", "password");
093
094 // Checkout a pair of connections
095 PooledConnection pcon1 =
096 ((PooledConnectionAndInfo) pool.borrowObject())
097 .getPooledConnection();
098 Connection con1 = pcon1.getConnection();
099 PooledConnection pcon2 =
100 ((PooledConnectionAndInfo) pool.borrowObject())
101 .getPooledConnection();
102 assertEquals(2, pool.getNumActive());
103 assertEquals(0, pool.getNumIdle());
104
105 // Verify listening
106 PooledConnectionProxy pc = (PooledConnectionProxy) pcon1;
107 assertTrue(pc.getListeners().contains(factory));
108
109 // Throw connectionError event
110 pc.throwConnectionError();
111
112 // Active count should be reduced by 1 and no idle increase
113 assertEquals(1, pool.getNumActive());
114 assertEquals(0, pool.getNumIdle());
115
116 // Throw another one - should be ignored
117 pc.throwConnectionError();
118 assertEquals(1, pool.getNumActive());
119 assertEquals(0, pool.getNumIdle());
120
121 // Ask for another connection
122 PooledConnection pcon3 =
123 ((PooledConnectionAndInfo) pool.borrowObject())
124 .getPooledConnection();
125 assertTrue(!pcon3.equals(pcon1)); // better not get baddie back
126 assertTrue(!pc.getListeners().contains(factory)); // verify cleanup
127 assertEquals(2, pool.getNumActive());
128 assertEquals(0, pool.getNumIdle());
129
130 // Return good connections back to pool
131 pcon2.getConnection().close();
132 pcon3.getConnection().close();
133 assertEquals(2, pool.getNumIdle());
134 assertEquals(0, pool.getNumActive());
135
136 // Verify pc is closed
137 try {
138 pc.getConnection();
139 fail("Expecting SQLException using closed PooledConnection");
140 } catch (SQLException ex) {
141 // expected
142 }
143
144 // Back from the dead - ignore the ghost!
145 con1.close();
146 assertEquals(2, pool.getNumIdle());
147 assertEquals(0, pool.getNumActive());
148
149 // Clear pool
150 factory.getPool().clear();
151 assertEquals(0, pool.getNumIdle());
152 }
153
154 }