Skip to content

Commit

Permalink
Apply TestContainer (#264)
Browse files Browse the repository at this point in the history
Motivation:
Enhance test reliability and environment consistency by integrating
TestContainers

Modification:
Added TestContainers dependency and updated tests to run with
containerized DBs.

Expanded test scope to include MySQL and MariaDB versions to cover
conditional test cases.

Result:
Improved test suite stability and simplified setup for contributors.
Resolves #76

Co-authored-by: saurabhyadav1985 <[email protected]>
Co-authored-by: Mirro Mutth <[email protected]>
  • Loading branch information
3 people authored Apr 4, 2024
1 parent faa30a7 commit 52bc71f
Show file tree
Hide file tree
Showing 20 changed files with 493 additions and 175 deletions.
12 changes: 4 additions & 8 deletions .github/workflows/ci-graalvm-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,16 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set up MySQL
env:
MYSQL_DATABASE: r2dbc
MYSQL_ROOT_PASSWORD: r2dbc-password!@
MYSQL_VERSION: 8.1
run: docker-compose -f ${{ github.workspace }}/containers/mysql-compose.yml up -d

- uses: graalvm/setup-graalvm@v1
with:
java-version: 21
distribution: 'graalvm'
native-image-job-reports: true
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Start Bundled MySQL
run: sudo service mysql start

- name: Cache & Load Local Maven Repository
uses: actions/cache@v3
with:
Expand All @@ -50,4 +46,4 @@ jobs:
echo "JAVA_HOME=$JAVA_HOME"
echo "./mvnw -Pgraalvm package -Dmaven.javadoc.skip=true"
./mvnw -Pgraalvm package -Dmaven.javadoc.skip=true
./test-native-image/target/test-native-image -Dtest.mysql.password=r2dbc-password!@
./test-native-image/target/test-native-image
12 changes: 3 additions & 9 deletions .github/workflows/ci-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
mysql-version: [ 5.5, 5.6, 5.7, 8.0, 8.1, 8.2 ]
mysql-version: [ 5.5, 5.6.45, 5.6, 5.7.28, 5.7, 8.0, 8.1, 8.2, 8.3]
name: Integration test with MySQL ${{ matrix.mysql-version }}
steps:
- uses: actions/checkout@v3
Expand All @@ -21,19 +21,13 @@ jobs:
cache: maven
- name: Shutdown the Default MySQL
run: sudo service mysql stop
- name: Set up MySQL ${{ matrix.mysql-version }}
env:
MYSQL_DATABASE: r2dbc
MYSQL_ROOT_PASSWORD: r2dbc-password!@
MYSQL_VERSION: ${{ matrix.mysql-version }}
run: docker-compose -f ${{ github.workspace }}/containers/mysql-compose.yml up -d
- name: Integration test with MySQL ${{ matrix.mysql-version }}
run: |
set -o pipefail
./mvnw -B verify -Dmaven.javadoc.skip=true \
-Dmaven.surefire.skip=true \
-Dtest.mysql.password=r2dbc-password!@ \
-Dtest.mysql.version=${{ matrix.mysql-version }} \
-Dtest.db.type=mysql \
-Dtest.db.version=${{ matrix.mysql-version }} \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN \
-Dio.netty.leakDetectionLevel=paranoid \
-Dio.netty.leakDetection.targetRecords=32 \
Expand Down
14 changes: 3 additions & 11 deletions .github/workflows/ci-mariadb-intergration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
mariadb-version: [ 10.6, 10.11 ]
mariadb-version: [ 10.0, 10.1, 10.2.15, 10.2, 10.3.7, 10.3, 10.5.1, 10.5, 10.6, 10.11]
name: Integration test with MariaDB ${{ matrix.mariadb-version }}
steps:
- uses: actions/checkout@v3
Expand All @@ -21,21 +21,13 @@ jobs:
cache: maven
- name: Shutdown the Default MySQL
run: sudo service mysql stop
- name: Set up MariaDB ${{ matrix.mariadb-version }}
env:
MYSQL_DATABASE: r2dbc
MYSQL_ROOT_PASSWORD: r2dbc-password!@
MARIADB_VERSION: ${{ matrix.mariadb-version }}
run: docker-compose -f ${{ github.workspace }}/containers/mariadb-compose.yml up -d
- name: Integration test with MySQL ${{ matrix.mysql-version }}
- name: Integration test with MariaDB ${{ matrix.mysql-version }}
run: |
set -o pipefail
./mvnw -B verify -Dmaven.javadoc.skip=true \
-Dmaven.surefire.skip=true \
-Dtest.mysql.password=r2dbc-password!@ \
-Dtest.mysql.version=${{ matrix.mariadb-version }} \
-Dtest.db.type=mariadb \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN \
-Dtest.db.version=${{ matrix.mariadb-version }} \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN \
-Dio.netty.leakDetectionLevel=paranoid \
-Dio.netty.leakDetection.targetRecords=32 \
Expand Down
12 changes: 0 additions & 12 deletions containers/mariadb-compose.yml

This file was deleted.

12 changes: 0 additions & 12 deletions containers/mysql-compose.yml

This file was deleted.

20 changes: 19 additions & 1 deletion r2dbc-mysql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@
<logback.version>1.5.3</logback.version>
<mockito.version>4.11.0</mockito.version>
<mysql.version>8.3.0</mysql.version>
<testcontainers.version>1.19.6</testcontainers.version>
<mariadb.version>3.3.3</mariadb.version>
<testcontainers.version>1.19.7</testcontainers.version>
<hikari-cp.version>4.0.3</hikari-cp.version>
<spring-framework.version>5.3.32</spring-framework.version>
<jackson.version>2.16.1</jackson.version>
Expand Down Expand Up @@ -241,6 +242,12 @@
<version>${mysql.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>${mariadb.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
Expand Down Expand Up @@ -270,6 +277,17 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mariadb</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public R2dbcException toException(@Nullable String sql) {
case 1907: // Statement executing timeout
case 3024: // Query execution was interrupted, maximum statement execution time exceeded
case 1969: // Query execution was interrupted
case 1968: // Query execution was interrupted (max_statement_time exceeded)
return new R2dbcTimeoutException(message, sqlState, code);
case 1613: // Transaction rollback because of took too long
return new R2dbcRollbackException(message, sqlState, code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package io.asyncer.r2dbc.mysql;

import io.asyncer.r2dbc.mysql.api.MySqlConnection;
import io.asyncer.r2dbc.mysql.internal.util.TestContainerExtension;
import io.asyncer.r2dbc.mysql.internal.util.TestServerUtil;
import io.r2dbc.spi.R2dbcBadGrammarException;
import io.r2dbc.spi.R2dbcTimeoutException;
import io.r2dbc.spi.Result;
import org.junit.jupiter.api.extension.ExtendWith;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand All @@ -38,6 +41,7 @@
/**
* Base class considers connection factory and general function for integration tests.
*/
@ExtendWith(TestContainerExtension.class)
abstract class IntegrationTestSupport {

private final MySqlConnectionFactory connectionFactory;
Expand Down Expand Up @@ -82,11 +86,6 @@ static Mono<Long> extractRowsUpdated(Result result) {
static MySqlConnectionConfiguration configuration(
Function<MySqlConnectionConfiguration.Builder, MySqlConnectionConfiguration.Builder> customizer
) {
String password = System.getProperty("test.mysql.password");

assertThat(password).withFailMessage("Property test.mysql.password must exists and not be empty")
.isNotNull()
.isNotEmpty();

String localInfilePath;

Expand All @@ -99,73 +98,47 @@ static MySqlConnectionConfiguration configuration(
}

MySqlConnectionConfiguration.Builder builder = MySqlConnectionConfiguration.builder()
.host("127.0.0.1")
.host(TestServerUtil.getHost())
.port(TestServerUtil.getPort())
.user(TestServerUtil.getUsername())
.password(TestServerUtil.getPassword())
.database(TestServerUtil.getDatabase())
.connectTimeout(Duration.ofSeconds(3))
.user("root")
.password(password)
.database("r2dbc")
.allowLoadLocalInfileInPath(localInfilePath);

return customizer.apply(builder).build();
}

boolean envIsLessThanMySql56() {
String version = System.getProperty("test.mysql.version");

if (version == null || version.isEmpty()) {
return true;
}

ServerVersion ver = ServerVersion.parse(version);
String type = System.getProperty("test.db.type");

if ("mariadb".equalsIgnoreCase(type)) {
if (TestServerUtil.isMariaDb()) {
return false;
}

final ServerVersion ver = TestServerUtil.getServerVersion();
return ver.isLessThan(ServerVersion.create(5, 6, 0));
}

boolean envIsLessThanMySql57OrMariaDb102() {
String version = System.getProperty("test.mysql.version");

if (version == null || version.isEmpty()) {
return true;
}

ServerVersion ver = ServerVersion.parse(version);
String type = System.getProperty("test.db.type");

if ("mariadb".equalsIgnoreCase(type)) {
boolean envIsLessThanMySql578OrMariaDb102() {
final ServerVersion ver = TestServerUtil.getServerVersion();
if (TestServerUtil.isMariaDb()) {
return ver.isLessThan(ServerVersion.create(10, 2, 0));
}

return ver.isLessThan(ServerVersion.create(5, 7, 0));
return ver.isLessThan(ServerVersion.create(5, 7, 8));
}

static boolean envIsMariaDb10_5_1() {
String type = System.getProperty("test.db.type");

if (!"mariadb".equalsIgnoreCase(type)) {
if (!TestServerUtil.isMariaDb()) {
return false;
}

ServerVersion ver = ServerVersion.parse(System.getProperty("test.mysql.version"));
final ServerVersion ver = TestServerUtil.getServerVersion();

return ver.isGreaterThanOrEqualTo(ServerVersion.create(10, 5, 1));
}

boolean envIsLessThanMySql574OrMariaDb1011() {
String version = System.getProperty("test.mysql.version");

if (version == null || version.isEmpty()) {
return true;
}

ServerVersion ver = ServerVersion.parse(version);
String type = System.getProperty("test.db.type");

if ("mariadb".equalsIgnoreCase(type)) {
final ServerVersion ver = TestServerUtil.getServerVersion();
if (TestServerUtil.isMariaDb()) {
return ver.isLessThan(ServerVersion.create(10, 1, 1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void tearDown() {
JacksonCodecRegistrar.tearDown();
}

@DisabledIf("envIsLessThanMySql57OrMariaDb102")
@DisabledIf("envIsLessThanMySql578OrMariaDb102")
@Test
void json() {
create().flatMap(connection -> Mono.from(connection.createStatement(TDL).execute())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
package io.asyncer.r2dbc.mysql;

import com.zaxxer.hikari.HikariDataSource;
import io.asyncer.r2dbc.mysql.internal.util.TestContainerExtension;
import io.r2dbc.spi.test.TestKit;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.jdbc.core.JdbcTemplate;

import java.time.Duration;
Expand All @@ -26,6 +28,7 @@
/**
* Base class considers integration tests of {@link TestKit}.
*/
@ExtendWith(TestContainerExtension.class)
abstract class MySqlTestKitSupport implements TestKit<String> {

private final MySqlConnectionFactory connectionFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void set() {
EnumSet.of(EnumData.ONE, EnumData.THREE));
}

@DisabledIf("envIsLessThanMySql57OrMariaDb102")
@DisabledIf("envIsLessThanMySql578OrMariaDb102")
@Test
void json() {
testType(String.class, false, "JSON", null, "{\"data\": 1}", "[\"data\", 1]", "1", "null",
Expand Down Expand Up @@ -576,7 +576,7 @@ void insertOnDuplicate() {
/**
* ref: <a href="https://github.com/asyncer-io/r2dbc-mysql/issues/91">Issue 91</a>
*/
@DisabledIf("envIsLessThanMySql57OrMariaDb102")
@DisabledIf("envIsLessThanMySql578OrMariaDb102")
@Test
void testUnionQueryWithJsonColumnDecodedAsString() {
complete(connection ->
Expand Down Expand Up @@ -619,11 +619,18 @@ void testUnionQueryWithJsonColumnDecodedAsString() {
@Test
@DisabledIf("envIsLessThanMySql574OrMariaDb1011")
void setStatementTimeoutTest() {
final String sql = "SELECT 1 WHERE SLEEP(1) > 1";
final String sql = "SELECT COUNT(*) " +
"FROM information_schema.tables a cross join " +
"information_schema.tables b cross join " +
"information_schema.tables c cross join " +
"information_schema.tables d cross join " +
"information_schema.tables e";

timeout(connection -> connection.setStatementTimeout(Duration.ofMillis(500))
.then(Mono.from(connection.createStatement(sql).execute()))
.flatMapMany(result -> Mono.from(result.map((row, metadata) -> row.get(0, String.class))))
.collectList()
.doOnNext(System.out::println)
);
}

Expand Down
Loading

0 comments on commit 52bc71f

Please sign in to comment.