View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.dbcp2;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.sql.Connection;
29  import java.sql.SQLException;
30  import java.util.Properties;
31  
32  import org.apache.commons.pool2.impl.GenericObjectPool;
33  import org.junit.jupiter.api.AfterEach;
34  import org.junit.jupiter.api.Assertions;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * TestSuite for PoolingDataSource
40   */
41  public class TestPoolingDataSource extends TestConnectionPool {
42  
43      protected PoolingDataSource<PoolableConnection> ds;
44  
45      private GenericObjectPool<PoolableConnection> pool;
46      @Override
47      protected Connection getConnection() throws Exception {
48          return ds.getConnection();
49      }
50  
51      @BeforeEach
52      public void setUp() throws Exception {
53          final Properties properties = new Properties();
54          properties.setProperty(Constants.KEY_USER, "userName");
55          properties.setProperty(Constants.KEY_PASSWORD, "password");
56          final PoolableConnectionFactory factory =
57              new PoolableConnectionFactory(
58                      new DriverConnectionFactory(new TesterDriver(),
59                              "jdbc:apache:commons:testdriver", properties),
60                      null);
61          factory.setValidationQuery("SELECT DUMMY FROM DUAL");
62          factory.setDefaultReadOnly(Boolean.TRUE);
63          factory.setDefaultAutoCommit(Boolean.TRUE);
64          pool = new GenericObjectPool<>(factory);
65          factory.setPool(pool);
66          pool.setMaxTotal(getMaxTotal());
67          pool.setMaxWait(getMaxWaitDuration());
68          ds = new PoolingDataSource<>(pool);
69          ds.setAccessToUnderlyingConnectionAllowed(true);
70      }
71  
72      @Override
73      @AfterEach
74      public void tearDown() throws Exception {
75          ds.close();
76          super.tearDown();
77      }
78  
79      @Test
80      void testClose() throws Exception {
81          final Properties properties = new Properties();
82          properties.setProperty(Constants.KEY_USER, "userName");
83          properties.setProperty(Constants.KEY_PASSWORD, "password");
84          final PoolableConnectionFactory f = new PoolableConnectionFactory(
85                  new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties), null);
86          f.setValidationQuery("SELECT DUMMY FROM DUAL");
87          f.setDefaultReadOnly(Boolean.TRUE);
88          f.setDefaultAutoCommit(Boolean.TRUE);
89          final GenericObjectPool<PoolableConnection> p = new GenericObjectPool<>(f);
90          p.setMaxTotal(getMaxTotal());
91          p.setMaxWait(getMaxWaitDuration());
92  
93          try (PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(p)) {
94              final Connection connection = dataSource.getConnection();
95              assertNotNull(connection);
96              connection.close();
97          }
98  
99          assertTrue(p.isClosed());
100         assertEquals(0, p.getNumIdle());
101         assertEquals(0, p.getNumActive());
102     }
103 
104     /**
105      * DBCP-412
106      * Verify that omitting factory.setPool(pool) when setting up PDS does not
107      * result in NPE.
108      */
109     @Test
110     void testFixFactoryConfig() throws Exception {
111         final Properties properties = new Properties();
112         properties.setProperty(Constants.KEY_USER, "userName");
113         properties.setProperty(Constants.KEY_PASSWORD, "password");
114         final PoolableConnectionFactory f =
115             new PoolableConnectionFactory(
116                     new DriverConnectionFactory(new TesterDriver(),
117                             "jdbc:apache:commons:testdriver", properties),
118                     null);
119         f.setValidationQuery("SELECT DUMMY FROM DUAL");
120         f.setDefaultReadOnly(Boolean.TRUE);
121         f.setDefaultAutoCommit(Boolean.TRUE);
122         final GenericObjectPool<PoolableConnection> p = new GenericObjectPool<>(f);
123         p.setMaxTotal(getMaxTotal());
124         p.setMaxWait(getMaxWaitDuration());
125         ds = new PoolingDataSource<>(p);
126         assertEquals(f.getPool(), p);
127         ds.getConnection();
128     }
129 
130     @Test
131     void testIsWrapperFor() throws Exception {
132         assertTrue(ds.isWrapperFor(PoolingDataSource.class));
133         assertTrue(ds.isWrapperFor(AutoCloseable.class));
134         assertFalse(ds.isWrapperFor(String.class));
135         assertFalse(ds.isWrapperFor(null));
136     }
137 
138     @Test
139     void testPoolGuardConnectionWrapperEqualInnermost() throws Exception {
140         ds.setAccessToUnderlyingConnectionAllowed(true);
141         final DelegatingConnection<?> con = (DelegatingConnection<?>) ds.getConnection();
142         final Connection inner = con.getInnermostDelegate();
143         ds.setAccessToUnderlyingConnectionAllowed(false);
144         final DelegatingConnection<Connection> con2 = new DelegatingConnection<>(inner);
145         assertNotEquals(con2, con);
146         assertTrue(con.innermostDelegateEquals(con2.getInnermostDelegate()));
147         assertTrue(con2.innermostDelegateEquals(inner));
148         assertNotEquals(con, con2);
149     }
150 
151     @Test
152     void testPoolGuardConnectionWrapperEqualsFail() throws Exception {
153         final Connection con1 = ds.getConnection();
154         final Connection con2 = ds.getConnection();
155         assertNotEquals(con1, con2);
156         con1.close();
157         con2.close();
158     }
159 
160     @Test
161     void testPoolGuardConnectionWrapperEqualsNull() throws Exception {
162         final Connection con1 = ds.getConnection();
163         final Connection con2 = null;
164         assertNotEquals(con2, con1);
165         con1.close();
166     }
167 
168     /*
169      * JIRA: DBCP-198
170      */
171     @Test
172     void testPoolGuardConnectionWrapperEqualsReflexive()
173         throws Exception {
174         final Connection con = ds.getConnection();
175         final Connection con2 = con;
176         assertEquals(con2, con);
177         assertEquals(con, con2);
178         con.close();
179     }
180 
181     @Test
182     void testPoolGuardConnectionWrapperEqualsSameDelegate() throws Exception {
183         // Get a maximal set of connections from the pool
184         final Connection[] c = new Connection[getMaxTotal()];
185         for (int i = 0; i < c.length; i++) {
186             c[i] = newConnection();
187         }
188         // Close the delegate of one wrapper in the pool
189         ((DelegatingConnection<?>) c[0]).getDelegate().close();
190 
191         // Grab a new connection - should get c[0]'s closed connection
192         // so should be delegate-equivalent
193         final Connection con = newConnection();
194         Assertions.assertNotEquals(c[0], con);
195         Assertions.assertEquals(
196                 ((DelegatingConnection<?>) c[0]).getInnermostDelegateInternal(),
197                 ((DelegatingConnection<?>) con).getInnermostDelegateInternal());
198         for (final Connection element : c) {
199             element.close();
200         }
201     }
202 
203     @Test
204     void testPoolGuardConnectionWrapperEqualsType() throws Exception {
205         final Connection con1 = ds.getConnection();
206         final Integer con2 = 0;
207         assertNotEquals(con2, con1);
208         con1.close();
209     }
210 
211     @Test
212     void testUnwrap() throws Exception {
213         assertSame(ds.unwrap(PoolingDataSource.class), ds);
214         assertSame(ds.unwrap(AutoCloseable.class), ds);
215         assertThrows(SQLException.class, () -> ds.unwrap(String.class));
216         assertThrows(SQLException.class, () -> ds.unwrap(null));
217     }
218 }