Improve test coverage.

pull/192/head
Brett Wooldridge 11 years ago
parent 68a92e7abd
commit 8b96191726

@ -27,7 +27,9 @@ import org.junit.Assert;
import org.junit.Test;
import com.zaxxer.hikari.mocks.StubConnection;
import com.zaxxer.hikari.mocks.StubStatement;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
* System property testProxy can be one of:
@ -39,350 +41,356 @@ import com.zaxxer.hikari.pool.HikariPool;
*/
public class TestConnections
{
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT * FROM device WHERE device_id=?");
Assert.assertNotNull(statement);
statement.setInt(1, 0);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
Assert.assertFalse(resultSet.next());
resultSet.close();
statement.close();
connection.close();
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testMaxLifetime() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100");
HikariDataSource ds = new HikariDataSource(config);
try
{
System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(2000);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testMaxLifetime2() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(800);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testDoubleClose() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Connection connection = ds.getConnection();
connection.close();
connection.close();
}
finally
{
ds.close();
}
}
@Test
public void testEviction() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(5);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Connection connection = ds.getConnection();
Assert.assertEquals(1, TestElf.getPool(ds).getTotalConnections());
ds.evictConnection(connection);
Assert.assertEquals(0, TestElf.getPool(ds).getTotalConnections());
}
finally
{
ds.close();
}
}
@Test
public void testBackfill() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(500);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
// This will take the pool down to zero
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT some, thing FROM somewhere WHERE something=?");
Assert.assertNotNull(statement);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
try
{
statement.getMaxFieldSize();
Assert.fail();
}
catch (Exception e)
{
Assert.assertSame(SQLException.class, e.getClass());
}
// The connection will be ejected from the pool here
connection.close();
Assert.assertSame("Totals connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
// This will cause a backfill
connection = ds.getConnection();
connection.close();
Assert.assertTrue("Totals connections not as expected", TestElf.getPool(ds).getTotalConnections() > 0);
Assert.assertTrue("Idle connections not as expected", TestElf.getPool(ds).getIdleConnections() > 0);
}
finally
{
ds.close();
}
}
@Test
public void testMaximumPoolLimit() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(1));
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.count.set(0);
final HikariDataSource ds = new HikariDataSource(config);
try
{
Thread[] threads = new Thread[20];
for (int i = 0; i < threads.length; i++)
{
threads[i] = new Thread(new Runnable() {
public void run()
{
try
{
Connection connection = ds.getConnection();
Thread.sleep(1000);
connection.close();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
for (int i = 0; i < threads.length; i++)
{
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
{
threads[i].join();
}
Assert.assertEquals(4, StubConnection.count.get());
}
finally
{
ds.close();
}
}
@Test
public void testGetWithUsername() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(4);
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
final HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection1 = ds.getConnection("foo", "bar");
connection1.close();
Connection connection2 = ds.getConnection("foo", "bar");
connection2.close();
Assert.assertSame(connection1.unwrap(Connection.class), connection2.unwrap(Connection.class));
Connection connection3 = ds.getConnection("faz", "baf");
connection3.close();
HashMap<Object,HikariPool> multiPool = TestElf.getMultiPool(ds);
Assert.assertTrue(multiPool.size() > 1);
Object[] array = multiPool.keySet().toArray();
Assert.assertNotEquals(array[0], array[1]);
}
finally {
ds.close();
}
}
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT * FROM device WHERE device_id=?");
Assert.assertNotNull(statement);
statement.setInt(1, 0);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
Assert.assertFalse(resultSet.next());
resultSet.close();
statement.close();
connection.close();
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testMaxLifetime() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100");
HikariDataSource ds = new HikariDataSource(config);
try {
System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(2000);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testMaxLifetime2() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(800);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testDoubleClose() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection = ds.getConnection();
connection.close();
connection.close();
}
finally {
ds.close();
}
}
@Test
public void testEviction() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(5);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection = ds.getConnection();
Assert.assertEquals(1, TestElf.getPool(ds).getTotalConnections());
ds.evictConnection(connection);
Assert.assertEquals(0, TestElf.getPool(ds).getTotalConnections());
}
finally {
ds.close();
}
}
@Test
public void testBackfill() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(500);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
// This will take the pool down to zero
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT some, thing FROM somewhere WHERE something=?");
Assert.assertNotNull(statement);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
try {
statement.getMaxFieldSize();
Assert.fail();
}
catch (Exception e) {
Assert.assertSame(SQLException.class, e.getClass());
}
// The connection will be ejected from the pool here
connection.close();
Assert.assertSame("Totals connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
// This will cause a backfill
connection = ds.getConnection();
connection.close();
Assert.assertTrue("Totals connections not as expected", TestElf.getPool(ds).getTotalConnections() > 0);
Assert.assertTrue("Idle connections not as expected", TestElf.getPool(ds).getIdleConnections() > 0);
}
finally {
ds.close();
}
}
@Test
public void testMaximumPoolLimit() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(1));
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.count.set(0);
final HikariDataSource ds = new HikariDataSource(config);
try {
Thread[] threads = new Thread[20];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run()
{
try {
Connection connection = ds.getConnection();
Thread.sleep(500);
connection.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
Assert.assertEquals(4, StubConnection.count.get());
}
finally {
ds.close();
}
}
@Test
public void testGetWithUsername() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(4);
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
final HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection1 = ds.getConnection("foo", "bar");
connection1.close();
Connection connection2 = ds.getConnection("foo", "bar");
connection2.close();
Assert.assertSame(connection1.unwrap(Connection.class), connection2.unwrap(Connection.class));
Connection connection3 = ds.getConnection("faz", "baf");
connection3.close();
HashMap<Object, HikariPool> multiPool = TestElf.getMultiPool(ds);
Assert.assertTrue(multiPool.size() > 1);
Object[] array = multiPool.keySet().toArray();
Assert.assertNotEquals(array[0], array[1]);
}
finally {
ds.close();
}
}
@Test
public void testOldDriver() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.oldDriver = true;
StubStatement.oldDriver = true;
TestElf.resetPoolUtilities();
HikariDataSource ds = new HikariDataSource(config);
try {
PoolUtilities.quietlySleep(1001L);
Connection connection = ds.getConnection();
connection.close();
}
finally {
StubConnection.oldDriver = false;
StubStatement.oldDriver = false;
TestElf.resetPoolUtilities();
ds.close();
}
}
}

@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
import org.slf4j.impl.SimpleLogger;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
* Utility methods for testing.
@ -73,6 +74,22 @@ public final class TestElf
}
}
public static void resetPoolUtilities()
{
try {
Field field = PoolUtilities.class.getDeclaredField("jdbc4checked");
field.setAccessible(true);
field.setBoolean(null, false);
field = PoolUtilities.class.getDeclaredField("queryTimeoutSupported");
field.setAccessible(true);
field.setBoolean(null, true);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void setSlf4jTargetStream(Class<?> clazz, PrintStream stream)
{
SimpleLogger simpleLogger = (SimpleLogger) LoggerFactory.getLogger(clazz);

@ -47,6 +47,7 @@ public class StubConnection extends StubBaseConnection implements Connection
{
public static final AtomicInteger count = new AtomicInteger();
public static volatile boolean slowCreate;
public static volatile boolean oldDriver;
private static long foo;
private boolean autoCommit;
@ -476,6 +477,10 @@ public class StubConnection extends StubBaseConnection implements Connection
/** {@inheritDoc} */
public int getNetworkTimeout() throws SQLException
{
if (oldDriver) {
throw new AbstractMethodError();
}
return 0;
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.mocks;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Statement;
@ -28,355 +29,358 @@ import java.sql.Statement;
*/
public class StubStatement implements Statement
{
private boolean closed;
private Connection connection;
public StubStatement(Connection connection)
{
this.connection = connection;
}
/** {@inheritDoc} */
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
checkClosed();
return (T) this;
}
/** {@inheritDoc} */
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
checkClosed();
StubResultSet resultSet = new StubResultSet();
return resultSet;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void close() throws SQLException
{
closed = true;
}
/** {@inheritDoc} */
@Override
public int getMaxFieldSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxFieldSize(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getMaxRows() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxRows(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setEscapeProcessing(boolean enable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getQueryTimeout() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setQueryTimeout(int seconds) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void cancel() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public SQLWarning getWarnings() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public void clearWarnings() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setCursorName(String name) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getResultSet() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int getUpdateCount() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public void setFetchDirection(int direction) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchDirection() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setFetchSize(int rows) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetConcurrency() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetType() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void addBatch(String sql) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void clearBatch() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int[] executeBatch() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public Connection getConnection() throws SQLException
{
checkClosed();
return connection;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults(int current) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getGeneratedKeys() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public int getResultSetHoldability() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean isClosed() throws SQLException
{
return closed;
}
/** {@inheritDoc} */
@Override
public void setPoolable(boolean poolable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean isPoolable() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
public void closeOnCompletion() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
public boolean isCloseOnCompletion() throws SQLException
{
checkClosed();
return false;
}
private void checkClosed() throws SQLException
{
if (closed)
{
throw new SQLException("Statement is closed");
}
}
public static volatile boolean oldDriver;
private boolean closed;
private Connection connection;
public StubStatement(Connection connection) {
this.connection = connection;
}
/** {@inheritDoc} */
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
checkClosed();
return (T) this;
}
/** {@inheritDoc} */
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
checkClosed();
StubResultSet resultSet = new StubResultSet();
return resultSet;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void close() throws SQLException
{
closed = true;
}
/** {@inheritDoc} */
@Override
public int getMaxFieldSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxFieldSize(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getMaxRows() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxRows(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setEscapeProcessing(boolean enable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getQueryTimeout() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setQueryTimeout(int seconds) throws SQLException
{
if (oldDriver) {
throw new SQLFeatureNotSupportedException();
}
checkClosed();
}
/** {@inheritDoc} */
@Override
public void cancel() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public SQLWarning getWarnings() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public void clearWarnings() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setCursorName(String name) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getResultSet() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int getUpdateCount() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public void setFetchDirection(int direction) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchDirection() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setFetchSize(int rows) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetConcurrency() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetType() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void addBatch(String sql) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void clearBatch() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int[] executeBatch() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public Connection getConnection() throws SQLException
{
checkClosed();
return connection;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults(int current) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getGeneratedKeys() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public int getResultSetHoldability() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean isClosed() throws SQLException
{
return closed;
}
/** {@inheritDoc} */
@Override
public void setPoolable(boolean poolable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean isPoolable() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
public void closeOnCompletion() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
public boolean isCloseOnCompletion() throws SQLException
{
checkClosed();
return false;
}
private void checkClosed() throws SQLException
{
if (closed) {
throw new SQLException("Statement is closed");
}
}
}

@ -27,7 +27,9 @@ import org.junit.Assert;
import org.junit.Test;
import com.zaxxer.hikari.mocks.StubConnection;
import com.zaxxer.hikari.mocks.StubStatement;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
* System property testProxy can be one of:
@ -39,350 +41,356 @@ import com.zaxxer.hikari.pool.HikariPool;
*/
public class TestConnections
{
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT * FROM device WHERE device_id=?");
Assert.assertNotNull(statement);
statement.setInt(1, 0);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
Assert.assertFalse(resultSet.next());
resultSet.close();
statement.close();
connection.close();
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testMaxLifetime() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100");
HikariDataSource ds = new HikariDataSource(config);
try
{
System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(2000);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testMaxLifetime2() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(800);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally
{
ds.close();
}
}
@Test
public void testDoubleClose() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Connection connection = ds.getConnection();
connection.close();
connection.close();
}
finally
{
ds.close();
}
}
@Test
public void testEviction() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(5);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Connection connection = ds.getConnection();
Assert.assertEquals(1, TestElf.getPool(ds).getTotalConnections());
ds.evictConnection(connection);
Assert.assertEquals(0, TestElf.getPool(ds).getTotalConnections());
}
finally
{
ds.close();
}
}
@Test
public void testBackfill() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(500);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try
{
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
// This will take the pool down to zero
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT some, thing FROM somewhere WHERE something=?");
Assert.assertNotNull(statement);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
try
{
statement.getMaxFieldSize();
Assert.fail();
}
catch (Exception e)
{
Assert.assertSame(SQLException.class, e.getClass());
}
// The connection will be ejected from the pool here
connection.close();
Assert.assertSame("Totals connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
// This will cause a backfill
connection = ds.getConnection();
connection.close();
Assert.assertTrue("Totals connections not as expected", TestElf.getPool(ds).getTotalConnections() > 0);
Assert.assertTrue("Idle connections not as expected", TestElf.getPool(ds).getIdleConnections() > 0);
}
finally
{
ds.close();
}
}
@Test
public void testMaximumPoolLimit() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(1));
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.count.set(0);
final HikariDataSource ds = new HikariDataSource(config);
try
{
Thread[] threads = new Thread[20];
for (int i = 0; i < threads.length; i++)
{
threads[i] = new Thread(new Runnable() {
public void run()
{
try
{
Connection connection = ds.getConnection();
Thread.sleep(1000);
connection.close();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
for (int i = 0; i < threads.length; i++)
{
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
{
threads[i].join();
}
Assert.assertEquals(4, StubConnection.count.get());
}
finally
{
ds.close();
}
}
@Test
public void testGetWithUsername() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(4);
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
final HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection1 = ds.getConnection("foo", "bar");
connection1.close();
Connection connection2 = ds.getConnection("foo", "bar");
connection2.close();
Assert.assertSame(connection1.unwrap(Connection.class), connection2.unwrap(Connection.class));
Connection connection3 = ds.getConnection("faz", "baf");
connection3.close();
HashMap<Object,HikariPool> multiPool = TestElf.getMultiPool(ds);
Assert.assertTrue(multiPool.size() > 1);
Object[] array = multiPool.keySet().toArray();
Assert.assertNotEquals(array[0], array[1]);
}
finally {
ds.close();
}
}
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT * FROM device WHERE device_id=?");
Assert.assertNotNull(statement);
statement.setInt(1, 0);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
Assert.assertFalse(resultSet.next());
resultSet.close();
statement.close();
connection.close();
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testMaxLifetime() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100");
HikariDataSource ds = new HikariDataSource(config);
try {
System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs");
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(2000);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testMaxLifetime2() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
ds.setMaxLifetime(700);
Assert.assertSame("Total connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection.close();
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
Thread.sleep(800);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
connection2.close();
Assert.assertSame("Post total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Post idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
}
finally {
ds.close();
}
}
@Test
public void testDoubleClose() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection = ds.getConnection();
connection.close();
connection.close();
}
finally {
ds.close();
}
}
@Test
public void testEviction() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(5);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection = ds.getConnection();
Assert.assertEquals(1, TestElf.getPool(ds).getTotalConnections());
ds.evictConnection(connection);
Assert.assertEquals(0, TestElf.getPool(ds).getTotalConnections());
}
finally {
ds.close();
}
}
@Test
public void testBackfill() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(500);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
try {
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
// This will take the pool down to zero
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
PreparedStatement statement = connection.prepareStatement("SELECT some, thing FROM somewhere WHERE something=?");
Assert.assertNotNull(statement);
ResultSet resultSet = statement.executeQuery();
Assert.assertNotNull(resultSet);
try {
statement.getMaxFieldSize();
Assert.fail();
}
catch (Exception e) {
Assert.assertSame(SQLException.class, e.getClass());
}
// The connection will be ejected from the pool here
connection.close();
Assert.assertSame("Totals connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
// This will cause a backfill
connection = ds.getConnection();
connection.close();
Assert.assertTrue("Totals connections not as expected", TestElf.getPool(ds).getTotalConnections() > 0);
Assert.assertTrue("Idle connections not as expected", TestElf.getPool(ds).getIdleConnections() > 0);
}
finally {
ds.close();
}
}
@Test
public void testMaximumPoolLimit() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(4);
config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(1));
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.count.set(0);
final HikariDataSource ds = new HikariDataSource(config);
try {
Thread[] threads = new Thread[20];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run()
{
try {
Connection connection = ds.getConnection();
Thread.sleep(500);
connection.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
Assert.assertEquals(4, StubConnection.count.get());
}
finally {
ds.close();
}
}
@Test
public void testGetWithUsername() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(0);
config.setMaximumPoolSize(4);
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
final HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection1 = ds.getConnection("foo", "bar");
connection1.close();
Connection connection2 = ds.getConnection("foo", "bar");
connection2.close();
Assert.assertSame(connection1.unwrap(Connection.class), connection2.unwrap(Connection.class));
Connection connection3 = ds.getConnection("faz", "baf");
connection3.close();
HashMap<Object, HikariPool> multiPool = TestElf.getMultiPool(ds);
Assert.assertTrue(multiPool.size() > 1);
Object[] array = multiPool.keySet().toArray();
Assert.assertNotEquals(array[0], array[1]);
}
finally {
ds.close();
}
}
@Test
public void testOldDriver() throws Exception
{
HikariConfig config = new HikariConfig();
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
StubConnection.oldDriver = true;
StubStatement.oldDriver = true;
TestElf.resetPoolUtilities();
HikariDataSource ds = new HikariDataSource(config);
try {
PoolUtilities.quietlySleep(1001L);
Connection connection = ds.getConnection();
connection.close();
}
finally {
StubConnection.oldDriver = false;
StubStatement.oldDriver = false;
TestElf.resetPoolUtilities();
ds.close();
}
}
}

@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
import org.slf4j.impl.SimpleLogger;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
* Utility methods for testing.
@ -73,6 +74,22 @@ public final class TestElf
}
}
public static void resetPoolUtilities()
{
try {
Field field = PoolUtilities.class.getDeclaredField("jdbc4checked");
field.setAccessible(true);
field.setBoolean(null, false);
field = PoolUtilities.class.getDeclaredField("queryTimeoutSupported");
field.setAccessible(true);
field.setBoolean(null, true);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void setSlf4jTargetStream(Class<?> clazz, PrintStream stream)
{
SimpleLogger simpleLogger = (SimpleLogger) LoggerFactory.getLogger(clazz);

@ -47,6 +47,7 @@ public class StubConnection extends StubBaseConnection implements Connection
{
public static final AtomicInteger count = new AtomicInteger();
public static volatile boolean slowCreate;
public static volatile boolean oldDriver;
private static long foo;
private boolean autoCommit;
@ -476,6 +477,10 @@ public class StubConnection extends StubBaseConnection implements Connection
/** {@inheritDoc} */
public int getNetworkTimeout() throws SQLException
{
if (oldDriver) {
throw new AbstractMethodError();
}
return 0;
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.mocks;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Statement;
@ -28,355 +29,358 @@ import java.sql.Statement;
*/
public class StubStatement implements Statement
{
private boolean closed;
private Connection connection;
public StubStatement(Connection connection)
{
this.connection = connection;
}
/** {@inheritDoc} */
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
checkClosed();
return (T) this;
}
/** {@inheritDoc} */
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
checkClosed();
StubResultSet resultSet = new StubResultSet();
return resultSet;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void close() throws SQLException
{
closed = true;
}
/** {@inheritDoc} */
@Override
public int getMaxFieldSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxFieldSize(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getMaxRows() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxRows(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setEscapeProcessing(boolean enable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getQueryTimeout() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setQueryTimeout(int seconds) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void cancel() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public SQLWarning getWarnings() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public void clearWarnings() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setCursorName(String name) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getResultSet() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int getUpdateCount() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public void setFetchDirection(int direction) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchDirection() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setFetchSize(int rows) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetConcurrency() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetType() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void addBatch(String sql) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void clearBatch() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int[] executeBatch() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public Connection getConnection() throws SQLException
{
checkClosed();
return connection;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults(int current) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getGeneratedKeys() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public int getResultSetHoldability() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean isClosed() throws SQLException
{
return closed;
}
/** {@inheritDoc} */
@Override
public void setPoolable(boolean poolable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean isPoolable() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
public void closeOnCompletion() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
public boolean isCloseOnCompletion() throws SQLException
{
checkClosed();
return false;
}
private void checkClosed() throws SQLException
{
if (closed)
{
throw new SQLException("Statement is closed");
}
}
public static volatile boolean oldDriver;
private boolean closed;
private Connection connection;
public StubStatement(Connection connection) {
this.connection = connection;
}
/** {@inheritDoc} */
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
checkClosed();
return (T) this;
}
/** {@inheritDoc} */
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
checkClosed();
StubResultSet resultSet = new StubResultSet();
return resultSet;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void close() throws SQLException
{
closed = true;
}
/** {@inheritDoc} */
@Override
public int getMaxFieldSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxFieldSize(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getMaxRows() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setMaxRows(int max) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setEscapeProcessing(boolean enable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getQueryTimeout() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setQueryTimeout(int seconds) throws SQLException
{
if (oldDriver) {
throw new SQLFeatureNotSupportedException();
}
checkClosed();
}
/** {@inheritDoc} */
@Override
public void cancel() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public SQLWarning getWarnings() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public void clearWarnings() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void setCursorName(String name) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getResultSet() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int getUpdateCount() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public void setFetchDirection(int direction) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchDirection() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void setFetchSize(int rows) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int getFetchSize() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetConcurrency() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int getResultSetType() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public void addBatch(String sql) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public void clearBatch() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public int[] executeBatch() throws SQLException
{
checkClosed();
return null;
}
/** {@inheritDoc} */
@Override
public Connection getConnection() throws SQLException
{
checkClosed();
return connection;
}
/** {@inheritDoc} */
@Override
public boolean getMoreResults(int current) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public ResultSet getGeneratedKeys() throws SQLException
{
checkClosed();
return new StubResultSet();
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
@Override
public int getResultSetHoldability() throws SQLException
{
checkClosed();
return 0;
}
/** {@inheritDoc} */
@Override
public boolean isClosed() throws SQLException
{
return closed;
}
/** {@inheritDoc} */
@Override
public void setPoolable(boolean poolable) throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
@Override
public boolean isPoolable() throws SQLException
{
checkClosed();
return false;
}
/** {@inheritDoc} */
public void closeOnCompletion() throws SQLException
{
checkClosed();
}
/** {@inheritDoc} */
public boolean isCloseOnCompletion() throws SQLException
{
checkClosed();
return false;
}
private void checkClosed() throws SQLException
{
if (closed) {
throw new SQLException("Statement is closed");
}
}
}

Loading…
Cancel
Save