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    *      http://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.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
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      public void test1() {
99          final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string","userName","password");
100         final PoolableConnectionFactory pcf =
101             new PoolableConnectionFactory(connectionFactory, null);
102         pcf.setDefaultReadOnly(Boolean.FALSE);
103         pcf.setDefaultAutoCommit(Boolean.TRUE);
104         final GenericObjectPool<PoolableConnection> connectionPool =
105                 new GenericObjectPool<>(pcf);
106         pcf.setPool(connectionPool);
107         final DataSource ds = new PoolingDataSource<>(connectionPool);
108         Assertions.assertNotNull(ds);
109     }
110 
111     @Test
112     public void test2() {
113         final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string","userName","password");
114         final PoolableConnectionFactory pcf =
115             new PoolableConnectionFactory(connectionFactory, null);
116         pcf.setDefaultReadOnly(Boolean.FALSE);
117         pcf.setDefaultAutoCommit(Boolean.TRUE);
118         final GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf);
119         final PoolingDriver driver2 = new PoolingDriver();
120         driver2.registerPool("example", connectionPool);
121     }
122 
123     @Test
124     public void testClosePool() throws Exception {
125         final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test");
126         assertNotNull(conn);
127         conn.close();
128 
129         final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
130         driver2.closePool("test");
131 
132         try (Connection c = DriverManager.getConnection("jdbc:apache:commons:dbcp:test")) {
133             fail("expected SQLException");
134         }
135         catch (final SQLException e) {
136             // OK
137         }
138     }
139 
140     @Test
141     public void testInvalidateConnection() throws Exception {
142         final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test");
143         assertNotNull(conn);
144 
145         final ObjectPool<?> pool = driver.getConnectionPool("test");
146         assertEquals(1, pool.getNumActive());
147         assertEquals(0, pool.getNumIdle());
148 
149         final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
150         driver2.invalidateConnection(conn);
151 
152         assertEquals(0, pool.getNumActive());
153         assertEquals(0, pool.getNumIdle());
154         assertTrue(conn.isClosed());
155     }
156 
157     @Test
158     public void testLogWriter() throws Exception {
159         final PrintStream ps = new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name());
160         final PrintWriter pw = new PrintWriter(new OutputStreamWriter(new ByteArrayOutputStream(), StandardCharsets.UTF_8));
161         System.setErr(new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name()));
162         SQLException ex;
163 
164         DriverManager.setLogWriter(pw);
165         ex = new SQLException("A", new Exception("a"));
166         ex.printStackTrace();
167         ex.printStackTrace(ps);
168         ex.printStackTrace(pw);
169         ex = new SQLException("B");
170         ex.printStackTrace();
171         ex.printStackTrace(ps);
172         ex.printStackTrace(pw);
173         ex = new SQLException(null, new Exception("c"));
174         ex.printStackTrace();
175         ex.printStackTrace(ps);
176         ex.printStackTrace(pw);
177         ex = new SQLException((String)null);
178         ex.printStackTrace();
179         ex.printStackTrace(ps);
180         ex.printStackTrace(pw);
181 
182         DriverManager.setLogWriter(null);
183         ex = new SQLException("A", new Exception("a"));
184         ex.printStackTrace();
185         ex.printStackTrace(ps);
186         ex.printStackTrace(pw);
187         ex = new SQLException("B");
188         ex.printStackTrace();
189         ex.printStackTrace(ps);
190         ex.printStackTrace(pw);
191         ex = new SQLException(null, new Exception("c"));
192         ex.printStackTrace();
193         ex.printStackTrace(ps);
194         ex.printStackTrace(pw);
195         ex = new SQLException((String)null);
196         ex.printStackTrace();
197         ex.printStackTrace(ps);
198         ex.printStackTrace(pw);
199     }
200 
201     /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */
202     @Test
203     public void testReportedBug12400() throws Exception {
204         final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
205         config.setMaxTotal(70);
206         config.setMaxWait(Duration.ofMinutes(1));
207         config.setMaxIdle(10);
208         final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
209             "jdbc:apache:commons:testdriver",
210             "userName",
211             "password");
212         final PoolableConnectionFactory poolableConnectionFactory =
213             new PoolableConnectionFactory(connectionFactory, null);
214         poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE);
215         poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE);
216         final ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory,
217                 config);
218         poolableConnectionFactory.setPool(connectionPool);
219         assertNotNull(poolableConnectionFactory);
220         final PoolingDriver driver2 = new PoolingDriver();
221         driver2.registerPool("neusoftim", connectionPool);
222         final Connection[] conn = new Connection[25];
223         for(int i=0;i<25;i++) {
224             conn[i] = DriverManager.getConnection("jdbc:apache:commons:dbcp:neusoftim");
225             for(int j=0;j<i;j++) {
226                 assertNotSame(conn[j], conn[i]);
227                 assertNotEquals(conn[j], conn[i]);
228             }
229         }
230         for(int i=0;i<25;i++) {
231             conn[i].close();
232         }
233     }
234 
235     /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=28912" */
236     @Test
237     public void testReportedBug28912() throws Exception {
238         final Connection conn1 = getConnection();
239         assertNotNull(conn1);
240         assertFalse(conn1.isClosed());
241         conn1.close();
242 
243         final Connection conn2 = getConnection();
244         assertNotNull(conn2);
245 
246         assertTrue(conn1.isClosed());
247         assertFalse(conn2.isClosed());
248 
249         // should be able to call close multiple times with no effect
250         conn1.close();
251 
252         assertTrue(conn1.isClosed());
253         assertFalse(conn2.isClosed());
254     }
255 }