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.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.sql.Connection;
28  import java.sql.DriverManager;
29  import java.sql.SQLException;
30  import java.sql.Savepoint;
31  
32  import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
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   * Tests {@link DelegatingConnection}.
40   */
41  public class TestDelegatingConnection {
42  
43      /**
44       * Delegate that doesn't support read-only or auto-commit. It will merely take the input value of setReadOnly and setAutoCommit and discard it, to keep
45       * false.
46       */
47      static final class NoReadOnlyOrAutoCommitConnection extends TesterConnection {
48          private final boolean readOnly = false;
49          private final boolean autoCommit = false;
50  
51          public NoReadOnlyOrAutoCommitConnection() {
52              super("", "");
53          }
54  
55          @Override
56          public boolean getAutoCommit() {
57              return autoCommit;
58          }
59  
60          @Override
61          public boolean isReadOnly() throws SQLException {
62              return readOnly;
63          }
64  
65          @Override
66          public void setAutoCommit(final boolean autoCommit) {
67              // Do nothing
68          }
69  
70          @Override
71          public void setReadOnly(final boolean readOnly) {
72              // Do nothing
73          }
74      }
75  
76      /**
77       * Delegate that will throw RTE on toString Used to validate fix for DBCP-241
78       */
79      static final class RTEGeneratingConnection extends TesterConnection {
80  
81          public RTEGeneratingConnection() {
82              super("", "");
83          }
84  
85          @Override
86          public String toString() {
87              throw new RuntimeException("bang!");
88          }
89  
90      }
91  
92      private DelegatingConnection<? extends Connection> delegatingConnection;
93      private Connection connection;
94      private Connection connection2;
95      private DelegatingConnection<? extends Connection> h2DConnection;
96      private TesterStatement testerStatement;
97      private TesterResultSet testerResultSet;
98  
99      @AfterEach
100     public void afterEach() throws SQLException {
101         testerStatement.setSqlExceptionOnClose(false);
102         testerResultSet.setSqlExceptionOnClose(false);
103         h2DConnection.close();
104     }
105 
106     @BeforeEach
107     public void setUp() throws Exception {
108         connection = new TesterConnection("test", "test");
109         connection2 = new TesterConnection("test", "test");
110         delegatingConnection = new DelegatingConnection<>(connection);
111         testerStatement = new TesterStatement(delegatingConnection);
112         testerResultSet = new TesterResultSet(testerStatement);
113         h2DConnection = new DelegatingConnection<>(DriverManager.getConnection("jdbc:h2:mem:test"));
114     }
115 
116     @Test
117     void testAbort() throws Exception {
118         h2DConnection.abort(r -> {
119         });
120     }
121 
122     @Test
123     void testAutoCommitCaching() throws SQLException {
124         final Connection con = new NoReadOnlyOrAutoCommitConnection();
125         final DelegatingConnection<Connection> delCon = new DelegatingConnection<>(con);
126 
127         delCon.setAutoCommit(true);
128 
129         assertFalse(con.getAutoCommit());
130         assertFalse(delCon.getAutoCommit());
131     }
132 
133     @Test
134     void testCheckOpen() throws Exception {
135         delegatingConnection.checkOpen();
136         delegatingConnection.close();
137         assertThrows(SQLException.class, delegatingConnection::checkOpen);
138     }
139 
140     /**
141      * Verify fix for DBCP-241
142      */
143     @Test
144     void testCheckOpenNull() throws Exception {
145         delegatingConnection.close();
146         SQLException e = assertThrows(SQLException.class, delegatingConnection::checkOpen);
147         assertTrue(e.getMessage().endsWith("is closed."));
148 
149         delegatingConnection = new DelegatingConnection<>(null);
150         delegatingConnection.setClosedInternal(true);
151         e = assertThrows(SQLException.class, delegatingConnection::checkOpen);
152         assertTrue(e.getMessage().endsWith("is null."));
153 
154         final PoolingConnection pc = new PoolingConnection(connection2);
155         pc.setStatementPool(new GenericKeyedObjectPool<>(pc));
156         delegatingConnection = new DelegatingConnection<>(pc);
157         pc.close();
158         delegatingConnection.close();
159         e = assertThrows(SQLException.class, () -> delegatingConnection.prepareStatement(""));
160         assertTrue(e.getMessage().endsWith("is closed."));
161 
162         delegatingConnection = new DelegatingConnection<>(new RTEGeneratingConnection());
163         delegatingConnection.close();
164         e = assertThrows(SQLException.class, delegatingConnection::checkOpen);
165         assertTrue(e.getMessage().endsWith("is closed."));
166     }
167 
168     @Test
169     void testCommit() throws Exception {
170         h2DConnection.commit();
171     }
172 
173     @Test
174     void testConnectionToString() throws Exception {
175         final String s = delegatingConnection.toString();
176         assertNotNull(s);
177         assertFalse(s.isEmpty());
178     }
179 
180     @Test
181     void testCreateArrayOf() throws Exception {
182         assertNotNull(h2DConnection.createArrayOf("CHARACTER", new Object[] { "A", "B" }));
183     }
184 
185     @Test
186     void testCreateBlob() throws Exception {
187         assertNotNull(h2DConnection.createBlob());
188     }
189 
190     @Test
191     void testCreateClob() throws Exception {
192         assertNotNull(h2DConnection.createClob());
193     }
194 
195     @Test
196     void testCreateNClob() throws Exception {
197         assertNotNull(h2DConnection.createNClob());
198     }
199 
200     @Test
201     void testCreateSQLXML() throws Exception {
202         assertNotNull(h2DConnection.createSQLXML());
203     }
204 
205     @Test
206     void testCreateStruct() throws Exception {
207         // not supported by H2
208         assertThrows(SQLException.class, () -> h2DConnection.createStruct("CHARACTER", new Object[] { "A", "B" }));
209     }
210 
211     @Test
212     void testGetCacheState() throws Exception {
213         assertTrue(h2DConnection.getCacheState());
214     }
215 
216     @Test
217     void testGetClientInfo() throws Exception {
218         assertNotNull(h2DConnection.getClientInfo());
219     }
220 
221     @Test
222     void testGetClientInfoString() throws Exception {
223         assertNull(h2DConnection.getClientInfo("xyz"));
224     }
225 
226     @Test
227     void testGetDefaultQueryTimeout() throws Exception {
228         assertNull(h2DConnection.getDefaultQueryTimeout());
229     }
230 
231     @Test
232     void testGetDefaultQueryTimeoutDuration() throws Exception {
233         assertNull(h2DConnection.getDefaultQueryTimeoutDuration());
234     }
235 
236     @Test
237     void testGetDelegate() throws Exception {
238         assertEquals(connection, delegatingConnection.getDelegate());
239     }
240 
241     @Test
242     void testGetHoldability() throws Exception {
243         assertEquals(1, h2DConnection.getHoldability());
244     }
245 
246     @Test
247     void testGetNetworkTimeout() throws Exception {
248         assertEquals(0, h2DConnection.getNetworkTimeout());
249     }
250 
251     @Test
252     void testGetTypeMap() throws Exception {
253         assertNull(h2DConnection.getTypeMap());
254     }
255 
256     @Test
257     void testIsClosed() throws Exception {
258         delegatingConnection.checkOpen();
259         assertFalse(delegatingConnection.isClosed());
260         delegatingConnection.close();
261         assertTrue(delegatingConnection.isClosed());
262     }
263 
264     @Test
265     void testIsClosedNullDelegate() throws Exception {
266         delegatingConnection.checkOpen();
267         assertFalse(delegatingConnection.isClosed());
268         delegatingConnection.setDelegate(null);
269         assertTrue(delegatingConnection.isClosed());
270     }
271 
272     @SuppressWarnings("resource")
273     @Test
274     void testIsWrapperFor() throws Exception {
275         assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getClass()));
276         assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getDelegate().getClass()));
277         assertThrows(SQLException.class, () -> delegatingConnection.isWrapperFor(Integer.class));
278     }
279 
280     @Test
281     void testNativeSQL() throws Exception {
282         assertNotNull(h2DConnection.nativeSQL("select 1"));
283     }
284 
285     @Test
286     void testPassivateWithResultSetCloseException() {
287         testerResultSet.setSqlExceptionOnClose(true);
288         delegatingConnection.addTrace(testerResultSet);
289         final SQLException e = assertThrows(SQLException.class, delegatingConnection::passivate);
290         Assertions.assertInstanceOf(SQLExceptionList.class, e);
291         Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size());
292     }
293 
294     @Test
295     void testPassivateWithResultSetCloseExceptionAndStatementCloseException() {
296         testerStatement.setSqlExceptionOnClose(true);
297         testerResultSet.setSqlExceptionOnClose(true);
298         delegatingConnection.addTrace(testerStatement);
299         delegatingConnection.addTrace(testerResultSet);
300         final SQLException e = assertThrows(SQLException.class, delegatingConnection::passivate);
301         Assertions.assertInstanceOf(SQLExceptionList.class, e);
302         Assertions.assertEquals(2, ((SQLExceptionList) e).getCauseList().size());
303     }
304 
305     @Test
306     void testPassivateWithStatementCloseException() {
307         testerStatement.setSqlExceptionOnClose(true);
308         delegatingConnection.addTrace(testerStatement);
309         final SQLException e = assertThrows(SQLException.class, delegatingConnection::passivate);
310         Assertions.assertInstanceOf(SQLExceptionList.class, e);
311         Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size());
312     }
313 
314     @Test
315     void testReadOnlyCaching() throws SQLException {
316         final Connection con = new NoReadOnlyOrAutoCommitConnection();
317         final DelegatingConnection<Connection> delCon = new DelegatingConnection<>(con);
318 
319         delCon.setReadOnly(true);
320 
321         assertFalse(con.isReadOnly());
322         assertFalse(delCon.isReadOnly());
323     }
324 
325     @Test
326     void testReleaseSavepoint() throws Exception {
327         final Savepoint s = h2DConnection.setSavepoint();
328         h2DConnection.releaseSavepoint(s);
329     }
330 
331     @Test
332     void testRollback() throws Exception {
333         h2DConnection.rollback();
334     }
335 
336     @Test
337     void testRollbackSavepoint() throws Exception {
338         h2DConnection.setAutoCommit(false);
339         try {
340             h2DConnection.rollback(h2DConnection.setSavepoint());
341         } finally {
342             h2DConnection.setAutoCommit(true);
343         }
344     }
345 
346     @Test
347     void testSetClientInfo() throws Exception {
348         // TODO
349         // h2DConnection.setClientInfo("ApplicationName", "app1");
350     }
351 
352     @Test
353     void testSetDefaultQueryTimeout() throws Exception {
354         final int expected = 1;
355         delegatingConnection.setDefaultQueryTimeout(expected);
356         assertEquals(expected, delegatingConnection.getDefaultQueryTimeout());
357     }
358 
359     @Test
360     void testSetHoldability() throws Exception {
361         final int expected = 1;
362         h2DConnection.setHoldability(expected);
363         assertEquals(expected, h2DConnection.getHoldability());
364     }
365 
366     @Test
367     void testSetNetworkTimeout() throws Exception {
368         h2DConnection.setNetworkTimeout(r -> {
369         }, 1);
370         assertEquals(0, h2DConnection.getNetworkTimeout());
371     }
372 
373     @Test
374     void testSetSavepoint() throws Exception {
375         h2DConnection.setSavepoint();
376     }
377 
378     @SuppressWarnings("javadoc")
379     @Test
380     void testUnwrap() throws Exception {
381         assertNotNull(delegatingConnection.unwrap(delegatingConnection.getClass()));
382         assertNotNull(delegatingConnection.unwrap(delegatingConnection.getDelegate().getClass()));
383         assertThrows(SQLException.class, () -> delegatingConnection.unwrap(Integer.class));
384     }
385 
386 }