package org.testcontainers.jdbc; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.lang.SystemUtils; import org.junit.AfterClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import static java.util.Arrays.asList; import static org.junit.Assume.assumeFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; @RunWith(Parameterized.class) public class JDBCDriverTest { @Parameter public String jdbcUrl; @Parameter(1) public boolean performTestForScriptedSchema; @Parameter(2) public boolean performTestForCharacterSet; @Parameter(3) public boolean performTestForCustomIniFile; @Parameterized.Parameters(name = "{index} - {0}") public static Iterable<Object[]> data() { return asList( new Object[][]{ {"jdbc:tc:mysql:5.5.43://hostname/databasename", false, false, false}, {"jdbc:tc:mysql://hostname/databasename?TC_INITSCRIPT=somepath/init_mysql.sql", true, false, false}, {"jdbc:tc:mysql://hostname/databasename?TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction", true, false, false}, {"jdbc:tc:mysql://hostname/databasename?useUnicode=yes&characterEncoding=utf8", false, true, false}, {"jdbc:tc:mysql://hostname/databasename", false, false, false}, {"jdbc:tc:postgresql://hostname/databasename", false, false, false}, {"jdbc:tc:mariadb:10.1.16://hostname/databasename", false, false, false}, {"jdbc:tc:mariadb://hostname/databasename", false, false, false}, {"jdbc:tc:mariadb://hostname/databasename?useUnicode=yes&characterEncoding=utf8", false, true, false}, {"jdbc:tc:mariadb://hostname/databasename?TC_INITSCRIPT=somepath/init_mariadb.sql", true, false, false}, {"jdbc:tc:mariadb://hostname/databasename?TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction", true, false, false}, {"jdbc:tc:mysql:5.6://hostname/databasename?TC_MY_CNF=somepath/mysql_conf_override", false, false, true}, {"jdbc:tc:mariadb:10.1.16://hostname/databasename?TC_MY_CNF=somepath/mariadb_conf_override", false, false, true} }); } public static void sampleInitFunction(Connection connection) throws SQLException { connection.createStatement().execute("CREATE TABLE bar (\n" + " foo VARCHAR(255)\n" + ");"); connection.createStatement().execute("INSERT INTO bar (foo) VALUES ('hello world');"); connection.createStatement().execute("CREATE TABLE my_counter (\n" + " n INT\n" + ");"); } @AfterClass public static void testCleanup() { ContainerDatabaseDriver.killContainers(); } @Test public void test() throws SQLException { performSimpleTest(jdbcUrl); if (performTestForScriptedSchema) { performTestForScriptedSchema(jdbcUrl); } if (performTestForCharacterSet) { performSimpleTestWithCharacterSet(jdbcUrl); } if (performTestForCustomIniFile) { performTestForCustomIniFile(jdbcUrl); } } private void performSimpleTest(String jdbcUrl) throws SQLException { try (HikariDataSource dataSource = getDataSource(jdbcUrl, 1)) { boolean result = new QueryRunner(dataSource).query("SELECT 1", rs -> { rs.next(); int resultSetInt = rs.getInt(1); assertEquals("A basic SELECT query succeeds", 1, resultSetInt); return true; }); assertTrue("The database returned a record as expected", result); } } private void performTestForScriptedSchema(String jdbcUrl) throws SQLException { try (HikariDataSource dataSource = getDataSource(jdbcUrl, 1)) { boolean result = new QueryRunner(dataSource).query("SELECT foo FROM bar WHERE foo LIKE '%world'", rs -> { rs.next(); String resultSetString = rs.getString(1); assertEquals("A basic SELECT query succeeds where the schema has been applied from a script", "hello world", resultSetString); return true; }); assertTrue("The database returned a record as expected", result); } } private void performSimpleTestWithCharacterSet(String jdbcUrl) throws SQLException { try (HikariDataSource dataSource = getDataSource(jdbcUrl, 1)) { boolean result = new QueryRunner(dataSource).query("SHOW VARIABLES LIKE 'character\\_set\\_connection'", rs -> { rs.next(); String resultSetInt = rs.getString(2); assertEquals("Passing query parameters to set DB connection encoding is successful", "utf8", resultSetInt); return true; }); assertTrue("The database returned a record as expected", result); } } private void performTestForCustomIniFile(final String jdbcUrl) throws SQLException { assumeFalse(SystemUtils.IS_OS_WINDOWS); try (HikariDataSource ds = getDataSource(jdbcUrl, 1)) { Statement statement = ds.getConnection().createStatement(); statement.execute("SELECT @@GLOBAL.innodb_file_format"); ResultSet resultSet = statement.getResultSet(); assertTrue("The query returns a result", resultSet.next()); String result = resultSet.getString(1); assertEquals("The InnoDB file format has been set by the ini file content", "Barracuda", result); } } private HikariDataSource getDataSource(String jdbcUrl, int poolSize) { HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setJdbcUrl(jdbcUrl); hikariConfig.setConnectionTestQuery("SELECT 1"); hikariConfig.setMinimumIdle(1); hikariConfig.setMaximumPoolSize(poolSize); return new HikariDataSource(hikariConfig); } }