1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2;
19
20 import static org.hamcrest.MatcherAssert.assertThat;
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.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertNull;
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 import static org.junit.jupiter.api.Assertions.fail;
29
30 import java.io.IOException;
31 import java.lang.management.ManagementFactory;
32 import java.lang.management.ThreadMXBean;
33 import java.sql.Connection;
34 import java.sql.SQLException;
35 import java.time.Duration;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collection;
39 import java.util.Properties;
40 import java.util.Set;
41 import java.util.concurrent.atomic.AtomicInteger;
42 import java.util.stream.Stream;
43
44 import javax.management.AttributeNotFoundException;
45 import javax.management.MBeanAttributeInfo;
46 import javax.management.MBeanServer;
47 import javax.management.ObjectName;
48 import javax.sql.DataSource;
49
50 import org.hamcrest.CoreMatchers;
51 import org.junit.jupiter.api.AfterEach;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Disabled;
55 import org.junit.jupiter.api.Test;
56
57
58
59
60 public class TestBasicDataSource extends TestConnectionPool {
61
62 private static final String CATALOG = "test catalog";
63
64 protected BasicDataSource ds;
65
66 protected BasicDataSource createDataSource() throws Exception {
67 return new BasicDataSource();
68 }
69
70 @Override
71 protected Connection getConnection() throws Exception {
72 return ds.getConnection();
73 }
74
75 @BeforeEach
76 public void setUp() throws Exception {
77 ds = createDataSource();
78 ds.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
79 ds.setUrl("jdbc:apache:commons:testdriver");
80 ds.setMaxTotal(getMaxTotal());
81 ds.setMaxWait(getMaxWaitDuration());
82 ds.setDefaultAutoCommit(Boolean.TRUE);
83 ds.setDefaultReadOnly(Boolean.FALSE);
84 ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
85 ds.setDefaultCatalog(CATALOG);
86 ds.setUsername("userName");
87 ds.setPassword("password");
88 ds.setValidationQuery("SELECT DUMMY FROM DUAL");
89 ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "SELECT 2"));
90 ds.setDriverClassLoader(new TesterClassLoader());
91 ds.setJmxName("org.apache.commons.dbcp2:name=test");
92 }
93
94 @Override
95 @AfterEach
96 public void tearDown() throws Exception {
97 super.tearDown();
98 ds.close();
99 ds = null;
100 }
101
102 @Test
103 public void testAccessToUnderlyingConnectionAllowed() throws Exception {
104 ds.setAccessToUnderlyingConnectionAllowed(true);
105 assertTrue(ds.isAccessToUnderlyingConnectionAllowed());
106
107 try (final Connection conn = getConnection()) {
108 Connection dconn = ((DelegatingConnection<?>) conn).getDelegate();
109 assertNotNull(dconn);
110
111 dconn = ((DelegatingConnection<?>) conn).getInnermostDelegate();
112 assertNotNull(dconn);
113
114 assertTrue(dconn instanceof TesterConnection);
115 }
116 }
117
118 @Test
119 public void testClose() throws Exception {
120 ds.setAccessToUnderlyingConnectionAllowed(true);
121
122
123 final Connection activeConnection = getConnection();
124 final Connection rawActiveConnection = ((DelegatingConnection<?>) activeConnection).getInnermostDelegate();
125 assertFalse(activeConnection.isClosed());
126 assertFalse(rawActiveConnection.isClosed());
127
128
129 final Connection idleConnection = getConnection();
130 final Connection rawIdleConnection = ((DelegatingConnection<?>) idleConnection).getInnermostDelegate();
131 assertFalse(idleConnection.isClosed());
132 assertFalse(rawIdleConnection.isClosed());
133
134
135 idleConnection.close();
136 assertTrue(idleConnection.isClosed());
137 assertFalse(rawIdleConnection.isClosed());
138
139 ds.close();
140
141
142 assertTrue(rawIdleConnection.isClosed());
143
144
145 assertFalse(activeConnection.isClosed());
146 assertFalse(rawActiveConnection.isClosed());
147
148
149 activeConnection.close();
150
151
152 assertTrue(activeConnection.isClosed());
153 assertTrue(rawActiveConnection.isClosed());
154
155
156 assertThrows(SQLException.class, this::getConnection);
157
158
159 ds.close();
160
161 }
162
163 @Test
164 public void testConcurrentInitBorrow() throws Exception {
165 ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnectionDelayDriver");
166 ds.setUrl("jdbc:apache:commons:testerConnectionDelayDriver:50");
167 ds.setInitialSize(8);
168
169
170 final TestThread testThread = new TestThread(1, 0);
171 final Thread t = new Thread(testThread);
172 t.start();
173
174
175 Thread.sleep(100);
176 try (Connection conn = ds.getConnection()) {
177
178
179
180 assertTrue(ds.getConnectionPool().getNumIdle() > 5);
181
182
183 t.join();
184 assertFalse(testThread.failed());
185 }
186 ds.close();
187 }
188
189
190
191
192
193 @Test
194 public void testConcurrentInvalidateBorrow() throws Exception {
195 ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnRequestCountDriver");
196 ds.setUrl("jdbc:apache:commons:testerConnRequestCountDriver");
197 ds.setTestOnBorrow(true);
198 ds.setValidationQuery("SELECT DUMMY FROM DUAL");
199 ds.setMaxTotal(8);
200 ds.setLifo(true);
201 ds.setMaxWait(Duration.ofMillis(-1));
202
203
204 final TestThread testThread1 = new TestThread(1000,0);
205 final Thread t1 = new Thread(testThread1);
206 t1.start();
207 final TestThread testThread2 = new TestThread(1000,0);
208 final Thread t2 = new Thread(testThread1);
209 t2.start();
210
211
212 for (int i = 0; i < 1000; i++) {
213 final Connection conn = ds.getConnection();
214 ds.invalidateConnection(conn);
215 }
216
217
218 t1.join();
219 t2.join();
220 assertFalse(testThread1.failed());
221 assertFalse(testThread2.failed());
222
223 ds.close();
224 }
225
226
227
228
229
230 @Test
231 public void testConnectionMBeansDisabled() throws Exception {
232 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
233
234 final ObjectName commons = new ObjectName("org.apache.commons.*:*");
235 final Set<ObjectName> results = mbs.queryNames(commons, null);
236 for (final ObjectName result : results) {
237 mbs.unregisterMBean(result);
238 }
239 ds.setRegisterConnectionMBean(false);
240 try (Connection conn = ds.getConnection()) {
241
242 final ObjectName connections = new ObjectName("org.apache.commons.*:connection=*,*");
243 assertEquals(0, mbs.queryNames(connections, null).size());
244 }
245 }
246
247
248
249
250
251 @Test
252 public void testCreateConnectionFactoryWithConnectionFactoryClassName() throws Exception {
253 Properties properties = new Properties();
254
255 properties = new Properties();
256 properties.put("initialSize", "1");
257 properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver");
258 properties.put("url", "jdbc:apache:commons:testdriver");
259 properties.put("username", "foo");
260 properties.put("password", "bar");
261 properties.put("connectionFactoryClassName", "org.apache.commons.dbcp2.TesterConnectionFactory");
262 try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) {
263 try (Connection conn = ds.getConnection()) {
264 assertNotNull(conn);
265 }
266 }
267 }
268
269
270
271
272
273 @Test
274 public void testCreateConnectionFactoryWithoutConnectionFactoryClassName() throws Exception {
275
276 final Properties properties = new Properties();
277 properties.put("initialSize", "1");
278 properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver");
279 properties.put("url", "jdbc:apache:commons:testdriver");
280 properties.put("username", "foo");
281 properties.put("password", "bar");
282 try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) {
283 try (Connection conn = ds.getConnection()) {
284 assertNotNull(conn);
285 }
286 }
287 }
288
289
290
291
292
293
294 @Test
295 public void testCreateDataSourceCleanupEvictor() throws Exception {
296 ds.close();
297 ds = null;
298 ds = createDataSource();
299 ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnRequestCountDriver");
300 ds.setUrl("jdbc:apache:commons:testerConnRequestCountDriver");
301 ds.setValidationQuery("SELECT DUMMY FROM DUAL");
302 ds.setUsername("userName");
303
304
305 ds.setPassword("wrong");
306
307 ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100));
308
309 ds.setMinIdle(2);
310
311
312 synchronized (TesterConnRequestCountDriver.class) {
313 TesterConnRequestCountDriver.initConnRequestCount();
314
315
316 for (int i = 0; i < 10; i++) {
317 try {
318 @SuppressWarnings("unused")
319 final DataSource ds2 = ds.createDataSource();
320 } catch (final SQLException e) {
321
322 }
323 }
324
325
326 Thread.sleep(1000);
327
328
329 assertEquals(10, TesterConnRequestCountDriver.getConnectionRequestCount());
330 }
331
332
333 assertNull(ds.getConnectionPool());
334 }
335
336
337
338
339
340 @Test
341 public void testCreateDataSourceCleanupThreads() throws Exception {
342 ds.close();
343 ds = null;
344 ds = createDataSource();
345 ds.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
346 ds.setUrl("jdbc:apache:commons:testdriver");
347 ds.setMaxTotal(getMaxTotal());
348 ds.setMaxWait(getMaxWaitDuration());
349 ds.setDefaultAutoCommit(Boolean.TRUE);
350 ds.setDefaultReadOnly(Boolean.FALSE);
351 ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
352 ds.setDefaultCatalog(CATALOG);
353 ds.setUsername("userName");
354
355 ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100));
356
357 ds.setPassword("wrong");
358 ds.setValidationQuery("SELECT DUMMY FROM DUAL");
359 final int threadCount = Thread.activeCount();
360 for (int i = 0; i < 10; i++) {
361 try (Connection c = ds.getConnection()){
362 } catch (final SQLException ex) {
363
364 }
365 }
366
367 assertTrue(Thread.activeCount() <= threadCount + 1);
368 }
369
370 @Test
371 public void testDefaultCatalog() throws Exception {
372 final Connection[] c = new Connection[getMaxTotal()];
373 for (int i = 0; i < c.length; i++) {
374 c[i] = getConnection();
375 assertNotNull(c[i]);
376 assertEquals(CATALOG, c[i].getCatalog());
377 }
378
379 for (final Connection element : c) {
380 element.setCatalog("error");
381 element.close();
382 }
383
384 for (int i = 0; i < c.length; i++) {
385 c[i] = getConnection();
386 assertNotNull(c[i]);
387 assertEquals(CATALOG, c[i].getCatalog());
388 }
389
390 for (final Connection element : c) {
391 element.close();
392 }
393 }
394
395 @Test
396 public void testDeprecatedAccessors() throws SQLException {
397 try (BasicDataSource bds = new BasicDataSource()) {
398 int i = 0;
399
400 i++;
401 bds.setDefaultQueryTimeout(i);
402 assertEquals(i, bds.getDefaultQueryTimeout());
403 assertEquals(Duration.ofSeconds(i), bds.getDefaultQueryTimeoutDuration());
404
405 i++;
406 bds.setMaxConnLifetimeMillis(i);
407 assertEquals(i, bds.getMaxConnLifetimeMillis());
408 assertEquals(Duration.ofMillis(i), bds.getMaxConnDuration());
409
410 i++;
411 bds.setMaxWaitMillis(i);
412 assertEquals(i, bds.getMaxWaitMillis());
413 assertEquals(Duration.ofMillis(i), bds.getMaxWaitDuration());
414
415 i++;
416 bds.setMinEvictableIdleTimeMillis(i);
417 assertEquals(i, bds.getMinEvictableIdleTimeMillis());
418 assertEquals(Duration.ofMillis(i), bds.getMinEvictableIdleDuration());
419
420 i++;
421 bds.setRemoveAbandonedTimeout(i);
422 assertEquals(i, bds.getRemoveAbandonedTimeout());
423 assertEquals(Duration.ofSeconds(i), bds.getRemoveAbandonedTimeoutDuration());
424
425 i++;
426 bds.setSoftMinEvictableIdleTimeMillis(i);
427 assertEquals(i, bds.getSoftMinEvictableIdleTimeMillis());
428 assertEquals(Duration.ofMillis(i), bds.getSoftMinEvictableIdleDuration());
429
430 i++;
431 bds.setTimeBetweenEvictionRunsMillis(i);
432 assertEquals(i, bds.getTimeBetweenEvictionRunsMillis());
433 assertEquals(Duration.ofMillis(i), bds.getDurationBetweenEvictionRuns());
434
435 i++;
436 bds.setValidationQueryTimeout(1);
437 assertEquals(1, bds.getValidationQueryTimeout());
438 assertEquals(Duration.ofSeconds(1), bds.getValidationQueryTimeoutDuration());
439 }
440 }
441
442
443
444
445
446
447 @Test
448 public void testDisconnectSqlCodes() throws Exception {
449 final ArrayList<String> disconnectionSqlCodes = new ArrayList<>();
450 disconnectionSqlCodes.add("XXX");
451 ds.setDisconnectionSqlCodes(disconnectionSqlCodes);
452 ds.setFastFailValidation(true);
453 try (Connection conn = ds.getConnection()) {
454
455 final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory();
456 assertTrue(pcf.isFastFailValidation());
457 assertTrue(pcf.getDisconnectionSqlCodes().contains("XXX"));
458 assertEquals(1, pcf.getDisconnectionSqlCodes().size());
459 }
460 }
461
462
463
464
465
466 @Test
467 public void testDriverClassLoader() throws Exception {
468 try (Connection conn = getConnection()) {
469 final ClassLoader cl = ds.getDriverClassLoader();
470 assertNotNull(cl);
471 assertTrue(cl instanceof TesterClassLoader);
472 assertTrue(((TesterClassLoader) cl).didLoad(ds.getDriverClassName()));
473 }
474 }
475
476 @Test
477 public void testEmptyInitConnectionSql() throws Exception {
478
479 ds.setConnectionInitSqls(Arrays.asList("", " "));
480 assertNotNull(ds.getConnectionInitSqls());
481 assertEquals(0, ds.getConnectionInitSqls().size());
482
483 ds.setConnectionInitSqls(null);
484 assertNotNull(ds.getConnectionInitSqls());
485 assertEquals(0, ds.getConnectionInitSqls().size());
486
487 ds.setConnectionInitSqls((Collection<String>) Arrays.asList("", " "));
488 assertNotNull(ds.getConnectionInitSqls());
489 assertEquals(0, ds.getConnectionInitSqls().size());
490 }
491
492 @Test
493 public void testEmptyValidationQuery() throws Exception {
494 assertNotNull(ds.getValidationQuery());
495
496 ds.setValidationQuery("");
497 assertNull(ds.getValidationQuery());
498
499 ds.setValidationQuery(" ");
500 assertNull(ds.getValidationQuery());
501 }
502
503 @Test
504 @Disabled
505 public void testEvict() throws Exception {
506 final long delay = 1000;
507
508 ds.setInitialSize(10);
509 ds.setMaxIdle(10);
510 ds.setMaxTotal(10);
511 ds.setMinIdle(5);
512 ds.setNumTestsPerEvictionRun(3);
513 ds.setMinEvictableIdle(Duration.ofMillis(100));
514 ds.setDurationBetweenEvictionRuns(Duration.ofMillis(delay));
515 ds.setPoolPreparedStatements(true);
516
517 try (Connection conn = ds.getConnection()) {
518
519 }
520
521 final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
522 while (Stream.of(threadBean.getThreadInfo(threadBean.getAllThreadIds())).anyMatch(t -> t.getThreadName().equals("commons-pool-evictor-thread"))) {
523 if (ds.getNumIdle() <= ds.getMinIdle()) {
524 break;
525 }
526 Thread.sleep(delay);
527 }
528 if (ds.getNumIdle() > ds.getMinIdle()) {
529 fail("EvictionTimer thread was destroyed with numIdle=" + ds.getNumIdle() + "(expected: less or equal than " + ds.getMinIdle() + ")");
530 }
531 }
532
533 @Test
534 public void testInitialSize() throws Exception {
535 ds.setMaxTotal(20);
536 ds.setMaxIdle(20);
537 ds.setInitialSize(10);
538
539 try (Connection conn = getConnection()) {
540 assertNotNull(conn);
541 }
542
543 assertEquals(0, ds.getNumActive());
544 assertEquals(10, ds.getNumIdle());
545 }
546
547
548
549
550
551 @Test
552 public void testInstanceNotFoundExceptionLogSuppressed() throws Exception {
553 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
554 try (Connection c = ds.getConnection()) {
555
556 }
557 final ObjectName objectName = new ObjectName(ds.getJmxName());
558 if (mbs.isRegistered(objectName)) {
559 mbs.unregisterMBean(objectName);
560 }
561 StackMessageLog.clear();
562 ds.close();
563 assertThat(StackMessageLog.popMessage(),
564 CoreMatchers.not(CoreMatchers.containsString("InstanceNotFoundException")));
565 assertNull(ds.getRegisteredJmxName());
566 }
567
568 @Test
569 public void testInvalidateConnection() throws Exception {
570 ds.setMaxTotal(2);
571 try (final Connection conn1 = ds.getConnection()) {
572 try (final Connection conn2 = ds.getConnection()) {
573 ds.invalidateConnection(conn1);
574 assertTrue(conn1.isClosed());
575 assertEquals(1, ds.getNumActive());
576 assertEquals(0, ds.getNumIdle());
577 try (final Connection conn3 = ds.getConnection()) {
578 conn2.close();
579 }
580 }
581 }
582 }
583
584 @Test
585 public void testInvalidConnectionInitSqlList() {
586 ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid"));
587 final SQLException e = assertThrows(SQLException.class, ds::getConnection);
588 assertTrue(e.toString().contains("invalid"));
589 }
590
591 @Test
592 public void testInvalidConnectionInitSqlCollection() {
593 ds.setConnectionInitSqls((Collection<String>) Arrays.asList("SELECT 1", "invalid"));
594 final SQLException e = assertThrows(SQLException.class, ds::getConnection);
595 assertTrue(e.toString().contains("invalid"));
596 }
597
598 @Test
599 public void testInvalidValidationQuery() {
600 ds.setValidationQuery("invalid");
601 final SQLException e = assertThrows(SQLException.class, ds::getConnection);
602 assertTrue(e.toString().contains("invalid"));
603 }
604
605
606
607 @Test
608 public void testIsClosedFailure() throws SQLException {
609 ds.setAccessToUnderlyingConnectionAllowed(true);
610 final Connection conn = ds.getConnection();
611 assertNotNull(conn);
612 assertEquals(1, ds.getNumActive());
613
614
615 final TesterConnection tconn = (TesterConnection) ((DelegatingConnection<?>) conn).getInnermostDelegate();
616 tconn.setFailure(new IOException("network error"));
617
618 assertThrows(SQLException.class, () -> conn.close());
619
620 assertEquals(0, ds.getNumActive());
621 }
622
623 @Test
624 public void testIsWrapperFor() throws Exception {
625 assertTrue(ds.isWrapperFor(BasicDataSource.class));
626 assertTrue(ds.isWrapperFor(AutoCloseable.class));
627 assertFalse(ds.isWrapperFor(String.class));
628 assertFalse(ds.isWrapperFor(null));
629 }
630
631
632
633
634
635 @Test
636 public void testJmxDisabled() throws Exception {
637 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
638
639 final ObjectName commons = new ObjectName("org.apache.commons.*:*");
640 final Set<ObjectName> results = mbs.queryNames(commons, null);
641 for (final ObjectName result : results) {
642 mbs.unregisterMBean(result);
643 }
644 ds.setJmxName(null);
645 ds.setPoolPreparedStatements(true);
646 try (Connection conn = ds.getConnection()) {
647
648 assertEquals(0, mbs.queryNames(commons, null).size());
649 }
650 }
651
652
653
654
655
656
657
658 @Test
659 public void testJmxDoesNotExposePassword() throws Exception {
660 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
661
662 try (Connection c = ds.getConnection()) {
663
664 }
665 final ObjectName objectName = new ObjectName(ds.getJmxName());
666
667 final MBeanAttributeInfo[] attributes = mbs.getMBeanInfo(objectName).getAttributes();
668
669 assertTrue(attributes != null && attributes.length > 0);
670
671 Arrays.asList(attributes).forEach(attrInfo -> {
672 assertFalse("password".equalsIgnoreCase(attrInfo.getName()));
673 });
674
675 assertThrows(AttributeNotFoundException.class, () -> {
676 mbs.getAttribute(objectName, "Password");
677 });
678 }
679
680 @Test
681 public void testManualConnectionEvict() throws Exception {
682 ds.setMinIdle(0);
683 ds.setMaxIdle(4);
684 ds.setMinEvictableIdle(Duration.ofMillis(10));
685 ds.setNumTestsPerEvictionRun(2);
686
687 try (Connection ds2 = ds.createDataSource().getConnection(); Connection ds3 = ds.createDataSource().getConnection()) {
688 assertEquals(0, ds.getNumIdle());
689 }
690
691
692 Thread.sleep(100);
693
694
695 assertEquals(2, ds.getNumIdle());
696
697
698 ds.evict();
699
700
701 assertEquals(0, ds.getNumIdle());
702 }
703
704 @Test
705 public void testMaxConnLifetimeExceeded() throws Exception {
706 try {
707 StackMessageLog.lock();
708 ds.setMaxConn(Duration.ofMillis(100));
709 try (Connection conn = ds.getConnection()) {
710 assertEquals(1, ds.getNumActive());
711 Thread.sleep(500);
712 }
713 assertEquals(0, ds.getNumIdle());
714 final String message = StackMessageLog.popMessage();
715 Assertions.assertNotNull(message);
716 assertTrue(message.indexOf("exceeds the maximum permitted value") > 0);
717 } finally {
718 StackMessageLog.clear();
719 StackMessageLog.unLock();
720 }
721 }
722
723 @Test
724 public void testMaxConnLifetimeExceededMutedLog() throws Exception {
725 try {
726 StackMessageLog.lock();
727 StackMessageLog.clear();
728 ds.setMaxConn(Duration.ofMillis(100));
729 ds.setLogExpiredConnections(false);
730 try (final Connection conn = ds.getConnection()) {
731 assertEquals(1, ds.getNumActive());
732 Thread.sleep(500);
733 }
734 assertEquals(0, ds.getNumIdle());
735 assertTrue(StackMessageLog.isEmpty(), StackMessageLog.getAll().toString());
736 } finally {
737 StackMessageLog.clear();
738 StackMessageLog.unLock();
739 }
740 }
741
742
743
744
745
746
747 @Test
748 public void testMaxTotalZero() throws Exception {
749 ds.setMaxTotal(0);
750 assertThrows(SQLException.class, ds::getConnection);
751 }
752
753
754
755
756
757
758 @Test
759 public void testMutateAbandonedConfig() throws Exception {
760 final Properties properties = new Properties();
761 properties.put("initialSize", "1");
762 properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver");
763 properties.put("url", "jdbc:apache:commons:testdriver");
764 properties.put("username", "foo");
765 properties.put("password", "bar");
766 try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) {
767 final boolean original = ds.getConnectionPool().getLogAbandoned();
768 ds.setLogAbandoned(!original);
769 Assertions.assertNotEquals(original, ds.getConnectionPool().getLogAbandoned());
770 }
771 }
772
773 @Test
774 public void testNoAccessToUnderlyingConnectionAllowed() throws Exception {
775
776 assertFalse(ds.isAccessToUnderlyingConnectionAllowed());
777
778 try (Connection conn = getConnection()) {
779 Connection dconn = ((DelegatingConnection<?>) conn).getDelegate();
780 assertNull(dconn);
781
782 dconn = ((DelegatingConnection<?>) conn).getInnermostDelegate();
783 assertNull(dconn);
784 }
785 }
786
787
788
789
790
791
792 @Test
793 public void testPoolCloseCheckedException() throws Exception {
794 ds.setAccessToUnderlyingConnectionAllowed(true);
795
796 final TesterConnection tc;
797
798 try (Connection conn = ds.getConnection()) {
799 tc = (TesterConnection) ((DelegatingConnection<?>) conn).getInnermostDelegate();
800 }
801
802
803
804 tc.setFailure(new SQLException("bang"));
805
806
807
808
809 try {
810 StackMessageLog.lock();
811 StackMessageLog.clear();
812 ds.close();
813
814 final String message = StackMessageLog.popMessage();
815 Assertions.assertNotNull(message);
816 assertTrue(message.indexOf("bang") > 0);
817 } catch (final SQLException ex) {
818 assertTrue(ex.getMessage().indexOf("Cannot close") > 0);
819 assertTrue(ex.getCause().getMessage().indexOf("bang") > 0);
820 } finally {
821 StackMessageLog.unLock();
822 }
823 }
824
825 @Test
826 public void testPoolCloseRTE() throws Exception {
827
828 ds.setAccessToUnderlyingConnectionAllowed(true);
829 final TesterConnection tc;
830 try (Connection conn = ds.getConnection()) {
831 tc = (TesterConnection) ((DelegatingConnection<?>) conn).getInnermostDelegate();
832 }
833 tc.setFailure(new IllegalStateException("boom"));
834 try {
835 StackMessageLog.lock();
836 StackMessageLog.clear();
837 ds.close();
838 final String message = StackMessageLog.popMessage();
839 Assertions.assertNotNull(message);
840 assertTrue(message.indexOf("boom") > 0);
841 } catch (final IllegalStateException ex) {
842 assertTrue(ex.getMessage().indexOf("boom") > 0);
843 } finally {
844 StackMessageLog.unLock();
845 }
846 }
847
848 @Override
849 @Test
850 public void testPooling() throws Exception {
851
852 ds.setAccessToUnderlyingConnectionAllowed(true);
853 super.testPooling();
854 }
855
856
857
858
859
860
861 @Test
862 public void testPropertyTestOnReturn() throws Exception {
863 ds.setValidationQuery("select 1 from dual");
864 ds.setTestOnBorrow(false);
865 ds.setTestWhileIdle(false);
866 ds.setTestOnReturn(true);
867
868 try (Connection conn = ds.getConnection()) {
869 assertNotNull(conn);
870
871 assertFalse(ds.getConnectionPool().getTestOnBorrow());
872 assertFalse(ds.getConnectionPool().getTestWhileIdle());
873 assertTrue(ds.getConnectionPool().getTestOnReturn());
874 }
875 }
876
877 @Test
878 public void testRestart() throws Exception {
879 ds.setMaxTotal(2);
880 ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100));
881 ds.setNumTestsPerEvictionRun(2);
882 ds.setMinEvictableIdle(Duration.ofMinutes(1));
883 ds.setInitialSize(2);
884 ds.setDefaultCatalog("foo");
885 try (Connection conn1 = ds.getConnection()) {
886 Thread.sleep(200);
887
888 ds.setDefaultCatalog("bar");
889 ds.setInitialSize(1);
890
891 ds.restart();
892 assertEquals("bar", ds.getDefaultCatalog());
893 assertEquals(1, ds.getInitialSize());
894 ds.getLogWriter();
895 assertEquals(0, ds.getNumActive());
896 assertEquals(1, ds.getNumIdle());
897 }
898
899 assertEquals(1, ds.getNumIdle());
900 ds.close();
901 }
902
903
904
905
906
907
908 @Test
909 public void testRollbackReadOnly() throws Exception {
910 ds.setDefaultReadOnly(Boolean.TRUE);
911 ds.setDefaultAutoCommit(Boolean.FALSE);
912
913 try (Connection conn = ds.getConnection()) {
914 assertNotNull(conn);
915 }
916 }
917
918 @Test
919 public void testSetAutoCommitTrueOnClose() throws Exception {
920 ds.setAccessToUnderlyingConnectionAllowed(true);
921 ds.setDefaultAutoCommit(Boolean.FALSE);
922 final Connection dconn;
923 try (Connection conn = getConnection()) {
924 assertNotNull(conn);
925 assertFalse(conn.getAutoCommit());
926
927 dconn = ((DelegatingConnection<?>) conn).getInnermostDelegate();
928 assertNotNull(dconn);
929 assertFalse(dconn.getAutoCommit());
930
931 }
932
933 assertTrue(dconn.getAutoCommit());
934 }
935
936 @Test
937 public void testSetProperties() throws Exception {
938
939 ds.setConnectionProperties("name1=value1;name2=value2;name3=value3");
940 assertEquals(3, ds.getConnectionProperties().size());
941 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
942 assertEquals("value2", ds.getConnectionProperties().getProperty("name2"));
943 assertEquals("value3", ds.getConnectionProperties().getProperty("name3"));
944
945
946 ds.setConnectionProperties("name1=value1;name2=value2");
947 assertEquals(2, ds.getConnectionProperties().size());
948 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
949 assertEquals("value2", ds.getConnectionProperties().getProperty("name2"));
950 assertFalse(ds.getConnectionProperties().containsKey("name3"));
951
952
953 ds.setConnectionProperties("name1=value1;name2");
954 assertEquals(2, ds.getConnectionProperties().size());
955 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
956 assertEquals("", ds.getConnectionProperties().getProperty("name2"));
957
958
959 ds.setConnectionProperties("name1=value1;name2=");
960 assertEquals(2, ds.getConnectionProperties().size());
961 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
962 assertEquals("", ds.getConnectionProperties().getProperty("name2"));
963
964
965 ds.setConnectionProperties("name1=value1");
966 assertEquals(1, ds.getConnectionProperties().size());
967 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
968
969
970 ds.setConnectionProperties("name1=value1;");
971 assertEquals(1, ds.getConnectionProperties().size());
972 assertEquals("value1", ds.getConnectionProperties().getProperty("name1"));
973
974
975 ds.setConnectionProperties("name1");
976 assertEquals(1, ds.getConnectionProperties().size());
977 assertEquals("", ds.getConnectionProperties().getProperty("name1"));
978
979
980 assertThrows(NullPointerException.class, () -> ds.setConnectionProperties(null));
981 }
982
983 @Test
984 public void testSetValidationTestProperties() {
985
986 assertTrue(ds.getTestOnBorrow());
987 assertFalse(ds.getTestOnReturn());
988 assertFalse(ds.getTestWhileIdle());
989
990 ds.setTestOnBorrow(true);
991 ds.setTestOnReturn(true);
992 ds.setTestWhileIdle(true);
993 assertTrue(ds.getTestOnBorrow());
994 assertTrue(ds.getTestOnReturn());
995 assertTrue(ds.getTestWhileIdle());
996
997 ds.setTestOnBorrow(false);
998 ds.setTestOnReturn(false);
999 ds.setTestWhileIdle(false);
1000 assertFalse(ds.getTestOnBorrow());
1001 assertFalse(ds.getTestOnReturn());
1002 assertFalse(ds.getTestWhileIdle());
1003 }
1004
1005 @Test
1006 public void testStart() throws Exception {
1007 ds.setAccessToUnderlyingConnectionAllowed(true);
1008 ds.setMaxTotal(2);
1009 final DelegatingConnection<?> conn1 = (DelegatingConnection<?>) ds.getConnection();
1010 final DelegatingConnection<?> conn2 = (DelegatingConnection<?>) ds.getConnection();
1011 final Connection inner1 = conn1.getInnermostDelegate();
1012 final Connection inner2 = conn2.getInnermostDelegate();
1013 assertFalse(inner2.isClosed());
1014 conn2.close();
1015 assertFalse(inner2.isClosed());
1016
1017 ds.close();
1018
1019 assertFalse(conn1.isClosed());
1020 assertTrue(inner2.isClosed());
1021 assertEquals(0, ds.getNumIdle());
1022
1023
1024 ds.start();
1025 final Connection conn3 = ds.getConnection();
1026 final Connection conn4 = ds.getConnection();
1027 conn3.close();
1028 conn4.close();
1029
1030
1031 conn1.close();
1032 assertTrue(inner1.isClosed());
1033 }
1034
1035 @Test
1036 public void testStartInitializes() throws Exception {
1037 ds.setInitialSize(2);
1038
1039 assertEquals(0, ds.getNumIdle());
1040 assertNull(ds.getRegisteredJmxName());
1041
1042
1043 ds.start();
1044 assertEquals(2, ds.getNumIdle());
1045 assertNotNull(ds.getRegisteredJmxName());
1046 }
1047
1048 @Test
1049 public void testTransactionIsolationBehavior() throws Exception {
1050 try (final Connection conn = getConnection()) {
1051 assertNotNull(conn);
1052 assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation());
1053 conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
1054 }
1055
1056 final Connection conn2 = getConnection();
1057 assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2.getTransactionIsolation());
1058
1059 final Connection conn3 = getConnection();
1060 assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3.getTransactionIsolation());
1061
1062 conn2.close();
1063
1064 conn3.close();
1065 }
1066
1067 @Test
1068 public void testUnwrap() throws Exception {
1069 assertSame(ds.unwrap(BasicDataSource.class), ds);
1070 assertSame(ds.unwrap(AutoCloseable.class), ds);
1071 assertThrows(SQLException.class, () -> ds.unwrap(String.class));
1072 assertThrows(SQLException.class, () -> ds.unwrap(null));
1073 }
1074
1075 @Test
1076 public void testValidationQueryTimeoutNegative() throws Exception {
1077 ds.setTestOnBorrow(true);
1078 ds.setTestOnReturn(true);
1079 ds.setValidationQueryTimeout(Duration.ofSeconds(-1));
1080 try (final Connection con = ds.getConnection()) {
1081
1082 }
1083 }
1084
1085 @Test
1086 public void testValidationQueryTimeoutSucceed() throws Exception {
1087 ds.setTestOnBorrow(true);
1088 ds.setTestOnReturn(true);
1089 ds.setValidationQueryTimeout(Duration.ofMillis(100));
1090 try (final Connection con = ds.getConnection()) {
1091
1092 }
1093 }
1094
1095 @Test
1096 public void testValidationQueryTimeoutZero() throws Exception {
1097 ds.setTestOnBorrow(true);
1098 ds.setTestOnReturn(true);
1099 ds.setValidationQueryTimeout(Duration.ZERO);
1100 try (final Connection con = ds.getConnection()) {
1101
1102 }
1103 }
1104
1105 @Test
1106 public void testValidationQueryTimoutFail() {
1107 ds.setTestOnBorrow(true);
1108 ds.setValidationQueryTimeout(Duration.ofSeconds(3));
1109 final SQLException e = assertThrows(SQLException.class, ds::getConnection);
1110 assertTrue(e.toString().contains("timeout"));
1111 }
1112 }
1113
1114
1115
1116
1117
1118 final class TesterConnectionDelayDriver extends TesterDriver {
1119 private static final String CONNECT_STRING = "jdbc:apache:commons:testerConnectionDelayDriver";
1120
1121 public TesterConnectionDelayDriver() {
1122
1123 }
1124
1125 @Override
1126 public boolean acceptsURL(final String url) throws SQLException {
1127 return url.startsWith(CONNECT_STRING);
1128 }
1129
1130 @Override
1131 public Connection connect(final String url, final Properties info) throws SQLException {
1132 final String[] parsedUrl = url.split(":");
1133 final int delay = Integer.parseInt(parsedUrl[parsedUrl.length - 1]);
1134 try {
1135 Thread.sleep(delay);
1136 } catch (final InterruptedException ex) {
1137 Thread.currentThread().interrupt();
1138 }
1139 return super.connect(url, info);
1140 }
1141
1142 }
1143
1144
1145
1146
1147 final class TesterConnRequestCountDriver extends TesterDriver {
1148 private static final String CONNECT_STRING = "jdbc:apache:commons:testerConnRequestCountDriver";
1149 private static final AtomicInteger connectionRequestCount = new AtomicInteger();
1150
1151 public static int getConnectionRequestCount() {
1152 return connectionRequestCount.get();
1153 }
1154
1155 public static void initConnRequestCount() {
1156 connectionRequestCount.set(0);
1157 }
1158
1159 public TesterConnRequestCountDriver() {
1160
1161 }
1162
1163 @Override
1164 public boolean acceptsURL(final String url) throws SQLException {
1165 return CONNECT_STRING.startsWith(url);
1166 }
1167
1168 @Override
1169 public Connection connect(final String url, final Properties info) throws SQLException {
1170 connectionRequestCount.incrementAndGet();
1171 return super.connect(url, info);
1172 }
1173 }