1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2.managed;
19
20 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotEquals;
24 import static org.junit.jupiter.api.Assertions.assertNotNull;
25 import static org.junit.jupiter.api.Assertions.assertSame;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28
29 import java.sql.CallableStatement;
30 import java.sql.Connection;
31 import java.sql.PreparedStatement;
32 import java.sql.ResultSet;
33 import java.sql.SQLException;
34 import java.sql.Statement;
35
36 import javax.transaction.Synchronization;
37 import javax.transaction.Transaction;
38
39 import org.apache.commons.dbcp2.DelegatingConnection;
40 import org.junit.jupiter.api.AfterEach;
41 import org.junit.jupiter.api.Assertions;
42 import org.junit.jupiter.api.BeforeEach;
43 import org.junit.jupiter.api.Test;
44 import org.junit.jupiter.api.function.ThrowingSupplier;
45
46
47
48
49 public class TestManagedDataSourceInTx extends TestManagedDataSource {
50
51
52 @Override
53 protected void assertBackPointers(final Connection conn, final Statement statement) throws SQLException {
54 assertFalse(conn.isClosed());
55 assertFalse(isClosed(statement));
56
57 assertSame(conn, statement.getConnection(),
58 "statement.getConnection() should return the exact same connection instance that was used to create the statement");
59
60 try (ResultSet resultSet = statement.getResultSet()) {
61 assertFalse(isClosed(resultSet));
62 assertSame(statement, resultSet.getStatement(),
63 "resultSet.getStatement() should return the exact same statement instance that was used to create the result set");
64
65 try (ResultSet executeResultSet = statement.executeQuery("select * from dual")) {
66 assertFalse(isClosed(executeResultSet));
67 assertSame(statement, executeResultSet.getStatement(),
68 "resultSet.getStatement() should return the exact same statement instance that was used to create the result set");
69 }
70
71 try (ResultSet keysResultSet = statement.getGeneratedKeys()) {
72 assertFalse(isClosed(keysResultSet));
73 assertSame(statement, keysResultSet.getStatement(),
74 "resultSet.getStatement() should return the exact same statement instance that was used to create the result set");
75 }
76 if (statement instanceof PreparedStatement) {
77 final PreparedStatement preparedStatement = (PreparedStatement) statement;
78 try (ResultSet preparedResultSet = preparedStatement.executeQuery()) {
79 assertFalse(isClosed(preparedResultSet));
80 assertSame(statement, preparedResultSet.getStatement(),
81 "resultSet.getStatement() should return the exact same statement instance that was used to create the result set");
82 }
83 }
84
85 resultSet.getStatement().getConnection().close();
86 }
87 }
88
89 @Override
90 @BeforeEach
91 public void setUp() throws Exception {
92 super.setUp();
93 transactionManager.begin();
94 }
95
96 @Override
97 @AfterEach
98 public void tearDown() throws Exception {
99 if (transactionManager.getTransaction() != null) {
100 transactionManager.commit();
101 }
102 super.tearDown();
103 }
104
105 @Override
106 @Test
107 public void testAutoCommitBehavior() throws Exception {
108 final Connection connection = newConnection();
109
110
111 assertFalse(connection.getAutoCommit(), "Auto-commit should be disabled");
112
113
114 assertThrows(SQLException.class, () -> connection.setAutoCommit(true), "setAutoCommit method should be disabled while enlisted in a transaction");
115
116
117 assertFalse(connection.getAutoCommit(), "Auto-commit should be disabled");
118
119
120 connection.close();
121 }
122
123 @Override
124 @Test
125 public void testClearWarnings() throws Exception {
126
127 Connection connection = newConnection();
128 assertNotNull(connection);
129
130
131 final CallableStatement statement = connection.prepareCall("warning");
132 assertNotNull(connection.getWarnings());
133
134
135 final Connection sharedConnection = newConnection();
136
137
138 assertNotNull(sharedConnection.getWarnings());
139
140
141 connection.close();
142 connection = newConnection();
143
144
145 assertNotNull(connection.getWarnings());
146 assertNotNull(sharedConnection.getWarnings());
147
148 statement.close();
149 sharedConnection.close();
150 connection.close();
151 }
152
153 @Test
154 void testCloseInTransaction() throws Exception {
155 try (DelegatingConnection<?> connectionA = (DelegatingConnection<?>) newConnection();
156 DelegatingConnection<?> connectionB = (DelegatingConnection<?>) newConnection()) {
157 assertNotEquals(connectionA, connectionB);
158 assertNotEquals(connectionB, connectionA);
159 assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
160 assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
161 }
162
163 final Connection connection = newConnection();
164
165 assertFalse(connection.isClosed(), "Connection should be open");
166
167 connection.close();
168
169 assertTrue(connection.isClosed(), "Connection should be closed");
170 }
171
172 @Test
173 void testCommit() throws Exception {
174 try (Connection connection = newConnection()) {
175
176 assertFalse(connection.isClosed(), "Connection should be open");
177
178 assertThrows(SQLException.class, connection::commit, "commit method should be disabled while enlisted in a transaction");
179
180 assertFalse(connection.isClosed(), "Connection should be open");
181
182 }
183 }
184
185 @Override
186 @Test
187 public void testConnectionReturnOnCommit() throws Exception {
188
189 }
190
191 @Override
192 @Test
193 public void testConnectionsAreDistinct() throws Exception {
194 final Connection[] conn = new Connection[getMaxTotal()];
195 for (int i = 0; i < conn.length; i++) {
196 conn[i] = newConnection();
197 for (int j = 0; j < i; j++) {
198
199 Assertions.assertNotSame(conn[j], conn[i]);
200
201
202 Assertions.assertNotEquals(conn[j], conn[i]);
203
204 Assertions.assertEquals(((DelegatingConnection<?>) conn[j]).getInnermostDelegateInternal(),
205 ((DelegatingConnection<?>) conn[i]).getInnermostDelegateInternal());
206 }
207 }
208 for (final Connection element : conn) {
209 element.close();
210 }
211 }
212
213 @Test
214 void testDoubleReturn() throws Exception {
215 transactionManager.getTransaction().registerSynchronization(new Synchronization() {
216 private ManagedConnection<?> conn;
217
218 @Override
219 public void afterCompletion(final int i) {
220 final int numActive = pool.getNumActive();
221 try {
222 conn.checkOpen();
223 } catch (final Exception e) {
224
225 }
226 assertEquals(numActive, pool.getNumActive());
227 assertDoesNotThrow(conn::close, "Should have been able to close the connection");
228
229 }
230
231 @Override
232 public void beforeCompletion() {
233 assertDoesNotThrow(() -> conn = (ManagedConnection<?>) ds.getConnection(), "Could not get connection");
234 }
235 });
236 transactionManager.commit();
237 }
238
239 @Test
240 void testGetConnectionInAfterCompletion() throws Exception {
241 try (DelegatingConnection<?> connection = (DelegatingConnection<?>) newConnection()) {
242
243 transactionManager.getTransaction().registerSynchronization(new SynchronizationAdapter() {
244 @Override
245 public void afterCompletion(final int i) {
246 final Connection connection1 = assertDoesNotThrow((ThrowingSupplier<Connection>) ds::getConnection);
247 assertThrows(SQLException.class, () -> connection1.getWarnings(), "Could operate on closed connection");
248 }
249 });
250 }
251 transactionManager.commit();
252 }
253
254 @Override
255 @Test
256 public void testHashCode() throws Exception {
257 try (Connection conn1 = newConnection()) {
258 assertNotNull(conn1);
259 try (Connection conn2 = newConnection()) {
260 assertNotNull(conn2);
261
262
263 Assertions.assertNotEquals(conn1.hashCode(), conn2.hashCode());
264 }
265 }
266 }
267
268
269
270
271 @Override
272 @Test
273 public void testManagedConnectionEqualsFail() throws Exception {
274
275
276
277 }
278
279 @Override
280 @Test
281 public void testMaxTotal() throws Exception {
282 final Transaction[] transactions = new Transaction[getMaxTotal()];
283 final Connection[] c = new Connection[getMaxTotal()];
284 for (int i = 0; i < c.length; i++) {
285
286 c[i] = newConnection();
287 assertNotNull(c[i]);
288
289
290 transactions[i] = transactionManager.suspend();
291 assertNotNull(transactions[i]);
292 transactionManager.begin();
293 }
294
295 try {
296 assertThrows(SQLException.class, this::newConnection, "Allowed to open more than DefaultMaxTotal connections.");
297
298
299 } finally {
300 transactionManager.commit();
301 for (int i = 0; i < c.length; i++) {
302 transactionManager.resume(transactions[i]);
303 c[i].close();
304 transactionManager.commit();
305 }
306 }
307 }
308
309 @Override
310 @Test
311 public void testNestedConnections() {
312
313 }
314
315 @Test
316 void testReadOnly() throws Exception {
317 try (Connection connection = newConnection()) {
318
319
320 assertTrue(connection.isReadOnly(), "Connection be read-only");
321
322 assertThrows(SQLException.class, () -> connection.setReadOnly(true), "setReadOnly method should be disabled while enlisted in a transaction");
323
324 assertTrue(connection.isReadOnly(), "Connection be read-only");
325
326 assertThrows(SQLException.class, () -> connection.setReadOnly(false), "setReadOnly method should be disabled while enlisted in a transaction");
327
328 assertTrue(connection.isReadOnly(), "Connection be read-only");
329
330 }
331 }
332
333 @Override
334 @Test
335 public void testSharedConnection() throws Exception {
336 try (DelegatingConnection<?> connectionA = (DelegatingConnection<?>) newConnection();
337 DelegatingConnection<?> connectionB = (DelegatingConnection<?>) newConnection()) {
338 assertNotEquals(connectionA, connectionB);
339 assertNotEquals(connectionB, connectionA);
340 assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
341 assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
342 }
343 }
344
345 @Test
346 void testSharedTransactionConversion() throws Exception {
347 try (DelegatingConnection<?> connectionA = (DelegatingConnection<?>) newConnection();
348 DelegatingConnection<?> connectionB = (DelegatingConnection<?>) newConnection()) {
349
350 assertNotEquals(connectionA, connectionB);
351 assertNotEquals(connectionB, connectionA);
352 assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
353 assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
354
355 transactionManager.commit();
356
357
358 connectionA.getAutoCommit();
359 connectionB.getAutoCommit();
360
361
362 assertNotEquals(connectionA, connectionB);
363 assertNotEquals(connectionB, connectionA);
364 assertFalse(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
365 assertFalse(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
366
367 transactionManager.begin();
368
369
370 connectionA.getAutoCommit();
371 connectionB.getAutoCommit();
372
373
374 assertNotEquals(connectionA, connectionB);
375 assertNotEquals(connectionB, connectionA);
376 assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
377 assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
378 }
379 }
380 }