diff --git a/modules/jdbc-test/src/test/java/org/testcontainers/junit/EmptyPasswordMysqlTest.java b/modules/jdbc-test/src/test/java/org/testcontainers/junit/EmptyPasswordMysqlTest.java new file mode 100644 index 00000000000..0dfc3149ef5 --- /dev/null +++ b/modules/jdbc-test/src/test/java/org/testcontainers/junit/EmptyPasswordMysqlTest.java @@ -0,0 +1,46 @@ +package org.testcontainers.junit; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.Rule; +import org.junit.Test; +import org.testcontainers.containers.MySQLContainer; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; + +public class EmptyPasswordMysqlTest { + private static final String DB_NAME = "foo"; + private static final String USER = "root"; // MySQL allows empty password with root only + + // Add MYSQL_ROOT_HOST environment so that we can root login from anywhere for testing purposes + @Rule + public MySQLContainer mysql = (MySQLContainer) new MySQLContainer("mysql:5.5") + .withDatabaseName(DB_NAME) + .withUsername(USER) + .withPassword("") + .withEnv("MYSQL_ROOT_HOST", "%"); + + @Test + public void testSimple() throws SQLException { + HikariConfig hikariConfig = new HikariConfig(); + hikariConfig.setJdbcUrl("jdbc:mysql://" + + mysql.getContainerIpAddress() + + ":" + mysql.getMappedPort(MySQLContainer.MYSQL_PORT) + + "/" + DB_NAME); + hikariConfig.setUsername(USER); + hikariConfig.setPassword(""); + + HikariDataSource ds = new HikariDataSource(hikariConfig); + Statement statement = ds.getConnection().createStatement(); + statement.execute("SELECT 1"); + ResultSet resultSet = statement.getResultSet(); + + assertEquals("There is a result", resultSet.next(), true); + int resultSetInt = resultSet.getInt(1); + assertEquals("A basic SELECT query succeeds", 1, resultSetInt); + } +} diff --git a/modules/jdbc-test/src/test/java/org/testcontainers/junit/SimpleMySQLTest.java b/modules/jdbc-test/src/test/java/org/testcontainers/junit/SimpleMySQLTest.java index 572921d8a1e..4c3731fcaf9 100644 --- a/modules/jdbc-test/src/test/java/org/testcontainers/junit/SimpleMySQLTest.java +++ b/modules/jdbc-test/src/test/java/org/testcontainers/junit/SimpleMySQLTest.java @@ -1,22 +1,26 @@ package org.testcontainers.junit; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; +import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; +import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import lombok.NonNull; + import org.apache.commons.lang.SystemUtils; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import static org.junit.Assume.assumeFalse; -import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; +import lombok.NonNull; /** @@ -128,6 +132,21 @@ public void testMySQL8() throws SQLException { } } + @Test + public void testEmptyPasswordWithNonRootUser() { + + MySQLContainer container = (MySQLContainer) new MySQLContainer("mysql:5.5").withDatabaseName("TEST") + .withUsername("test").withPassword("").withEnv("MYSQL_ROOT_HOST", "%"); + + try { + container.start(); + fail("ContainerLaunchException expected to be thrown"); + } catch (ContainerLaunchException e) { + } finally { + container.stop(); + } + } + @NonNull protected ResultSet performQuery(MySQLContainer containerRule, String sql) throws SQLException { HikariConfig hikariConfig = new HikariConfig(); diff --git a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java index 2dbc303407f..6d9139fa971 100644 --- a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java +++ b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java @@ -19,6 +19,7 @@ public class MySQLContainer> extends JdbcDatab private String databaseName = "test"; private String username = "test"; private String password = "test"; + private static final String MYSQL_ROOT_USER = "root"; public MySQLContainer() { super(IMAGE + ":" + DEFAULT_TAG); @@ -36,13 +37,20 @@ protected Set getLivenessCheckPorts() { @Override protected void configure() { - optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", "mysql-default-conf"); + optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", + "mysql-default-conf"); addExposedPort(MYSQL_PORT); addEnv("MYSQL_DATABASE", databaseName); addEnv("MYSQL_USER", username); - addEnv("MYSQL_PASSWORD", password); - addEnv("MYSQL_ROOT_PASSWORD", password); + if (password != null && !password.isEmpty()) { + addEnv("MYSQL_PASSWORD", password); + addEnv("MYSQL_ROOT_PASSWORD", password); + } else if (MYSQL_ROOT_USER.equalsIgnoreCase(username)) { + addEnv("MYSQL_ALLOW_EMPTY_PASSWORD", "yes"); + } else { + throw new ContainerLaunchException("Empty password can be used only with the root user"); + } setStartupAttempts(3); }