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.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.sql.Connection;
27  import java.sql.PreparedStatement;
28  import java.sql.SQLException;
29  
30  import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
31  import org.junit.jupiter.api.Assertions;
32  import org.junit.jupiter.api.BeforeEach;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   */
37  public class TestDelegatingConnection {
38  
39      /**
40       * Delegate that doesn't support read-only or auto-commit.
41       * It will merely take the input value of setReadOnly and
42       * setAutoCommit and discard it, to keep false.
43       */
44      static class NoReadOnlyOrAutoCommitConnection extends TesterConnection {
45          private final boolean readOnly = false;
46          private final boolean autoCommit = false;
47  
48          public NoReadOnlyOrAutoCommitConnection() {
49              super("","");
50          }
51  
52          @Override
53          public boolean getAutoCommit() {
54              return autoCommit;
55          }
56  
57          @Override
58          public boolean isReadOnly() throws SQLException {
59              return readOnly;
60          }
61  
62          @Override
63          public void setAutoCommit(final boolean autoCommit) {
64              // Do nothing
65          }
66  
67          @Override
68          public void setReadOnly(final boolean readOnly) {
69              // Do nothing
70          }
71      }
72  
73      /**
74       * Delegate that will throw RTE on toString
75       * Used to validate fix for DBCP-241
76       */
77      static class RTEGeneratingConnection extends TesterConnection {
78  
79          public RTEGeneratingConnection() {
80              super("","");
81          }
82  
83          @Override
84          public String toString() {
85              throw new RuntimeException("bang!");
86          }
87  
88      }
89  
90      private DelegatingConnection<? extends Connection> delegatingConnection;
91      private Connection connection;
92      private Connection connection2;
93      private TesterStatement testerStatement;
94      private TesterResultSet testerResultSet;
95  
96      @BeforeEach
97      public void setUp() throws Exception {
98          connection = new TesterConnection("test", "test");
99          connection2 = new TesterConnection("test", "test");
100         delegatingConnection = new DelegatingConnection<>(connection);
101         testerStatement = new TesterStatement(delegatingConnection);
102         testerResultSet = new TesterResultSet(testerStatement);
103     }
104 
105     @Test
106     public void testAutoCommitCaching() throws SQLException {
107         final Connection con = new NoReadOnlyOrAutoCommitConnection();
108         final DelegatingConnection<Connection> delCon = new DelegatingConnection<>(con);
109 
110         delCon.setAutoCommit(true);
111 
112         assertFalse(con.getAutoCommit());
113         assertFalse(delCon.getAutoCommit());
114     }
115 
116     @Test
117     public void testCheckOpen() throws Exception {
118         delegatingConnection.checkOpen();
119         delegatingConnection.close();
120         try {
121             delegatingConnection.checkOpen();
122             fail("Expecting SQLException");
123         } catch (final SQLException ex) {
124             // expected
125         }
126     }
127 
128     /**
129      * Verify fix for DBCP-241
130      */
131     @Test
132     public void testCheckOpenNull() throws Exception {
133         try {
134             delegatingConnection.close();
135             delegatingConnection.checkOpen();
136             fail("Expecting SQLException");
137         } catch (final SQLException ex) {
138             assertTrue(ex.getMessage().endsWith("is closed."));
139         }
140 
141         try {
142             delegatingConnection = new DelegatingConnection<>(null);
143             delegatingConnection.setClosedInternal(true);
144             delegatingConnection.checkOpen();
145             fail("Expecting SQLException");
146         } catch (final SQLException ex) {
147             assertTrue(ex.getMessage().endsWith("is null."));
148         }
149 
150         try {
151             final PoolingConnection pc = new PoolingConnection(connection2);
152             pc.setStatementPool(new GenericKeyedObjectPool<>(pc));
153             delegatingConnection = new DelegatingConnection<>(pc);
154             pc.close();
155             delegatingConnection.close();
156             try (PreparedStatement ps = delegatingConnection.prepareStatement("")){}
157             fail("Expecting SQLException");
158         } catch (final SQLException ex) {
159             assertTrue(ex.getMessage().endsWith("is closed."));
160         }
161 
162         try {
163             delegatingConnection = new DelegatingConnection<>(new RTEGeneratingConnection());
164             delegatingConnection.close();
165             delegatingConnection.checkOpen();
166             fail("Expecting SQLException");
167         } catch (final SQLException ex) {
168             assertTrue(ex.getMessage().endsWith("is closed."));
169         }
170     }
171 
172     @Test
173     public void testConnectionToString() throws Exception {
174         final String s = delegatingConnection.toString();
175         assertNotNull(s);
176         assertFalse(s.isEmpty());
177     }
178 
179     @Test
180     public void testGetDelegate() throws Exception {
181         assertEquals(connection, delegatingConnection.getDelegate());
182     }
183 
184     @Test
185     public void testIsClosed() throws Exception {
186         delegatingConnection.checkOpen();
187         assertFalse(delegatingConnection.isClosed());
188         delegatingConnection.close();
189         assertTrue(delegatingConnection.isClosed());
190     }
191 
192     @Test
193     public void testIsClosedNullDelegate() throws Exception {
194         delegatingConnection.checkOpen();
195         assertFalse(delegatingConnection.isClosed());
196         delegatingConnection.setDelegate(null);
197         assertTrue(delegatingConnection.isClosed());
198     }
199 
200     @Test
201     public void testPassivateWithResultSetCloseException() {
202         try {
203             testerResultSet.setSqlExceptionOnClose(true);
204             delegatingConnection.addTrace(testerResultSet);
205             delegatingConnection.passivate();
206             Assertions.fail("Expected SQLExceptionList");
207         } catch (final SQLException e) {
208             Assertions.assertTrue(e instanceof SQLExceptionList);
209             Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size());
210         } finally {
211             testerResultSet.setSqlExceptionOnClose(false);
212         }
213     }
214 
215     @Test
216     public void testPassivateWithResultSetCloseExceptionAndStatementCloseException() {
217         try {
218             testerStatement.setSqlExceptionOnClose(true);
219             testerResultSet.setSqlExceptionOnClose(true);
220             delegatingConnection.addTrace(testerStatement);
221             delegatingConnection.addTrace(testerResultSet);
222             delegatingConnection.passivate();
223             Assertions.fail("Expected SQLExceptionList");
224         } catch (final SQLException e) {
225             Assertions.assertTrue(e instanceof SQLExceptionList);
226             Assertions.assertEquals(2, ((SQLExceptionList) e).getCauseList().size());
227         } finally {
228             testerStatement.setSqlExceptionOnClose(false);
229         testerResultSet.setSqlExceptionOnClose(false);
230         }
231     }
232 
233     @Test
234     public void testPassivateWithStatementCloseException() {
235         try {
236             testerStatement.setSqlExceptionOnClose(true);
237             delegatingConnection.addTrace(testerStatement);
238             delegatingConnection.passivate();
239             Assertions.fail("Expected SQLExceptionList");
240         } catch (final SQLException e) {
241             Assertions.assertTrue(e instanceof SQLExceptionList);
242             Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size());
243         } finally {
244             testerStatement.setSqlExceptionOnClose(false);
245         }
246     }
247 
248     @Test
249     public void testReadOnlyCaching() throws SQLException {
250         final Connection con = new NoReadOnlyOrAutoCommitConnection();
251         final DelegatingConnection<Connection> delCon = new DelegatingConnection<>(con);
252 
253         delCon.setReadOnly(true);
254 
255         assertFalse(con.isReadOnly());
256         assertFalse(delCon.isReadOnly());
257     }
258 
259 }