View Javadoc
1   /*
2    *    Copyright 2009-2022 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.mybatis.guice.datasource.hikaricp;
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.assertNull;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  import static org.mockito.Mockito.mock;
23  
24  import com.codahale.metrics.MetricRegistry;
25  import com.codahale.metrics.health.HealthCheckRegistry;
26  import com.google.inject.AbstractModule;
27  import com.google.inject.Guice;
28  import com.google.inject.Injector;
29  import com.google.inject.name.Names;
30  import com.zaxxer.hikari.HikariDataSource;
31  import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
32  import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory;
33  
34  import java.sql.SQLException;
35  import java.util.Properties;
36  import java.util.concurrent.ScheduledExecutorService;
37  import java.util.concurrent.ThreadFactory;
38  
39  import org.junit.jupiter.api.Test;
40  import org.junit.jupiter.api.extension.ExtendWith;
41  import org.mockito.junit.jupiter.MockitoExtension;
42  
43  @ExtendWith(MockitoExtension.class)
44  class HikariCPProviderTest {
45  
46    @Test
47    void get() throws SQLException {
48  
49      // JDBC connection
50      // ============================================================================================================
51      final String url = "jdbc:h2:mem:testdb";
52      final String username = "test_user";
53      final String password = "test_password";
54  
55      final int loginTimeout = 1; // Seconds
56  
57      // Hikari CP configuration
58      // ============================================================================================================
59      final boolean allowPoolSuspension = true;
60      final boolean autoCommit = true;
61  
62      final String catalog = "custom";
63      final String connectionInitSql = "CREATE SCHEMA IF NOT EXISTS TEST; SET SCHEMA TEST;";
64      final String connectionTestQuery = "Commit;";
65      final long connectionTimeoutMs = 1000L;
66  
67      final String driverClassName = "org.h2.Driver";
68  
69      final Properties healthCheckProperties = new Properties();
70      healthCheckProperties.put("boom", "goes the dynamite");
71      final HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
72  
73      final long idleTimeoutMs = 42L;
74      final long initializationFailTimeout = 2L;
75      final boolean isolateInternalQueries = true;
76  
77      final long leakDetectionThresholdMs = 2000L; // 2000ms
78  
79      final long maxLifetimeMs = 30000L;
80      final long maxPoolSize = 10L;
81  
82      final MetricRegistry metricRegistry = new MetricRegistry();
83      final MetricsTrackerFactory metricsTrackerFactory = new CodahaleMetricsTrackerFactory(metricRegistry);
84  
85      final long minimumIdle = 10L;
86  
87      final String poolName = "MyBatis Pool";
88  
89      final boolean readOnly = false;
90  
91      final String schema = "PUBLIC";
92  
93      final long validationTimeoutMs = 250; // Min is 250ms
94  
95      Injector injector = Guice.createInjector(new AbstractModule() {
96        @Override
97        protected void configure() {
98  
99          // JDBC connection
100         // ============================================================================================================
101         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
102         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
103         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
104         bindConstant().annotatedWith(Names.named("JDBC.loginTimeout")).to(loginTimeout);
105 
106         // Hikari CP configuration
107         // ============================================================================================================
108 
109         bindConstant().annotatedWith(Names.named("hikaricp.allowPoolSuspension")).to(allowPoolSuspension);
110         bindConstant().annotatedWith(Names.named("hikaricp.autoCommit")).to(autoCommit);
111 
112         bindConstant().annotatedWith(Names.named("hikaricp.catalog")).to(catalog);
113         bindConstant().annotatedWith(Names.named("hikaricp.connectionInitSql")).to(connectionInitSql);
114         bindConstant().annotatedWith(Names.named("hikaricp.connectionTestQuery")).to(connectionTestQuery);
115         bindConstant().annotatedWith(Names.named("hikaricp.connectionTimeoutMs")).to(connectionTimeoutMs);
116 
117         bindConstant().annotatedWith(Names.named("hikaricp.driverClassName")).to(driverClassName);
118 
119         bind(Properties.class).annotatedWith(Names.named("hikaricp.healthCheckProperties"))
120             .toInstance(healthCheckProperties);
121         bind(Object.class).annotatedWith(Names.named("hikaricp.healthCheckRegistry")).toInstance(healthCheckRegistry);
122 
123         bindConstant().annotatedWith(Names.named("hikaricp.idleTimeoutMs")).to(idleTimeoutMs);
124         bindConstant().annotatedWith(Names.named("hikaricp.initializationFailTimeout")).to(initializationFailTimeout);
125         bindConstant().annotatedWith(Names.named("hikaricp.isolateInternalQueries")).to(isolateInternalQueries);
126 
127         bindConstant().annotatedWith(Names.named("hikaricp.leakDetectionThresholdMs")).to(leakDetectionThresholdMs);
128 
129         bindConstant().annotatedWith(Names.named("hikaricp.maxLifetimeMs")).to(maxLifetimeMs);
130         bindConstant().annotatedWith(Names.named("hikaricp.maxPoolSize")).to(maxPoolSize);
131 
132         bind(MetricsTrackerFactory.class).annotatedWith(Names.named("hikaricp.metricsTrackerFactory"))
133             .toInstance(metricsTrackerFactory);
134 
135         bindConstant().annotatedWith(Names.named("hikaricp.minimumIdle")).to(minimumIdle);
136         bindConstant().annotatedWith(Names.named("hikaricp.poolName")).to(poolName);
137         bindConstant().annotatedWith(Names.named("hikaricp.readOnly")).to(readOnly);
138 
139         bindConstant().annotatedWith(Names.named("hikaricp.schema")).to(schema);
140 
141         bindConstant().annotatedWith(Names.named("hikaricp.validationTimeoutMs")).to(validationTimeoutMs);
142       }
143     });
144 
145     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
146     HikariDataSource dataSource = (HikariDataSource) provider.get();
147 
148     // JDBC connection
149     // ============================================================================================================
150     assertEquals(url, dataSource.getJdbcUrl());
151     assertEquals(username, dataSource.getUsername());
152     assertEquals(password, dataSource.getPassword());
153     assertEquals(1, dataSource.getLoginTimeout());
154 
155     // Hikari CP configuration
156     // ============================================================================================================
157     assertEquals(allowPoolSuspension, dataSource.isAllowPoolSuspension());
158     assertEquals(autoCommit, dataSource.isAutoCommit());
159 
160     assertEquals(catalog, dataSource.getCatalog());
161     assertEquals(connectionInitSql, dataSource.getConnectionInitSql());
162     assertEquals(connectionTestQuery, dataSource.getConnectionTestQuery());
163     assertEquals(connectionTimeoutMs, dataSource.getConnectionTimeout());
164 
165     assertEquals(driverClassName, dataSource.getDriverClassName());
166 
167     assertEquals(healthCheckProperties, dataSource.getHealthCheckProperties());
168     assertEquals(healthCheckRegistry, dataSource.getHealthCheckRegistry());
169 
170     assertEquals(idleTimeoutMs, dataSource.getIdleTimeout());
171     assertEquals(initializationFailTimeout, dataSource.getInitializationFailTimeout());
172     assertEquals(isolateInternalQueries, dataSource.isIsolateInternalQueries());
173 
174     assertEquals(leakDetectionThresholdMs, dataSource.getLeakDetectionThreshold());
175 
176     assertEquals(maxLifetimeMs, dataSource.getMaxLifetime());
177     assertEquals(maxPoolSize, dataSource.getMaximumPoolSize());
178     assertEquals(metricsTrackerFactory, dataSource.getMetricsTrackerFactory());
179     assertEquals(minimumIdle, dataSource.getMinimumIdle());
180 
181     assertEquals(poolName, dataSource.getPoolName());
182     assertEquals(readOnly, dataSource.isReadOnly());
183     assertFalse(dataSource.isRegisterMbeans());
184     assertEquals(schema, dataSource.getSchema());
185     assertNull(dataSource.getTransactionIsolation());
186     assertEquals(validationTimeoutMs, dataSource.getValidationTimeout());
187   }
188 
189   @Test
190   void get_MetricRegistry() throws SQLException {
191     final String url = "jdbc:h2:mem:testdb";
192     final String username = "test_user";
193     final String password = "test_password";
194     final Object metricsRegistry = mock(MetricRegistry.class);
195     Injector injector = Guice.createInjector(new AbstractModule() {
196       @Override
197       protected void configure() {
198         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
199         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
200         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
201         bind(Object.class).annotatedWith(Names.named("hikaricp.metricRegistry")).toInstance(metricsRegistry);
202       }
203     });
204     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
205     HikariDataSource dataSource = (HikariDataSource) provider.get();
206     assertEquals(url, dataSource.getJdbcUrl());
207     assertEquals(username, dataSource.getUsername());
208     assertEquals(password, dataSource.getPassword());
209     assertEquals(metricsRegistry, dataSource.getMetricRegistry());
210   }
211 
212   @Test
213   void get_RegisterMbeans() throws SQLException {
214     final String url = "jdbc:h2:mem:testdb";
215     final String username = "test_user";
216     final String password = "test_password";
217     final boolean registerMbeans = true;
218     Injector injector = Guice.createInjector(new AbstractModule() {
219       @Override
220       protected void configure() {
221         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
222         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
223         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
224         bindConstant().annotatedWith(Names.named("hikaricp.registerMbeans")).to(registerMbeans);
225       }
226     });
227     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
228     HikariDataSource dataSource = (HikariDataSource) provider.get();
229     assertEquals(url, dataSource.getJdbcUrl());
230     assertEquals(username, dataSource.getUsername());
231     assertEquals(password, dataSource.getPassword());
232     assertTrue(dataSource.isRegisterMbeans());
233   }
234 
235   @Test
236   void get_ScheduledExecutor() throws SQLException {
237     final String url = "jdbc:h2:mem:testdb";
238     final String username = "test_user";
239     final String password = "test_password";
240     final ScheduledExecutorService scheduledExecutor = mock(ScheduledExecutorService.class);
241     Injector injector = Guice.createInjector(new AbstractModule() {
242       @Override
243       protected void configure() {
244         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
245         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
246         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
247         bind(ScheduledExecutorService.class).annotatedWith(Names.named("hikaricp.scheduledExecutorService"))
248             .toInstance(scheduledExecutor);
249       }
250     });
251     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
252     HikariDataSource dataSource = (HikariDataSource) provider.get();
253     assertEquals(url, dataSource.getJdbcUrl());
254     assertEquals(username, dataSource.getUsername());
255     assertEquals(password, dataSource.getPassword());
256     assertEquals(scheduledExecutor, dataSource.getScheduledExecutor());
257   }
258 
259   @Test
260   void get_ThreadFactory() throws SQLException {
261     final String url = "jdbc:h2:mem:testdb";
262     final String username = "test_user";
263     final String password = "test_password";
264     final ThreadFactory threadFactory = mock(ThreadFactory.class);
265     Injector injector = Guice.createInjector(new AbstractModule() {
266       @Override
267       protected void configure() {
268         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
269         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
270         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
271         bind(ThreadFactory.class).annotatedWith(Names.named("hikaricp.threadFactory")).toInstance(threadFactory);
272       }
273     });
274     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
275     HikariDataSource dataSource = (HikariDataSource) provider.get();
276     assertEquals(url, dataSource.getJdbcUrl());
277     assertEquals(username, dataSource.getUsername());
278     assertEquals(password, dataSource.getPassword());
279     assertEquals(threadFactory, dataSource.getThreadFactory());
280   }
281 
282   @Test
283   void get_TransactionIsolation() throws SQLException {
284     final String url = "jdbc:h2:mem:testdb";
285     final String username = "test_user";
286     final String password = "test_password";
287     final String transactionIsolation = "TRANSACTION_READ_COMMITTED";
288     Injector injector = Guice.createInjector(new AbstractModule() {
289       @Override
290       protected void configure() {
291         bindConstant().annotatedWith(Names.named("JDBC.url")).to(url);
292         bindConstant().annotatedWith(Names.named("JDBC.username")).to(username);
293         bindConstant().annotatedWith(Names.named("JDBC.password")).to(password);
294         bindConstant().annotatedWith(Names.named("hikaricp.transactionIsolation")).to(transactionIsolation);
295       }
296     });
297     HikariCPProvider provider = injector.getInstance(HikariCPProvider.class);
298     HikariDataSource dataSource = (HikariDataSource) provider.get();
299     assertEquals(url, dataSource.getJdbcUrl());
300     assertEquals(username, dataSource.getUsername());
301     assertEquals(password, dataSource.getPassword());
302     assertEquals(transactionIsolation, dataSource.getTransactionIsolation());
303   }
304 }