Back to Repositories

Testing Concurrent Connection Closure Handling in HikariCP

This test suite validates the concurrent closing of database connections in HikariCP, focusing on thread safety and resource management. It ensures that multiple threads can safely close PreparedStatement objects without causing deadlocks or resource leaks.

Test Coverage Overview

The test suite focuses on concurrent connection handling in HikariCP’s connection pooling implementation.

Key areas covered include:
  • Concurrent PreparedStatement closure operations
  • Thread pool execution with multiple parallel close requests
  • Resource cleanup under high concurrency
  • Connection pool stability under stress

Implementation Analysis

The testing approach employs a multi-threaded execution model using Java’s ExecutorService framework. It creates 500 prepared statements and closes them concurrently using 10 parallel threads, validating HikariCP’s thread-safety mechanisms.

Technical implementation features:
  • Fixed thread pool execution
  • Future-based completion tracking
  • Try-with-resources for automatic resource management
  • Callable interface implementation for asynchronous execution

Technical Details

Testing infrastructure includes:
  • JUnit testing framework
  • HikariConfig for connection pool configuration
  • StubDataSource for mock database connections
  • ExecutorService for parallel execution
  • Java Futures for asynchronous task management

Best Practices Demonstrated

The test exemplifies several testing best practices for concurrent systems.

Notable practices include:
  • Proper resource cleanup using try-with-resources
  • Controlled concurrent execution with fixed thread pools
  • Systematic verification of parallel operations
  • Mock data source usage for isolated testing
  • Clear separation of setup, execution, and verification phases

brettwooldridge/hikaricp

src/test/java/com/zaxxer/hikari/pool/ConcurrentCloseConnectionTest.java

            
/*
 * Copyright (C) 2013, 2014 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.pool;

import static com.zaxxer.hikari.pool.TestElf.newHikariConfig;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.junit.Test;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

/**
 * @author Matthew Tambara ([email protected])
 */
public class ConcurrentCloseConnectionTest
{
   @Test
   public void testConcurrentClose() throws Exception
   {
	  HikariConfig config = newHikariConfig();
      config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");

	  try (HikariDataSource ds = new HikariDataSource(config);
	      final Connection connection = ds.getConnection()) {

		  ExecutorService executorService = Executors.newFixedThreadPool(10);

		  List<Future<?>> futures = new ArrayList<>();

		  for (int i = 0; i < 500; i++) {
			  final PreparedStatement preparedStatement =
				  connection.prepareStatement("");

			  futures.add(executorService.submit(new Callable<Void>() {

				  @Override
				  public Void call() throws Exception {
					  preparedStatement.close();

					  return null;
				  }

			  }));
		  }

		  executorService.shutdown();

		  for (Future<?> future : futures) {
			  future.get();
		  }
	  }
   }
}