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.assertNotSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.io.ByteArrayOutputStream;
29  import java.io.OutputStreamWriter;
30  import java.io.PrintStream;
31  import java.io.PrintWriter;
32  import java.nio.charset.StandardCharsets;
33  import java.sql.Connection;
34  import java.sql.DriverManager;
35  import java.sql.SQLException;
36  import java.time.Duration;
37  
38  import javax.sql.DataSource;
39  
40  import org.apache.commons.pool2.ObjectPool;
41  import org.apache.commons.pool2.impl.GenericObjectPool;
42  import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
43  import org.junit.jupiter.api.AfterEach;
44  import org.junit.jupiter.api.Assertions;
45  import org.junit.jupiter.api.BeforeEach;
46  import org.junit.jupiter.api.Test;
47  
48  /**
49   * Tests for a {@link GenericObjectPool} based {@link PoolingDriver}.
50   */
51  public class TestPoolingDriver extends TestConnectionPool {
52  
53      private PoolingDriver driver;
54  
55      @Override
56      protected Connection getConnection() throws Exception {
57          return DriverManager.getConnection("jdbc:apache:commons:dbcp:test");
58      }
59  
60      @BeforeEach
61      public void setUp() throws Exception {
62          final DriverConnectionFactory cf = new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", null);
63  
64          final PoolableConnectionFactory pcf = new PoolableConnectionFactory(cf, null);
65          pcf.setPoolStatements(true);
66          pcf.setMaxOpenPreparedStatements(10);
67          pcf.setValidationQuery("SELECT COUNT(*) FROM DUAL");
68          pcf.setDefaultReadOnly(Boolean.FALSE);
69          pcf.setDefaultAutoCommit(Boolean.TRUE);
70  
71          final GenericObjectPoolConfig<PoolableConnection> poolConfig = new GenericObjectPoolConfig<>();
72          poolConfig.setMaxTotal(getMaxTotal());
73          poolConfig.setMaxWait(getMaxWaitDuration());
74          poolConfig.setMinIdle(10);
75          poolConfig.setTestOnBorrow(true);
76          poolConfig.setTestOnReturn(true);
77          poolConfig.setTestWhileIdle(true);
78          poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(10_000));
79          poolConfig.setNumTestsPerEvictionRun(5);
80          poolConfig.setMinEvictableIdleTime(Duration.ofMillis(5_000));
81  
82          final GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<>(pcf, poolConfig);
83          pcf.setPool(pool);
84  
85          assertNotNull(pcf);
86          driver = new PoolingDriver(true);
87          driver.registerPool("test", pool);
88      }
89  
90      @Override
91      @AfterEach
92      public void tearDown() throws Exception {
93          driver.closePool("test");
94          super.tearDown();
95      }
96  
97      @Test
98      void test1() {
99          final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string", "userName", "password");
100         final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connectionFactory, null);
101         pcf.setDefaultReadOnly(Boolean.FALSE);
102         pcf.setDefaultAutoCommit(Boolean.TRUE);
103         final GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf);
104         pcf.setPool(connectionPool);
105         final DataSource ds = new PoolingDataSource<>(connectionPool);
106         Assertions.assertNotNull(ds);
107     }
108 
109     @Test
110     void test2() {
111         final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string", "userName", "password");
112         final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connectionFactory, null);
113         pcf.setDefaultReadOnly(Boolean.FALSE);
114         pcf.setDefaultAutoCommit(Boolean.TRUE);
115         final GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf);
116         final PoolingDriver driver2 = new PoolingDriver();
117         driver2.registerPool("example", connectionPool);
118     }
119 
120     @Test
121     void testClosePool() throws Exception {
122         final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test");
123         assertNotNull(conn);
124         conn.close();
125 
126         final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
127         driver2.closePool("test");
128 
129         assertThrows(SQLException.class, () -> DriverManager.getConnection("jdbc:apache:commons:dbcp:test"));
130     }
131 
132     @Test
133     void testInvalidateConnection() throws Exception {
134         final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test");
135         assertNotNull(conn);
136 
137         final ObjectPool<?> pool = driver.getConnectionPool("test");
138         assertEquals(1, pool.getNumActive());
139         assertEquals(0, pool.getNumIdle());
140 
141         final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
142         driver2.invalidateConnection(conn);
143 
144         assertEquals(0, pool.getNumActive());
145         assertTrue(conn.isClosed());
146     }
147 
148     @Test
149     void testLogWriter() throws Exception {
150         final PrintStream ps = new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name());
151         final PrintWriter pw = new PrintWriter(new OutputStreamWriter(new ByteArrayOutputStream(), StandardCharsets.UTF_8));
152         System.setErr(new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name()));
153         SQLException ex;
154 
155         DriverManager.setLogWriter(pw);
156         ex = new SQLException("A", new Exception("a"));
157         ex.printStackTrace();
158         ex.printStackTrace(ps);
159         ex.printStackTrace(pw);
160         ex = new SQLException("B");
161         ex.printStackTrace();
162         ex.printStackTrace(ps);
163         ex.printStackTrace(pw);
164         ex = new SQLException(null, new Exception("c"));
165         ex.printStackTrace();
166         ex.printStackTrace(ps);
167         ex.printStackTrace(pw);
168         ex = new SQLException((String) null);
169         ex.printStackTrace();
170         ex.printStackTrace(ps);
171         ex.printStackTrace(pw);
172 
173         DriverManager.setLogWriter(null);
174         ex = new SQLException("A", new Exception("a"));
175         ex.printStackTrace();
176         ex.printStackTrace(ps);
177         ex.printStackTrace(pw);
178         ex = new SQLException("B");
179         ex.printStackTrace();
180         ex.printStackTrace(ps);
181         ex.printStackTrace(pw);
182         ex = new SQLException(null, new Exception("c"));
183         ex.printStackTrace();
184         ex.printStackTrace(ps);
185         ex.printStackTrace(pw);
186         ex = new SQLException((String) null);
187         ex.printStackTrace();
188         ex.printStackTrace(ps);
189         ex.printStackTrace(pw);
190     }
191 
192     /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */
193     @Test
194     void testReportedBug12400() throws Exception {
195         final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
196         config.setMaxTotal(70);
197         config.setMaxWait(Duration.ofMinutes(1));
198         config.setMaxIdle(10);
199         final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "userName", "password");
200         final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
201         poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE);
202         poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE);
203         final ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory, config);
204         poolableConnectionFactory.setPool(connectionPool);
205         assertNotNull(poolableConnectionFactory);
206         final PoolingDriver driver2 = new PoolingDriver();
207         driver2.registerPool("neusoftim", connectionPool);
208         final Connection[] conn = new Connection[25];
209         for (int i = 0; i < 25; i++) {
210             conn[i] = DriverManager.getConnection("jdbc:apache:commons:dbcp:neusoftim");
211             for (int j = 0; j < i; j++) {
212                 assertNotSame(conn[j], conn[i]);
213                 assertNotEquals(conn[j], conn[i]);
214             }
215         }
216         for (int i = 0; i < 25; i++) {
217             conn[i].close();
218         }
219     }
220 
221     /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=28912" */
222     @Test
223     void testReportedBug28912() throws Exception {
224         final Connection conn1 = getConnection();
225         assertNotNull(conn1);
226         assertFalse(conn1.isClosed());
227         conn1.close();
228 
229         final Connection conn2 = getConnection();
230         assertNotNull(conn2);
231 
232         assertTrue(conn1.isClosed());
233         assertFalse(conn2.isClosed());
234 
235         // should be able to call close multiple times with no effect
236         conn1.close();
237 
238         assertTrue(conn1.isClosed());
239         assertFalse(conn2.isClosed());
240     }
241 }