1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2.cpdsadapter;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
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 import static org.junit.jupiter.api.Assertions.fail;
27
28 import java.io.PrintWriter;
29 import java.sql.Connection;
30 import java.sql.PreparedStatement;
31 import java.sql.ResultSet;
32 import java.sql.SQLException;
33 import java.sql.SQLFeatureNotSupportedException;
34 import java.sql.Statement;
35 import java.time.Duration;
36 import java.util.Properties;
37
38 import javax.naming.NamingException;
39 import javax.naming.Reference;
40 import javax.naming.StringRefAddr;
41 import javax.sql.DataSource;
42
43 import org.apache.commons.dbcp2.Constants;
44 import org.apache.commons.dbcp2.DelegatingPreparedStatement;
45 import org.apache.commons.dbcp2.DelegatingStatement;
46 import org.apache.commons.dbcp2.PStmtKey;
47 import org.apache.commons.dbcp2.PoolablePreparedStatement;
48 import org.apache.commons.dbcp2.TestUtils;
49 import org.apache.commons.dbcp2.datasources.SharedPoolDataSource;
50 import org.apache.commons.pool2.impl.DefaultPooledObject;
51 import org.junit.jupiter.api.Assertions;
52 import org.junit.jupiter.api.BeforeEach;
53 import org.junit.jupiter.api.Test;
54
55
56
57
58 public class TestDriverAdapterCPDS {
59
60 private static final class ThreadDbcp367 extends Thread {
61
62 private final DataSource dataSource;
63
64 private volatile boolean failed;
65
66 public ThreadDbcp367(final DataSource dataSource) {
67 this.dataSource = dataSource;
68 }
69
70 public boolean isFailed() {
71 return failed;
72 }
73
74 @Override
75 public void run() {
76 Connection conn = null;
77 try {
78 for (int j = 0; j < 5000; j++) {
79 conn = dataSource.getConnection();
80 conn.close();
81 }
82 } catch (final SQLException sqle) {
83 failed = true;
84 sqle.printStackTrace();
85 }
86 }
87 }
88
89 @SuppressWarnings("resource")
90 private static void checkAfterClose(final Connection element, final PStmtKey pStmtKey) throws SQLException {
91 final ConnectionImpl connectionImpl = (ConnectionImpl) element;
92 assertNull(connectionImpl.getInnermostDelegate());
93 assertNotNull(connectionImpl.getInnermostDelegateInternal());
94 final PooledConnectionImpl pooledConnectionImpl = connectionImpl.getPooledConnectionImpl();
95 assertNotNull(pooledConnectionImpl);
96
97 pooledConnectionImpl.destroyObject(pStmtKey, null);
98 pooledConnectionImpl.destroyObject(pStmtKey, new DefaultPooledObject<>(null));
99 pooledConnectionImpl.destroyObject(pStmtKey, new DefaultPooledObject<>(new DelegatingPreparedStatement(null, null)));
100 }
101
102 private DriverAdapterCPDS pcds;
103
104 @BeforeEach
105 public void setUp() throws Exception {
106 pcds = new DriverAdapterCPDS();
107 pcds.setDriver("org.apache.commons.dbcp2.TesterDriver");
108 pcds.setUrl("jdbc:apache:commons:testdriver");
109 pcds.setUser("foo");
110 pcds.setPassword("bar");
111 pcds.setPoolPreparedStatements(true);
112 }
113
114 @Test
115 public void testClose()
116 throws Exception {
117 final Connection[] c = new Connection[10];
118 for (int i = 0; i < c.length; i++) {
119 c[i] = pcds.getPooledConnection().getConnection();
120 }
121
122
123 c[0].close();
124 assertTrue(c[0].isClosed());
125
126 c[0] = pcds.getPooledConnection().getConnection();
127
128 for (final Connection element : c) {
129 element.close();
130 checkAfterClose(element, null);
131 }
132
133
134 for (int i = 0; i < c.length; i++) {
135 c[i] = pcds.getPooledConnection().getConnection();
136 }
137 for (final Connection element : c) {
138 element.close();
139 checkAfterClose(element, null);
140 }
141 }
142
143 @Test
144 public void testCloseWithUserName()
145 throws Exception {
146 final Connection[] c = new Connection[10];
147 for (int i = 0; i < c.length; i++) {
148 c[i] = pcds.getPooledConnection("u1", "p1").getConnection();
149 }
150
151
152 c[0].close();
153 assertTrue(c[0].isClosed());
154
155 c[0] = pcds.getPooledConnection("u1", "p1").getConnection();
156
157 for (final Connection element : c) {
158 element.close();
159 checkAfterClose(element, null);
160 }
161
162
163 for (int i = 0; i < c.length; i++) {
164 c[i] = pcds.getPooledConnection("u1", "p1").getConnection();
165 }
166 for (final Connection element : c) {
167 element.close();
168 checkAfterClose(element, null);
169 }
170 }
171
172
173 @Test
174 public void testDbcp367() throws Exception {
175 final ThreadDbcp367[] threads = new ThreadDbcp367[200];
176
177 pcds.setPoolPreparedStatements(true);
178 pcds.setMaxPreparedStatements(-1);
179 pcds.setAccessToUnderlyingConnectionAllowed(true);
180
181 try (final SharedPoolDataSource spds = new SharedPoolDataSource()) {
182 spds.setConnectionPoolDataSource(pcds);
183 spds.setMaxTotal(threads.length + 10);
184 spds.setDefaultMaxWait(Duration.ofMillis(-1));
185 spds.setDefaultMaxIdle(10);
186 spds.setDefaultAutoCommit(Boolean.FALSE);
187
188 spds.setValidationQuery("SELECT 1");
189 spds.setDefaultDurationBetweenEvictionRuns(Duration.ofSeconds(10));
190 spds.setDefaultNumTestsPerEvictionRun(-1);
191 spds.setDefaultTestWhileIdle(true);
192 spds.setDefaultTestOnBorrow(true);
193 spds.setDefaultTestOnReturn(false);
194
195 for (int i = 0; i < threads.length; i++) {
196 threads[i] = new ThreadDbcp367(spds);
197 threads[i].start();
198 }
199
200 for (int i = 0; i < threads.length; i++) {
201 threads[i].join();
202 Assertions.assertFalse(threads[i].isFailed(), "Thread " + i + " has failed");
203 }
204 }
205 }
206
207 @SuppressWarnings("deprecation")
208 @Test
209 public void testDeprecatedAccessors() {
210 int i = 0;
211
212 i++;
213 pcds.setMinEvictableIdleTimeMillis(i);
214 assertEquals(i, pcds.getMinEvictableIdleTimeMillis());
215 assertEquals(Duration.ofMillis(i), pcds.getMinEvictableIdleDuration());
216
217 i++;
218 pcds.setTimeBetweenEvictionRunsMillis(i);
219 assertEquals(i, pcds.getTimeBetweenEvictionRunsMillis());
220 assertEquals(Duration.ofMillis(i), pcds.getDurationBetweenEvictionRuns());
221 }
222
223 @Test
224 public void testGetObjectInstance() throws Exception {
225 final Reference ref = pcds.getReference();
226 final Object o = pcds.getObjectInstance(ref, null, null, null);
227 assertEquals(pcds.getDriver(), ((DriverAdapterCPDS) o).getDriver());
228 }
229
230 @Test
231 public void testGetObjectInstanceChangeDescription() throws Exception {
232 final Reference ref = pcds.getReference();
233 for (int i = 0; i < ref.size(); i++) {
234 if (ref.get(i).getType().equals("description")) {
235 ref.remove(i);
236 break;
237 }
238 }
239 ref.add(new StringRefAddr("description", "anything"));
240 final Object o = pcds.getObjectInstance(ref, null, null, null);
241 assertEquals(pcds.getDescription(), ((DriverAdapterCPDS) o).getDescription());
242 }
243
244 @Test
245 public void testGetObjectInstanceNull() throws Exception {
246 final Object o = pcds.getObjectInstance(null, null, null, null);
247 assertNull(o);
248 }
249
250 @Test
251 public void testGetParentLogger() {
252 assertThrows(SQLFeatureNotSupportedException.class, pcds::getParentLogger);
253 }
254
255 @Test
256 public void testGetReference() throws NamingException {
257 final Reference ref = pcds.getReference();
258 assertEquals(pcds.getDriver(), ref.get("driver").getContent());
259 assertEquals(pcds.getDescription(), ref.get("description").getContent());
260 }
261
262 @Test
263 public void testGettersAndSetters() {
264 pcds.setUser("foo");
265 assertEquals("foo", pcds.getUser());
266 pcds.setPassword("bar");
267 assertEquals("bar", pcds.getPassword());
268 pcds.setPassword(new char[] {'a', 'b'});
269 assertArrayEquals(new char[] {'a', 'b'}, pcds.getPasswordCharArray());
270 final PrintWriter pw = new PrintWriter(System.err);
271 pcds.setLogWriter(pw);
272 @SuppressWarnings("resource")
273 final PrintWriter logWriter = pcds.getLogWriter();
274 assertEquals(pw, logWriter);
275 pcds.setLoginTimeout(10);
276 assertEquals(10, pcds.getLoginTimeout());
277 pcds.setMaxIdle(100);
278 assertEquals(100, pcds.getMaxIdle());
279 pcds.setDurationBetweenEvictionRuns(Duration.ofMillis(100));
280 assertEquals(100, pcds.getDurationBetweenEvictionRuns().toMillis());
281 pcds.setNumTestsPerEvictionRun(1);
282 assertEquals(1, pcds.getNumTestsPerEvictionRun());
283 pcds.setMinEvictableIdleDuration(Duration.ofMillis(11));
284 assertEquals(Duration.ofMillis(11), pcds.getMinEvictableIdleDuration());
285 pcds.setDescription("jo");
286 assertEquals("jo", pcds.getDescription());
287 }
288
289
290
291
292 @Test
293 public void testIncorrectPassword() throws Exception
294 {
295 pcds.getPooledConnection("u2", "p2").close();
296 try {
297
298 pcds.getPooledConnection("u1", "zlsafjk");
299 fail("Able to retrieve connection with incorrect password");
300 } catch (final SQLException e1) {
301
302
303 }
304
305
306 pcds.getPooledConnection("u1", "p1").close();
307 try {
308 pcds.getPooledConnection("u1", "x");
309 fail("Able to retrieve connection with incorrect password");
310 }
311 catch (final SQLException e) {
312 if (!e.getMessage().startsWith("x is not the correct password")) {
313 throw e;
314 }
315
316 }
317
318
319 pcds.getPooledConnection("u1", "p1").close();
320 }
321
322
323
324
325 @Test
326 public void testNullValidationQuery() throws Exception {
327 try (final SharedPoolDataSource spds = new SharedPoolDataSource()) {
328 spds.setConnectionPoolDataSource(pcds);
329 spds.setDefaultTestOnBorrow(true);
330 try (final Connection c = spds.getConnection()) {
331
332 }
333 }
334 }
335
336 @Test
337 public void testSetConnectionProperties() throws Exception {
338
339 pcds.setUser("bad");
340
341
342 final Properties properties = new Properties();
343 properties.put(Constants.KEY_USER, "foo");
344 properties.put(Constants.KEY_PASSWORD, pcds.getPassword());
345 pcds.setConnectionProperties(properties);
346 pcds.getPooledConnection().close();
347 assertEquals("foo", pcds.getUser());
348
349 properties.put("password", "bad");
350
351 assertEquals("bar", pcds.getPassword());
352
353
354 pcds.getPooledConnection("foo", "bar").close();
355 assertEquals("bar", pcds.getConnectionProperties().getProperty("password"));
356 }
357
358 @Test
359 public void testSetConnectionPropertiesConnectionCalled() throws Exception {
360 final Properties properties = new Properties();
361
362 pcds.getPooledConnection().close();
363 assertThrows(IllegalStateException.class, () -> pcds.setConnectionProperties(properties));
364 }
365
366 @Test
367 public void testSetConnectionPropertiesNull() throws Exception {
368 pcds.setConnectionProperties(null);
369 }
370
371 @Test
372 public void testSetPasswordNull() throws Exception {
373 pcds.setPassword("Secret");
374 assertEquals("Secret", pcds.getPassword());
375 pcds.setPassword((char[]) null);
376 assertNull(pcds.getPassword());
377 }
378
379 @Test
380 public void testSetPasswordNullWithConnectionProperties() throws Exception {
381 pcds.setConnectionProperties(new Properties());
382 pcds.setPassword("Secret");
383 assertEquals("Secret", pcds.getPassword());
384 pcds.setPassword((char[]) null);
385 assertNull(pcds.getPassword());
386 }
387
388 @Test
389 public void testSetPasswordThenModCharArray() {
390 final char[] pwd = {'a'};
391 pcds.setPassword(pwd);
392 assertEquals("a", pcds.getPassword());
393 pwd[0] = 'b';
394 assertEquals("a", pcds.getPassword());
395 }
396
397 @Test
398 public void testSetUserNull() throws Exception {
399 pcds.setUser("Alice");
400 assertEquals("Alice", pcds.getUser());
401 pcds.setUser(null);
402 assertNull(pcds.getUser());
403 }
404
405 @Test
406 public void testSetUserNullWithConnectionProperties() throws Exception {
407 pcds.setConnectionProperties(new Properties());
408 pcds.setUser("Alice");
409 assertEquals("Alice", pcds.getUser());
410 pcds.setUser(null);
411 assertNull(pcds.getUser());
412 }
413
414 @Test
415 public void testSimple() throws Exception {
416 try (final Connection conn = pcds.getPooledConnection().getConnection()) {
417 assertNotNull(conn);
418 try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
419 assertNotNull(stmt);
420 try (final ResultSet resultSet = stmt.executeQuery()) {
421 assertNotNull(resultSet);
422 assertTrue(resultSet.next());
423 }
424 }
425 }
426 }
427
428 @SuppressWarnings("resource")
429 @Test
430 public void testSimpleWithUsername() throws Exception {
431 final Connection connCheck;
432 PStmtKey pStmtKey;
433 try (final Connection conn = pcds.getPooledConnection("u1", "p1").getConnection()) {
434 assertNotNull(conn);
435 connCheck = conn;
436 try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
437 assertNotNull(stmt);
438 final DelegatingStatement delegatingStatement = (DelegatingStatement) stmt;
439 final Statement delegateStatement = delegatingStatement.getDelegate();
440 pStmtKey = TestUtils.getPStmtKey((PoolablePreparedStatement) delegateStatement);
441 assertNotNull(pStmtKey);
442 try (final ResultSet resultSet = stmt.executeQuery()) {
443 assertNotNull(resultSet);
444 assertTrue(resultSet.next());
445 }
446 }
447 }
448 checkAfterClose(connCheck, pStmtKey);
449 }
450
451 @Test
452 public void testToStringWithoutConnectionProperties() throws ClassNotFoundException {
453 final DriverAdapterCPDS cleanCpds = new DriverAdapterCPDS();
454 cleanCpds.setDriver("org.apache.commons.dbcp2.TesterDriver");
455 cleanCpds.setUrl("jdbc:apache:commons:testdriver");
456 cleanCpds.setUser("foo");
457 cleanCpds.setPassword("bar");
458 cleanCpds.toString();
459 }
460 }