View Javadoc
1   /*
2    *    Copyright 2009-2023 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.datasource.pooled;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.assertFalse;
20  import static org.junit.jupiter.api.Assertions.assertNotEquals;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.sql.Connection;
24  import java.sql.SQLException;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.concurrent.CountDownLatch;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.junit.jupiter.api.BeforeEach;
31  import org.junit.jupiter.api.Test;
32  
33  class PooledDataSourceTest {
34  
35    PooledDataSource dataSource;
36  
37    @BeforeEach
38    void beforeEach() {
39      dataSource = new PooledDataSource("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:multipledrivers", "sa", "");
40    }
41  
42    @Test
43    void shouldBlockUntilConnectionIsAvailableInPooledDataSource() throws Exception {
44      dataSource.setPoolMaximumCheckoutTime(20000);
45  
46      List<Connection> connections = new ArrayList<>();
47      CountDownLatch latch = new CountDownLatch(1);
48  
49      for (int i = 0; i < dataSource.getPoolMaximumActiveConnections(); i++) {
50        connections.add(dataSource.getConnection());
51      }
52  
53      new Thread(() -> {
54        try {
55          dataSource.getConnection();
56          latch.countDown();
57        } catch (Exception e) {
58          throw new RuntimeException(e);
59        }
60      }).start();
61  
62      assertFalse(latch.await(1000, TimeUnit.MILLISECONDS));
63      connections.get(0).close();
64      assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
65    }
66  
67    @Test
68    void PoppedConnectionShouldBeNotEqualToClosedConnection() throws Exception {
69      Connection connectionToClose = dataSource.getConnection();
70      CountDownLatch latch = new CountDownLatch(1);
71  
72      new Thread(() -> {
73        try {
74          latch.await();
75          assertNotEquals(connectionToClose, dataSource.getConnection());
76        } catch (Exception e) {
77          throw new RuntimeException(e);
78        }
79      }).start();
80  
81      connectionToClose.close();
82      latch.countDown();
83    }
84  
85    @Test
86    void shouldEnsureCorrectIdleConnectionCount() throws Exception {
87      dataSource.setPoolMaximumActiveConnections(10);
88      dataSource.setPoolMaximumIdleConnections(5);
89  
90      PoolState poolState = dataSource.getPoolState();
91      List<Connection> connections = new ArrayList<>();
92  
93      for (int i = 0; i < dataSource.getPoolMaximumActiveConnections(); i++) {
94        connections.add(dataSource.getConnection());
95      }
96  
97      assertEquals(0, poolState.getIdleConnectionCount());
98  
99      for (int i = 0; i < dataSource.getPoolMaximumActiveConnections(); i++) {
100       connections.get(i).close();
101     }
102 
103     assertEquals(dataSource.getPoolMaximumIdleConnections(), poolState.getIdleConnectionCount());
104 
105     for (int i = 0; i < dataSource.getPoolMaximumIdleConnections(); i++) {
106       dataSource.getConnection();
107     }
108 
109     assertEquals(0, poolState.getIdleConnectionCount());
110   }
111 
112   @Test
113   void connectionShouldBeAvailableAfterMaximumCheckoutTime() throws Exception {
114     dataSource.setPoolMaximumCheckoutTime(1000);
115     dataSource.setPoolTimeToWait(500);
116 
117     int poolMaximumActiveConnections = dataSource.getPoolMaximumActiveConnections();
118     CountDownLatch latch = new CountDownLatch(1);
119 
120     for (int i = 0; i < poolMaximumActiveConnections; i++) {
121       dataSource.getConnection();
122     }
123 
124     new Thread(() -> {
125       try {
126         dataSource.getConnection();
127         latch.countDown();
128       } catch (Exception e) {
129         throw new RuntimeException(e);
130       }
131     }).start();
132 
133     assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
134   }
135 
136   @Test
137   void forceCloseAllShouldRemoveAllActiveAndIdleConnection() throws SQLException {
138     dataSource.setPoolMaximumActiveConnections(10);
139     dataSource.setPoolMaximumIdleConnections(5);
140 
141     PoolState poolState = dataSource.getPoolState();
142     List<Connection> connections = new ArrayList<>();
143 
144     for (int i = 0; i < dataSource.getPoolMaximumActiveConnections(); i++) {
145       connections.add(dataSource.getConnection());
146     }
147 
148     for (int i = 0; i < dataSource.getPoolMaximumIdleConnections(); i++) {
149       connections.get(i).close();
150     }
151 
152     assertEquals(dataSource.getPoolMaximumActiveConnections() - poolState.getIdleConnectionCount(),
153         poolState.getActiveConnectionCount());
154     assertEquals(dataSource.getPoolMaximumIdleConnections(), poolState.getIdleConnectionCount());
155 
156     dataSource.forceCloseAll();
157 
158     assertEquals(0, poolState.getActiveConnectionCount());
159     assertEquals(0, poolState.getIdleConnectionCount());
160   }
161 }