Back to Repositories

Validating Connection Pool Management in HikariCP

This test suite validates core connection pool functionality in HikariCP, focusing on idle timeout behavior and connection management. It verifies proper pool initialization, connection lifecycle, and resource cleanup under various configurations.

Test Coverage Overview

The test suite provides comprehensive coverage of HikariCP’s basic pool operations.

Key areas tested include:
  • Connection pool initialization and configuration
  • Idle timeout functionality across different pool sizes
  • Connection acquisition and release patterns
  • Pool size management and scaling
Edge cases covered include minimum/maximum pool size boundaries and timeout threshold behaviors.

Implementation Analysis

The testing approach employs JUnit 4 framework with systematic verification of pool states. Tests utilize precise timing controls and connection state assertions to validate pool behavior.

Implementation patterns include:
  • Before/After test setup with H2 in-memory database
  • Controlled environment using system properties
  • Connection lifecycle validation
  • Pool metrics verification

Technical Details

Testing infrastructure includes:
  • JUnit 4 test framework
  • H2 in-memory database
  • HikariCP configuration utilities
  • Custom test helpers (TestElf)
Configuration focuses on:
  • Pool size parameters
  • Connection test queries
  • Idle timeout settings
  • Database connection properties

Best Practices Demonstrated

The test suite exemplifies robust testing practices through careful resource management and thorough state verification.

Notable practices include:
  • Proper test isolation and cleanup
  • Explicit timing controls
  • Comprehensive state assertions
  • Resource cleanup using try-with-resources
  • Clear test method naming and organization

brettwooldridge/hikaricp

src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java

            
/*
 * Copyright (C) 2016 Brett Wooldridge
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.zaxxer.hikari.db;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import static com.zaxxer.hikari.pool.TestElf.getPool;
import static com.zaxxer.hikari.pool.TestElf.newHikariConfig;
import static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
 * @author brettw
 *
 */
public class BasicPoolTest
{
   @Before
   public void setup() throws SQLException
   {
       HikariConfig config = newHikariConfig();
       config.setMinimumIdle(1);
       config.setMaximumPoolSize(2);
       config.setConnectionTestQuery("SELECT 1");
       config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
       config.addDataSourceProperty("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");

       try (HikariDataSource ds = new HikariDataSource(config);
            Connection conn = ds.getConnection();
            Statement stmt = conn.createStatement()) {
          stmt.execute("DROP TABLE IF EXISTS basic_pool_test");
          stmt.execute("CREATE TABLE basic_pool_test ("
                            + "id INTEGER NOT NULL PRIMARY KEY, "
                            + "timestamp TIMESTAMP, "
                            + "string VARCHAR(128), "
                            + "string_from_number NUMERIC "
                            + ")");
       }
   }

   @Test
   public void testIdleTimeout() throws InterruptedException, SQLException
   {
      HikariConfig config = newHikariConfig();
      config.setMinimumIdle(5);
      config.setMaximumPoolSize(10);
      config.setConnectionTestQuery("SELECT 1");
      config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
      config.addDataSourceProperty("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");

      System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "1000");

      try (HikariDataSource ds = new HikariDataSource(config)) {
         getUnsealedConfig(ds).setIdleTimeout(3000);

         System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");

         SECONDS.sleep(1);

         HikariPool pool = getPool(ds);

         assertEquals("Total connections not as expected", 5, pool.getTotalConnections());
         assertEquals("Idle connections not as expected", 5, pool.getIdleConnections());

         try (Connection connection = ds.getConnection()) {
            Assert.assertNotNull(connection);

            MILLISECONDS.sleep(1500);

            assertEquals("Second total connections not as expected", 6, pool.getTotalConnections());
            assertEquals("Second idle connections not as expected", 5, pool.getIdleConnections());
         }

         assertEquals("Idle connections not as expected", 6, pool.getIdleConnections());

         MILLISECONDS.sleep(3000);

         assertEquals("Third total connections not as expected", 5, pool.getTotalConnections());
         assertEquals("Third idle connections not as expected", 5, pool.getIdleConnections());
      }
   }

   @Test
   public void testIdleTimeout2() throws InterruptedException, SQLException
   {
      HikariConfig config = newHikariConfig();
      config.setMaximumPoolSize(50);
      config.setConnectionTestQuery("SELECT 1");
      config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
      config.addDataSourceProperty("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");

      System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "1000");

      try (HikariDataSource ds = new HikariDataSource(config)) {
         System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");

         SECONDS.sleep(3);

         HikariPool pool = getPool(ds);

         getUnsealedConfig(ds).setIdleTimeout(3000);

         assertEquals("Total connections not as expected", 50, pool.getTotalConnections());
         assertEquals("Idle connections not as expected", 50, pool.getIdleConnections());

         try (Connection connection = ds.getConnection()) {
            assertNotNull(connection);

            MILLISECONDS.sleep(1500);

            assertEquals("Second total connections not as expected", 50, pool.getTotalConnections());
            assertEquals("Second idle connections not as expected", 49, pool.getIdleConnections());
         }

         assertEquals("Idle connections not as expected", 50, pool.getIdleConnections());

         SECONDS.sleep(3);

         assertEquals("Third total connections not as expected", 50, pool.getTotalConnections());
         assertEquals("Third idle connections not as expected", 50, pool.getIdleConnections());
      }
   }
}