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  package org.apache.commons.dbcp2;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  
22  import java.sql.SQLException;
23  import java.time.Duration;
24  
25  import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
26  import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
27  import org.junit.jupiter.api.AfterEach;
28  import org.junit.jupiter.api.BeforeEach;
29  import org.junit.jupiter.api.Test;
30  
31  public class TestPoolingConnection {
32  
33      private PoolingConnection connection;
34  
35      @SuppressWarnings("resource") // Resources closed in @AfterEach method.
36      @BeforeEach
37      public void setUp() throws Exception {
38          connection = new PoolingConnection(new TesterConnection("test", "test"));
39          final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
40          config.setMaxTotalPerKey(-1);
41          config.setBlockWhenExhausted(false);
42          config.setMaxWait(Duration.ZERO);
43          config.setMaxIdlePerKey(1);
44          config.setMaxTotal(1);
45          connection.setStatementPool(new GenericKeyedObjectPool<>(connection, config));
46      }
47  
48      @AfterEach
49      public void tearDown() throws Exception {
50          connection.close();
51          connection = null;
52      }
53  
54      @Test
55      public void testPrepareCall() throws Exception {
56          final String sql = "select 'a' from dual";
57          try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql)) {
58              final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate();
59              // assert
60              assertEquals(sql, testStatement.getSql());
61          }
62      }
63  
64      @Test
65      public void testPrepareCallWithResultSetConcurrency() throws Exception {
66          final String sql = "select 'a' from dual";
67          final int resultSetType = 0;
68          final int resultSetConcurrency = 0;
69          try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql, resultSetType, resultSetConcurrency)) {
70              final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate();
71              // assert
72              assertEquals(sql, testStatement.getSql());
73              assertEquals(resultSetType, testStatement.getResultSetType());
74              assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency());
75          }
76      }
77  
78      @Test
79      public void testPrepareCallWithResultSetHoldability() throws Exception {
80          final String sql = "select 'a' from dual";
81          final int resultSetType = 0;
82          final int resultSetConcurrency = 0;
83          final int resultSetHoldability = 0;
84          try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql, resultSetType, resultSetConcurrency,
85              resultSetHoldability)) {
86              final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate();
87              // assert
88              assertEquals(sql, testStatement.getSql());
89              assertEquals(resultSetType, testStatement.getResultSetType());
90              assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency());
91              assertEquals(resultSetHoldability, testStatement.getResultSetHoldability());
92          }
93      }
94  
95      @Test
96      public void testPrepareStatement() throws Exception {
97          final String sql = "select 'a' from dual";
98          try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql)) {
99              final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
100             // assert
101             assertEquals(sql, testStatement.getSql());
102         }
103     }
104 
105     @Test
106     public void testPrepareStatementWithAutoGeneratedKeys() throws Exception {
107         final String sql = "select 'a' from dual";
108         final int autoGeneratedKeys = 0;
109         try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, autoGeneratedKeys)) {
110             final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
111             // assert
112             assertEquals(sql, testStatement.getSql());
113             assertEquals(autoGeneratedKeys, testStatement.getAutoGeneratedKeys());
114         }
115     }
116 
117     @Test
118     public void testPrepareStatementWithColumnIndexes() throws Exception {
119         final String sql = "select 'a' from dual";
120         final int[] columnIndexes = {1};
121         try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, columnIndexes)) {
122             final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
123             // assert
124             assertEquals(sql, testStatement.getSql());
125             assertArrayEquals(columnIndexes, testStatement.getColumnIndexes());
126         }
127     }
128 
129     @Test
130     public void testPrepareStatementWithColumnNames() throws Exception {
131         final String sql = "select 'a' from dual";
132         final String[] columnNames = {"columnName1"};
133         try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, columnNames)) {
134             final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
135             // assert
136             assertEquals(sql, testStatement.getSql());
137             assertArrayEquals(columnNames, testStatement.getColumnNames());
138         }
139     }
140 
141     @Test
142     public void testPrepareStatementWithResultSetConcurrency() throws Exception {
143         final String sql = "select 'a' from dual";
144         final int resultSetType = 0;
145         final int resultSetConcurrency = 0;
146         try (
147             final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, resultSetType, resultSetConcurrency)) {
148             final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
149             // assert
150             assertEquals(sql, testStatement.getSql());
151             assertEquals(resultSetType, testStatement.getResultSetType());
152             assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency());
153         }
154     }
155 
156     @Test
157     public void testPrepareStatementWithResultSetHoldability() throws Exception {
158         final String sql = "select 'a' from dual";
159         final int resultSetType = 0;
160         final int resultSetConcurrency = 0;
161         final int resultSetHoldability = 0;
162         try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, resultSetType, resultSetConcurrency,
163             resultSetHoldability)) {
164             final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate();
165             // assert
166             assertEquals(sql, testStatement.getSql());
167             assertEquals(resultSetType, testStatement.getResultSetType());
168             assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency());
169             assertEquals(resultSetHoldability, testStatement.getResultSetHoldability());
170         }
171     }
172 
173     /**
174      * Tests DBCP-596 PoolingConnection.toString() causes StackOverflowError.
175      */
176     @Test
177     public void testToStringStackOverflow() throws SQLException {
178         // Also tests a possible NullPointerException in PoolingConnection.close()
179         try (PoolingConnection conn = new PoolingConnection(null)) {
180             final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
181             try (GenericKeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(conn, config)) {
182                 conn.setStatementPool(stmtPool);
183             }
184             conn.toString();
185         }
186     }
187 }