Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/modules/databases/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Testcontainers module for [MySQL](https://hub.docker.com/_/mysql)
You can start a MySQL container instance from any Java application by using:

<!--codeinclude-->
[Container definition](../../../modules/mysql/src/test/java/org/testcontainers/junit/mysql/SimpleMySQLTest.java) inside_block:container
[Container definition](../../../modules/mysql/src/test/java/org/testcontainers/mysql/MySQLContainerTest.java) inside_block:container
<!--/codeinclude-->

See [Database containers](./index.md) for documentation and usage that is common to all relational database container types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
* Supported image: {@code mysql}
* <p>
* Exposed ports: 3306
*
* @deprecated use {@link org.testcontainers.mysql.MySQLContainer} instead.
*/
@Deprecated
public class MySQLContainer<SELF extends MySQLContainer<SELF>> extends JdbcDatabaseContainer<SELF> {

public static final String NAME = "mysql";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package org.testcontainers.mysql;

import org.jetbrains.annotations.NotNull;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.utility.DockerImageName;

import java.util.Set;

/**
* Testcontainers implementation for MySQL.
* <p>
* Supported image: {@code mysql}
* <p>
* Exposed ports: 3306
*/
public class MySQLContainer extends JdbcDatabaseContainer<MySQLContainer> {

public static final String NAME = "mysql";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("mysql");

static final String DEFAULT_USER = "test";

static final String DEFAULT_PASSWORD = "test";

private static final String MY_CNF_CONFIG_OVERRIDE_PARAM_NAME = "TC_MY_CNF";

public static final Integer MYSQL_PORT = 3306;

private String databaseName = "test";

private String username = DEFAULT_USER;

private String password = DEFAULT_PASSWORD;

private static final String MYSQL_ROOT_USER = "root";

public MySQLContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public MySQLContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

addExposedPort(MYSQL_PORT);
}

/**
* @return the ports on which to check if the container is ready
* @deprecated use {@link #getLivenessCheckPortNumbers()} instead
*/
@NotNull
@Override
@Deprecated
protected Set<Integer> getLivenessCheckPorts() {
return super.getLivenessCheckPorts();
}

@Override
protected void configure() {
optionallyMapResourceParameterAsVolume(
MY_CNF_CONFIG_OVERRIDE_PARAM_NAME,
"/etc/mysql/conf.d",
"mysql-default-conf",
Transferable.DEFAULT_DIR_MODE
);

addEnv("MYSQL_DATABASE", databaseName);
if (!MYSQL_ROOT_USER.equalsIgnoreCase(username)) {
addEnv("MYSQL_USER", username);
}
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);
}

@Override
public String getDriverClassName() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return "com.mysql.cj.jdbc.Driver";
} catch (ClassNotFoundException e) {
return "com.mysql.jdbc.Driver";
}
}

@Override
public String getJdbcUrl() {
String additionalUrlParams = constructUrlParameters("?", "&");
return "jdbc:mysql://" + getHost() + ":" + getMappedPort(MYSQL_PORT) + "/" + databaseName + additionalUrlParams;
}

@Override
protected String constructUrlForConnection(String queryString) {
String url = super.constructUrlForConnection(queryString);

if (!url.contains("useSSL=")) {
String separator = url.contains("?") ? "&" : "?";
url = url + separator + "useSSL=false";
}

if (!url.contains("allowPublicKeyRetrieval=")) {
url = url + "&allowPublicKeyRetrieval=true";
}

return url;
}

@Override
public String getDatabaseName() {
return databaseName;
}

@Override
public String getUsername() {
return username;
}

@Override
public String getPassword() {
return password;
}

@Override
public String getTestQueryString() {
return "SELECT 1";
}

public MySQLContainer withConfigurationOverride(String s) {
parameters.put(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, s);
return self();
}

@Override
public MySQLContainer withDatabaseName(final String databaseName) {
this.databaseName = databaseName;
return self();
}

@Override
public MySQLContainer withUsername(final String username) {
this.username = username;
return self();
}

@Override
public MySQLContainer withPassword(final String password) {
this.password = password;
return self();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package org.testcontainers.junit.mysql;
package org.testcontainers.mysql;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.MySQLTestImages;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.db.AbstractContainerDatabaseTest;
import org.testcontainers.utility.DockerImageName;

Expand All @@ -26,7 +25,7 @@ public static DockerImageName[] params() {
@ParameterizedTest
@MethodSource("params")
void versionCheckTest(DockerImageName dockerImageName) throws SQLException {
try (MySQLContainer<?> mysql = new MySQLContainer<>(dockerImageName)) {
try (MySQLContainer mysql = new MySQLContainer(dockerImageName)) {
mysql.start();
final ResultSet resultSet = performQuery(mysql, "SELECT VERSION()");
final String resultSetString = resultSet.getString(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package org.testcontainers.junit.mysql;
package org.testcontainers.mysql;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.MySQLTestImages;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.db.AbstractContainerDatabaseTest;

Expand All @@ -30,14 +29,14 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assumptions.assumeThat;

class SimpleMySQLTest extends AbstractContainerDatabaseTest {
class MySQLContainerTest extends AbstractContainerDatabaseTest {

private static final Logger logger = LoggerFactory.getLogger(SimpleMySQLTest.class);
private static final Logger logger = LoggerFactory.getLogger(MySQLContainerTest.class);

@Test
void testSimple() throws SQLException {
try ( // container {
MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0.36")
MySQLContainer mysql = new MySQLContainer("mysql:8.0.36")
// }
) {
mysql.start();
Expand All @@ -53,7 +52,7 @@ void testSimple() throws SQLException {
@Test
void testSpecificVersion() throws SQLException {
try (
MySQLContainer<?> mysqlOldVersion = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysqlOldVersion = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withConfigurationOverride("somepath/mysql_conf_override")
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
Expand All @@ -71,7 +70,7 @@ void testSpecificVersion() throws SQLException {
@Test
void testMySQLWithCustomIniFile() throws SQLException {
try (
MySQLContainer<?> mysqlCustomConfig = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysqlCustomConfig = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withConfigurationOverride("somepath/mysql_conf_override")
) {
mysqlCustomConfig.start();
Expand All @@ -83,7 +82,7 @@ void testMySQLWithCustomIniFile() throws SQLException {
@Test
void testCommandOverride() throws SQLException {
try (
MySQLContainer<?> mysqlCustomConfig = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysqlCustomConfig = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withCommand("mysqld --auto_increment_increment=42")
) {
mysqlCustomConfig.start();
Expand All @@ -98,7 +97,7 @@ void testCommandOverride() throws SQLException {
@Test
void testExplicitInitScript() throws SQLException {
try (
MySQLContainer<?> container = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer container = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withInitScript("somepath/init_mysql.sql")
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
Expand All @@ -114,7 +113,7 @@ void testExplicitInitScript() throws SQLException {
@Test
void testEmptyPasswordWithNonRootUser() {
try (
MySQLContainer<?> container = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer container = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withDatabaseName("TEST")
.withUsername("test")
.withPassword("")
Expand All @@ -130,7 +129,7 @@ void testEmptyPasswordWithNonRootUser() {
void testEmptyPasswordWithRootUser() throws SQLException {
// Add MYSQL_ROOT_HOST environment so that we can root login from anywhere for testing purposes
try (
MySQLContainer<?> mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withDatabaseName("foo")
.withUsername("root")
.withPassword("")
Expand All @@ -147,7 +146,7 @@ void testEmptyPasswordWithRootUser() throws SQLException {

@Test
void testWithAdditionalUrlParamTimeZone() throws SQLException {
MySQLContainer<?> mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withUrlParam("serverTimezone", "Europe/Zurich")
.withEnv("TZ", "Europe/Zurich")
.withLogConsumer(new Slf4jLogConsumer(logger));
Expand Down Expand Up @@ -182,7 +181,7 @@ void testWithAdditionalUrlParamTimeZone() throws SQLException {

@Test
void testWithAdditionalUrlParamMultiQueries() throws SQLException {
MySQLContainer<?> mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withUrlParam("allowMultiQueries", "true")
.withLogConsumer(new Slf4jLogConsumer(logger));
mysql.start();
Expand All @@ -207,7 +206,7 @@ void testWithAdditionalUrlParamMultiQueries() throws SQLException {

@Test
void testWithAdditionalUrlParamInJdbcUrl() {
MySQLContainer<?> mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withUrlParam("allowMultiQueries", "true")
.withUrlParam("rewriteBatchedStatements", "true")
.withLogConsumer(new Slf4jLogConsumer(logger));
Expand All @@ -228,7 +227,7 @@ void testWithAdditionalUrlParamInJdbcUrl() {
void testWithOnlyUserReadableCustomIniFile() throws Exception {
assumeThat(FileSystems.getDefault().supportedFileAttributeViews().contains("posix")).isTrue();
try (
MySQLContainer<?> mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE)
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withConfigurationOverride("somepath/mysql_conf_override")
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
Expand All @@ -252,12 +251,31 @@ void testWithOnlyUserReadableCustomIniFile() throws Exception {
}
}

private void assertHasCorrectExposedAndLivenessCheckPorts(MySQLContainer<?> mysql) {
@Test
void testCustom() throws SQLException {
// Add MYSQL_ROOT_HOST environment so that we can root login from anywhere for testing purposes
try (
MySQLContainer mysql = new MySQLContainer(MySQLTestImages.MYSQL_80_IMAGE)
.withDatabaseName("foo")
.withUsername("bar")
.withPassword("baz")
.withEnv("MYSQL_ROOT_HOST", "%")
) {
mysql.start();

ResultSet resultSet = performQuery(mysql, "SELECT 1");

int resultSetInt = resultSet.getInt(1);
assertThat(resultSetInt).as("A basic SELECT query succeeds").isEqualTo(1);
}
}

private void assertHasCorrectExposedAndLivenessCheckPorts(MySQLContainer mysql) {
assertThat(mysql.getExposedPorts()).containsExactly(MySQLContainer.MYSQL_PORT);
assertThat(mysql.getLivenessCheckPortNumbers()).containsExactly(mysql.getMappedPort(MySQLContainer.MYSQL_PORT));
}

private void assertThatCustomIniFileWasUsed(MySQLContainer<?> mysql) throws SQLException {
private void assertThatCustomIniFileWasUsed(MySQLContainer mysql) throws SQLException {
try (ResultSet resultSet = performQuery(mysql, "SELECT @@GLOBAL.innodb_max_undo_log_size")) {
long result = resultSet.getLong(1);
assertThat(result)
Expand Down
Loading