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    }