diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 6ecdbb6..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,66 +0,0 @@ -version: 2.1 -jobs: - build: - docker: - - image: eclipse-temurin:17.0.10_7-jdk-jammy - - image: circleci/mysql:5.7 - environment: - - MYSQL_USER=test - - MYSQL_PASSWORD=test - - MYSQL_DATABASE=testdb - - image: circleci/postgres:12.5 - environment: - - POSTGRES_USER=test - - POSTGRES_PASSWORD=test - - POSTGRES_DB=testdb - - working_directory: ~/repo - - environment: - # Customize the JVM maximum heap limit - JVM_OPTS: -Xmx3200m - TERM: dumb - - steps: - - checkout - - - run: ./gradlew test --console=plain -i - - # Jacoco and codecov - - run: ./gradlew jacocoTestReport - - run: bash <(curl -s https://codecov.io/bash) - - build-latest: - docker: - - image: eclipse-temurin:17.0.10_7-jdk-jammy - - image: circleci/mysql:8.0 - environment: - - MYSQL_USER=test - - MYSQL_PASSWORD=test - - MYSQL_DATABASE=testdb - #In MySql 8 local-infile is not active by default - command: mysqld --local-infile=1 - - image: circleci/postgres:13.1 - environment: - - POSTGRES_USER=test - - POSTGRES_PASSWORD=test - - POSTGRES_DB=testdb - - working_directory: ~/repo - - environment: - # Customize the JVM maximum heap limit - JVM_OPTS: -Xmx3200m - TERM: dumb - - steps: - - checkout - - - run: ./gradlew test -Pmysql8 --console=plain -i - -workflows: - version: 2.0 - build-multiple: - jobs: - - build - - build-latest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..80fd8e4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +name: JFleet CI/CD + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + env: + # Customize the JVM maximum heap limit + JVM_OPTS: -Xmx3200m + TERM: dumb + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + - name: Build with Gradle + run: ./gradlew test --console=plain -i + # Jacoco and codecov + - name: Jacoco + run: ./gradlew jacocoTestReport + - name: codecov + run: bash <(curl -s https://codecov.io/bash) + + build-latest: + runs-on: ubuntu-latest + env: + # Customize the JVM maximum heap limit + JVM_OPTS: -Xmx3200m + TERM: dumb + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + - name: Build with Gradle + run: ./gradlew test -Pmysql8 --console=plain -i + # Jacoco and codecov + - name: Jacoco + run: ./gradlew jacocoTestReport + - name: codecov + run: bash <(curl -s https://codecov.io/bash) diff --git a/.gitignore b/.gitignore index 99bd243..a77fb30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .gradle bin +build +.idea \ No newline at end of file diff --git a/README.md b/README.md index d28ba2b..e62f057 100644 --- a/README.md +++ b/README.md @@ -213,17 +213,13 @@ Any database engine with a standard JDBC driver should be used with the `JdbcBul ## Running the tests -Tests need a MySQL and a PostgreSQL instances running in localhost. A database called `testdb` must exist and an user `test` with password `test` must have `CREATE TABLE` and `DROP TABLE` permissions. +The tests utilize [TestContainers](https://testcontainers.com/) to create lightweight, temporary instances of common databases. +TestContainers automatically handles downloading the required database images and managing their lifecycle. -You can modify this settings changing locally [mysql-test.properties](https://github.com/jerolba/jfleet/blob/master/jfleet-core/src/test/resources/mysql-test.properties) and [postgres-test.properties](https://github.com/jerolba/jfleet/blob/master/jfleet-core/src/test/resources/postgres-test.properties) files. +During test execution, two databases—MySQL and PostgreSQL—are instantiated and will automatically shut down once the tests complete. +For details on how these containers are configured, refer to the `DatabaseContainers` class in the `jfleet-core` module. -If you have docker installed, you can launch them using the following commands: - -```bash -docker run --name mysql-jfleet -e MYSQL_ROOT_PASSWORD=jfleet -e MYSQL_USER=test -e MYSQL_PASSWORD=test -e MYSQL_DATABASE=testdb -p 3306:3306 -d mysql:5.7 - -docker run --name postgres-jfleet -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test -e POSTGRES_DB=testdb -p 5432:5432 -d postgres:12.5 -``` +To run the tests locally, ensure that Docker or a compatible Docker-API runtime is installed. For more information on configuring TestContainers, please consult the [System Requirements guide](https://java.testcontainers.org/supported_docker_environment/). To execute all test you must execute the command: diff --git a/gradle.properties b/gradle.properties index ec2fab2..f426aa9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,5 @@ version = 0.6.7 parquetVersion = 1.13.1 hadoopVersion = 3.3.5 -junitVersion = 5.10.2 \ No newline at end of file +junitVersion = 5.10.2 +testContainersVersion = 1.20.2 \ No newline at end of file diff --git a/jfleet-core/build.gradle b/jfleet-core/build.gradle index 2f09b3e..55c1287 100644 --- a/jfleet-core/build.gradle +++ b/jfleet-core/build.gradle @@ -37,6 +37,11 @@ dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junitVersion testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: junitVersion testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junitVersion + testImplementation group: 'org.testcontainers', name: 'testcontainers', version: testContainersVersion + testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: testContainersVersion + testImplementation group: 'org.testcontainers', name: 'mysql', version: testContainersVersion + testImplementation group: 'org.testcontainers', name: 'postgresql', version: testContainersVersion + } test { diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedIdInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedIdInspectorTest.java index 41ca9a9..b2ff299 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedIdInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedIdInspectorTest.java @@ -24,8 +24,8 @@ import javax.persistence.EmbeddedId; import javax.persistence.Entity; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.junit.jupiter.api.Test; public class EmbeddedIdInspectorTest { diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedInspectorTest.java index c10cc1f..ae4676a 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/EmbeddedInspectorTest.java @@ -17,8 +17,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.jfleet.entities.Company; import org.jfleet.entities.Person; import org.junit.jupiter.api.Test; diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/EntityInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/EntityInspectorTest.java index d2b3601..054887e 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/EntityInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/EntityInspectorTest.java @@ -17,8 +17,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/FailedManyToOneEntityInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/FailedManyToOneEntityInspectorTest.java index 7bb8115..e959c98 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/FailedManyToOneEntityInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/FailedManyToOneEntityInspectorTest.java @@ -26,8 +26,8 @@ import javax.persistence.JoinTable; import javax.persistence.ManyToOne; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.junit.jupiter.api.Test; public class FailedManyToOneEntityInspectorTest { diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/FieldTypeInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/FieldTypeInspectorTest.java index c9dc2ab..248f40e 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/FieldTypeInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/FieldTypeInspectorTest.java @@ -32,8 +32,8 @@ import javax.persistence.TemporalType; import org.jfleet.EntityFieldType; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.junit.jupiter.api.Test; public class FieldTypeInspectorTest { diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/ManyToOneEntityInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/ManyToOneEntityInspectorTest.java index cb6fd1d..b1c1d72 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/ManyToOneEntityInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/ManyToOneEntityInspectorTest.java @@ -22,8 +22,8 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.junit.jupiter.api.Test; public class ManyToOneEntityInspectorTest { diff --git a/jfleet-core/src/test/java/org/jfleet/inspection/OneToOneEntityInspectorTest.java b/jfleet-core/src/test/java/org/jfleet/inspection/OneToOneEntityInspectorTest.java index 8276c1e..53f3ee2 100644 --- a/jfleet-core/src/test/java/org/jfleet/inspection/OneToOneEntityInspectorTest.java +++ b/jfleet-core/src/test/java/org/jfleet/inspection/OneToOneEntityInspectorTest.java @@ -22,8 +22,8 @@ import javax.persistence.JoinColumn; import javax.persistence.OneToOne; -import org.jfleet.FieldInfo; import org.jfleet.EntityFieldType.FieldTypeEnum; +import org.jfleet.FieldInfo; import org.junit.jupiter.api.Test; public class OneToOneEntityInspectorTest { diff --git a/jfleet-core/src/test/java/org/jfleet/mysql/MySqlReservedWordTest.java b/jfleet-core/src/test/java/org/jfleet/mysql/MySqlReservedWordTest.java index a328758..9a69fdc 100644 --- a/jfleet-core/src/test/java/org/jfleet/mysql/MySqlReservedWordTest.java +++ b/jfleet-core/src/test/java/org/jfleet/mysql/MySqlReservedWordTest.java @@ -15,6 +15,7 @@ */ package org.jfleet.mysql; +import static org.jfleet.parameterized.Databases.MySql; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -29,12 +30,15 @@ import javax.persistence.Table; import org.jfleet.BulkInsert; -import org.jfleet.util.MySqlDatabase; +import org.jfleet.parameterized.DatabaseProvider; +import org.jfleet.util.Database; import org.jfleet.util.SqlUtil; import org.junit.jupiter.api.Test; public class MySqlReservedWordTest { + private final Database database = DatabaseProvider.getDatabase(MySql); + @Entity @Table(name = "\"select\"") public class ReservedWordEntity { @@ -65,7 +69,7 @@ public void canPersistWithReservedWords() throws Exception { Stream stream = IntStream.range(0, times) .mapToObj(i -> new ReservedWordEntity(i, "current_user_" + i)); - try (Connection conn = new MySqlDatabase().getConnection()) { + try (Connection conn = database.getConnection()) { SqlUtil.createTableForEntity(conn, ReservedWordEntity.class); insert.insertAll(conn, stream); diff --git a/jfleet-core/src/test/java/org/jfleet/mysql/MySqlTransactionPolicyTest.java b/jfleet-core/src/test/java/org/jfleet/mysql/MySqlTransactionPolicyTest.java index 19e213b..092a9ba 100644 --- a/jfleet-core/src/test/java/org/jfleet/mysql/MySqlTransactionPolicyTest.java +++ b/jfleet-core/src/test/java/org/jfleet/mysql/MySqlTransactionPolicyTest.java @@ -16,6 +16,7 @@ package org.jfleet.mysql; import static org.jfleet.mysql.LoadDataConfiguration.LoadDataConfigurationBuilder.from; +import static org.jfleet.parameterized.Databases.MySql; import static org.jfleet.util.TransactionPolicyTestHelper.employeesWithForeignKeyError; import static org.jfleet.util.TransactionPolicyTestHelper.employeesWithMultipleConstraintsErrors; import static org.jfleet.util.TransactionPolicyTestHelper.employeesWithOutErrors; @@ -32,8 +33,8 @@ import org.jfleet.BulkInsert; import org.jfleet.JFleetException; import org.jfleet.entities.Employee; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.util.Database; -import org.jfleet.util.MySqlDatabase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -44,10 +45,10 @@ public class MySqlTransactionPolicyTest { private static Logger logger = LoggerFactory.getLogger(MySqlTransactionPolicyTest.class); private static final int VERY_LOW_SIZE_TO_FREQUENT_LOAD_DATA = 10; - private Database database = new MySqlDatabase(); + private final Database database = DatabaseProvider.getDatabase(MySql); @BeforeEach - public void setup() throws IOException, SQLException { + public void setup() throws SQLException, IOException { try (Connection connection = database.getConnection()) { setupDatabase(connection); } @@ -55,6 +56,7 @@ public void setup() throws IOException, SQLException { @Test public void longTransactionExecuteMultipleLoadDataOperationsTransactionaly() throws Exception { + try (Connection connection = database.getConnection()) { connection.setAutoCommit(false); diff --git a/jfleet-core/src/test/java/org/jfleet/mysql/error/LockRetryTest.java b/jfleet-core/src/test/java/org/jfleet/mysql/error/LockRetryTest.java index 9497631..f98b3e5 100644 --- a/jfleet-core/src/test/java/org/jfleet/mysql/error/LockRetryTest.java +++ b/jfleet-core/src/test/java/org/jfleet/mysql/error/LockRetryTest.java @@ -16,6 +16,7 @@ package org.jfleet.mysql.error; import static org.jfleet.mysql.LoadDataConfiguration.LoadDataConfigurationBuilder.from; +import static org.jfleet.parameterized.Databases.MySql; import static org.jfleet.util.TransactionPolicyTestHelper.numberOfRowsInEmployeeTable; import static org.jfleet.util.TransactionPolicyTestHelper.setupDatabase; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,8 +34,8 @@ import org.jfleet.entities.Employee; import org.jfleet.mysql.LoadDataBulkInsert; import org.jfleet.mysql.LoadDataConfiguration; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.util.Database; -import org.jfleet.util.MySqlDatabase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -44,13 +45,13 @@ public class LockRetryTest { private static Logger logger = LoggerFactory.getLogger(LockRetryTest.class); - private Database database = new MySqlDatabase(); + private final Database database = DatabaseProvider.getDatabase(MySql); private static City city1 = new City(1, "Madrid"); private static City city2 = new City(2, "Barcelona"); @BeforeEach - public void setup() throws IOException, SQLException { + public void setup() throws SQLException, IOException { try (Connection connection = database.getConnection()) { setupDatabase(connection); } diff --git a/jfleet-core/src/test/java/org/jfleet/mysql/manual/ConnectionTest.java b/jfleet-core/src/test/java/org/jfleet/mysql/manual/ConnectionTest.java index 6a36578..5c19b66 100644 --- a/jfleet-core/src/test/java/org/jfleet/mysql/manual/ConnectionTest.java +++ b/jfleet-core/src/test/java/org/jfleet/mysql/manual/ConnectionTest.java @@ -15,6 +15,7 @@ */ package org.jfleet.mysql.manual; +import static org.jfleet.parameterized.Databases.MySql; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -25,8 +26,9 @@ import java.sql.ResultSet; import java.sql.SQLException; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.parameterized.IsMySql5Present; -import org.jfleet.util.MySqlDatabase; +import org.jfleet.util.Database; import org.junit.jupiter.api.Test; import com.mysql.jdbc.Connection; @@ -34,9 +36,11 @@ public class ConnectionTest { + private final Database database = DatabaseProvider.getDatabase(MySql); + @Test public void canConnectToTestDB() throws SQLException, IOException { - try (java.sql.Connection conn = new MySqlDatabase().getConnection()) { + try (java.sql.Connection conn = database.getConnection()) { assertNotNull(conn); } } @@ -47,7 +51,7 @@ public void canExecuteLoadData() throws SQLException, IOException { int someValue = 12345; String otherValue = "foobar"; - try (Connection conn = (Connection) new MySqlDatabase().getConnection()) { + try (Connection conn = (Connection) database.getConnection()) { conn.setAllowLoadLocalInfile(true); try (Statement stmt = (Statement) conn.createStatement()) { stmt.execute("CREATE TEMPORARY TABLE simple_table (some_column INTEGER, other_column VARCHAR(255))"); @@ -75,7 +79,7 @@ public void canExecuteLoadDataWithNullValues() throws SQLException, IOException int someValue = 12345; String otherValue = "foobar"; - try (Connection conn = (Connection) new MySqlDatabase().getConnection()) { + try (Connection conn = (Connection) database.getConnection()) { conn.setAllowLoadLocalInfile(true); try (Statement stmt = (Statement) conn.createStatement()) { stmt.execute("CREATE TEMPORARY TABLE simple_table (some_column INTEGER, other_column VARCHAR(255))"); diff --git a/jfleet-core/src/test/java/org/jfleet/mysql/manual/IdsTest.java b/jfleet-core/src/test/java/org/jfleet/mysql/manual/IdsTest.java index 79c4e63..2702025 100644 --- a/jfleet-core/src/test/java/org/jfleet/mysql/manual/IdsTest.java +++ b/jfleet-core/src/test/java/org/jfleet/mysql/manual/IdsTest.java @@ -15,6 +15,7 @@ */ package org.jfleet.mysql.manual; +import static org.jfleet.parameterized.Databases.MySql; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -24,8 +25,9 @@ import java.sql.ResultSet; import java.sql.SQLException; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.parameterized.IsMySql5Present; -import org.jfleet.util.MySqlDatabase; +import org.jfleet.util.Database; import org.junit.jupiter.api.Test; import com.mysql.jdbc.Connection; @@ -34,9 +36,11 @@ @IsMySql5Present public class IdsTest { + private final Database database = DatabaseProvider.getDatabase(MySql); + @Test public void canExecuteLoadDataWithAutoIncrement() throws SQLException, IOException { - try (Connection conn = (Connection) new MySqlDatabase().getConnection()) { + try (Connection conn = (Connection) database.getConnection()) { conn.setAllowLoadLocalInfile(true); try (Statement stmt = (Statement) conn.createStatement()) { stmt.execute("CREATE TEMPORARY TABLE table_with_id " @@ -66,7 +70,7 @@ public void canExecuteLoadDataWithAutoIncrement() throws SQLException, IOExcepti @Test public void canExecuteLoadDataWithAutoIncrementIdSetted() throws SQLException, IOException { - try (Connection conn = (Connection) new MySqlDatabase().getConnection()) { + try (Connection conn = (Connection) database.getConnection()) { conn.setAllowLoadLocalInfile(true); try (Statement stmt = (Statement) conn.createStatement()) { stmt.execute("CREATE TEMPORARY TABLE table_with_id " diff --git a/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseArgumentProvider.java b/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseArgumentProvider.java index dae2ac0..6dddbda 100644 --- a/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseArgumentProvider.java +++ b/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseArgumentProvider.java @@ -18,11 +18,6 @@ import java.lang.reflect.Method; import java.util.stream.Stream; -import org.jfleet.util.Database; -import org.jfleet.util.JdbcMysqlDatabase; -import org.jfleet.util.JdbcPostgresDatabase; -import org.jfleet.util.MySqlDatabase; -import org.jfleet.util.PostgresDatabase; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; @@ -30,7 +25,7 @@ public class DatabaseArgumentProvider implements ArgumentsProvider { @Override - public Stream provideArguments(ExtensionContext context) throws Exception { + public Stream provideArguments(ExtensionContext context) { Method testMethod = context.getTestMethod().get(); DBs dbs = testMethod.getAnnotation(DBs.class); if (dbs != null) { @@ -43,30 +38,7 @@ public Stream provideArguments(ExtensionContext context) th } private Stream getDatabases(Databases[] dbs) { - return Stream.of(dbs).map(this::createDatabase).map(Arguments::of); - } - - private Database createDatabase(Databases enumValue) { - switch (enumValue) { - case JdbcMySql: - return new JdbcMysqlDatabase(); - case JdbcPosgres: - return new JdbcPostgresDatabase(); - case MySql: - return new MySqlDatabase(); - case Postgres: - return new PostgresDatabase(); - } - return null; - } - - public static boolean isMySql5Present() { - try { - Class.forName("com.mysql.jdbc.PreparedStatement"); - } catch (ClassNotFoundException e) { - return false; - } - return true; + return Stream.of(dbs).map(DatabaseProvider::getDatabase).map(Arguments::of); } } diff --git a/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseProvider.java b/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseProvider.java new file mode 100644 index 0000000..2bcc84b --- /dev/null +++ b/jfleet-core/src/test/java/org/jfleet/parameterized/DatabaseProvider.java @@ -0,0 +1,28 @@ +package org.jfleet.parameterized; + +import org.jfleet.util.Database; +import org.jfleet.util.DatabaseContainers; +import org.jfleet.util.JdbcMysqlDatabase; +import org.jfleet.util.JdbcPostgresDatabase; +import org.jfleet.util.MySqlDatabase; +import org.jfleet.util.PostgresDatabase; +import org.testcontainers.containers.JdbcDatabaseContainer; + +public class DatabaseProvider { + + public static Database getDatabase(Databases enumValue) { + JdbcDatabaseContainer container = DatabaseContainers.getContainer(enumValue); + switch (enumValue) { + case JdbcMySql: + return new JdbcMysqlDatabase(container); + case JdbcPosgres: + return new JdbcPostgresDatabase(container); + case MySql: + return new MySqlDatabase(container); + case Postgres: + return new PostgresDatabase(container); + } + + return null; + } +} diff --git a/jfleet-core/src/test/java/org/jfleet/parameterized/IsMySql5Condition.java b/jfleet-core/src/test/java/org/jfleet/parameterized/IsMySql5Condition.java index 6e806a0..91a2342 100644 --- a/jfleet-core/src/test/java/org/jfleet/parameterized/IsMySql5Condition.java +++ b/jfleet-core/src/test/java/org/jfleet/parameterized/IsMySql5Condition.java @@ -15,7 +15,6 @@ */ package org.jfleet.parameterized; -import static org.jfleet.parameterized.DatabaseArgumentProvider.isMySql5Present; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; @@ -33,4 +32,13 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con return disabled("MySql 5.x driver is not present"); } + public static boolean isMySql5Present() { + try { + Class.forName("com.mysql.jdbc.PreparedStatement"); + } catch (ClassNotFoundException e) { + return false; + } + return true; + } + } diff --git a/jfleet-core/src/test/java/org/jfleet/postgres/PostgresDateTypePersistenceWithMillisecondsResolutionTest.java b/jfleet-core/src/test/java/org/jfleet/postgres/PostgresDateTypePersistenceWithMillisecondsResolutionTest.java index deea163..2296082 100644 --- a/jfleet-core/src/test/java/org/jfleet/postgres/PostgresDateTypePersistenceWithMillisecondsResolutionTest.java +++ b/jfleet-core/src/test/java/org/jfleet/postgres/PostgresDateTypePersistenceWithMillisecondsResolutionTest.java @@ -37,7 +37,6 @@ import org.jfleet.parameterized.TestDBs; import org.jfleet.shared.entities.EntityWithDateTypes; import org.jfleet.util.Database; -import org.jfleet.util.PostgresDatabase; import org.jfleet.util.SqlUtil; public class PostgresDateTypePersistenceWithMillisecondsResolutionTest { @@ -53,10 +52,9 @@ public void persistWithMillisecondResolution(Database database) throws Exception entity.setSqlTimeStamp(new Timestamp(getDate("24/01/2012 23:12:48.132").getTime())); entity.setLocalTime(LocalTime.of(23, 12, 48, 132_000_000)); entity.setLocalDateTime(LocalDateTime.of(2012, 01, 24, 23, 12, 48, 132_000_000)); - BulkInsert insert = database.getBulkInsert(EntityWithDateTypes.class); - try (Connection conn = new PostgresDatabase().getConnection()) { + try (Connection conn = database.getConnection()) { SqlUtil.createTableForEntity(conn, EntityWithDateTypes.class); insert.insertAll(conn, Stream.of(entity)); diff --git a/jfleet-core/src/test/java/org/jfleet/postgres/PostgresTransactionPolicyTest.java b/jfleet-core/src/test/java/org/jfleet/postgres/PostgresTransactionPolicyTest.java index c05aa12..68c4f53 100644 --- a/jfleet-core/src/test/java/org/jfleet/postgres/PostgresTransactionPolicyTest.java +++ b/jfleet-core/src/test/java/org/jfleet/postgres/PostgresTransactionPolicyTest.java @@ -15,6 +15,7 @@ */ package org.jfleet.postgres; +import static org.jfleet.parameterized.Databases.Postgres; import static org.jfleet.postgres.PgCopyConfiguration.PgCopyConfigurationBuilder.from; import static org.jfleet.util.TransactionPolicyTestHelper.employeesWithConstraintError; import static org.jfleet.util.TransactionPolicyTestHelper.employeesWithOutErrors; @@ -29,8 +30,8 @@ import org.jfleet.BulkInsert; import org.jfleet.entities.Employee; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.util.Database; -import org.jfleet.util.PostgresDatabase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -38,13 +39,13 @@ public class PostgresTransactionPolicyTest { - private static Logger logger = LoggerFactory.getLogger(PostgresTransactionPolicyTest.class); + private static final Logger logger = LoggerFactory.getLogger(PostgresTransactionPolicyTest.class); private static final int VERY_LOW_SIZE_TO_FREQUENT_LOAD_DATA = 10; - private Database database = new PostgresDatabase(); + private final Database database = DatabaseProvider.getDatabase(Postgres); @BeforeEach - public void setup() throws IOException, SQLException { + public void setup() throws SQLException, IOException { try (Connection connection = database.getConnection()) { setupDatabase(connection); } diff --git a/jfleet-core/src/test/java/org/jfleet/postgres/manual/ConnectionTest.java b/jfleet-core/src/test/java/org/jfleet/postgres/manual/ConnectionTest.java index c133dc0..26e9fe7 100644 --- a/jfleet-core/src/test/java/org/jfleet/postgres/manual/ConnectionTest.java +++ b/jfleet-core/src/test/java/org/jfleet/postgres/manual/ConnectionTest.java @@ -15,6 +15,7 @@ */ package org.jfleet.postgres.manual; +import static org.jfleet.parameterized.Databases.Postgres; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -28,8 +29,8 @@ import java.sql.Statement; import org.jfleet.common.StringBuilderReader; +import org.jfleet.parameterized.DatabaseProvider; import org.jfleet.util.Database; -import org.jfleet.util.PostgresDatabase; import org.junit.jupiter.api.Test; import org.postgresql.copy.CopyManager; import org.postgresql.jdbc.PgConnection; @@ -37,7 +38,7 @@ public class ConnectionTest { - private Database database = new PostgresDatabase(); + private final Database database = DatabaseProvider.getDatabase(Postgres); @Test public void canConnectToTestDB() throws SQLException, IOException { diff --git a/jfleet-core/src/test/java/org/jfleet/shared/SpecialCharsPersistenceTest.java b/jfleet-core/src/test/java/org/jfleet/shared/SpecialCharsPersistenceTest.java index b1230b2..03bde17 100644 --- a/jfleet-core/src/test/java/org/jfleet/shared/SpecialCharsPersistenceTest.java +++ b/jfleet-core/src/test/java/org/jfleet/shared/SpecialCharsPersistenceTest.java @@ -35,7 +35,7 @@ public class SpecialCharsPersistenceTest { @Entity @Table(name = "table_with_strings") - class EnityWithStrings { + class EntityWithStrings { private String foo; private String bar; @@ -59,14 +59,14 @@ public void setBar(String bar) { } public void testWithString(Database database, String text) throws Exception { - EnityWithStrings entity = new EnityWithStrings(); + EntityWithStrings entity = new EntityWithStrings(); entity.setFoo("Some text"); entity.setBar(text); - BulkInsert insert = database.getBulkInsert(EnityWithStrings.class); + BulkInsert insert = database.getBulkInsert(EntityWithStrings.class); try (Connection conn = database.getConnection()) { - SqlUtil.createTableForEntity(conn, EnityWithStrings.class); + SqlUtil.createTableForEntity(conn, EntityWithStrings.class); insert.insertAll(conn, Stream.of(entity)); try (Statement stmt = conn.createStatement()) { diff --git a/jfleet-core/src/test/java/org/jfleet/shared/TypePersistenceTest.java b/jfleet-core/src/test/java/org/jfleet/shared/TypePersistenceTest.java index c405427..c2e318f 100644 --- a/jfleet-core/src/test/java/org/jfleet/shared/TypePersistenceTest.java +++ b/jfleet-core/src/test/java/org/jfleet/shared/TypePersistenceTest.java @@ -26,6 +26,8 @@ import java.util.stream.Stream; import org.jfleet.BulkInsert; +import org.jfleet.parameterized.DBs; +import org.jfleet.parameterized.Databases; import org.jfleet.parameterized.TestDBs; import org.jfleet.shared.entities.EntityWithBasicTypes; import org.jfleet.shared.entities.EnumForTest; diff --git a/jfleet-core/src/test/java/org/jfleet/util/Database.java b/jfleet-core/src/test/java/org/jfleet/util/Database.java index 931b7c7..8ded8b2 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/Database.java +++ b/jfleet-core/src/test/java/org/jfleet/util/Database.java @@ -19,23 +19,20 @@ import java.sql.Connection; import org.jfleet.BulkInsert; +import org.testcontainers.containers.JdbcDatabaseContainer; public abstract class Database { - private String properties; + private final JdbcDatabaseContainer container; - public Database(String properties) { - this.properties = properties; - } - - public String getProperties() { - return properties; + public Database(JdbcDatabaseContainer container) { + this.container = container; } public abstract BulkInsert getBulkInsert(Class clazz); public Connection getConnection() throws IOException { - return new DatabaseTestConnectionProvider(getProperties()).get(); + return new DatabaseTestConnectionProvider(container).get(); } @Override diff --git a/jfleet-core/src/test/java/org/jfleet/util/DatabaseContainers.java b/jfleet-core/src/test/java/org/jfleet/util/DatabaseContainers.java new file mode 100644 index 0000000..dd19ac7 --- /dev/null +++ b/jfleet-core/src/test/java/org/jfleet/util/DatabaseContainers.java @@ -0,0 +1,67 @@ +package org.jfleet.util; + +import static org.jfleet.parameterized.Databases.JdbcMySql; +import static org.jfleet.parameterized.Databases.JdbcPosgres; +import static org.jfleet.parameterized.Databases.MySql; +import static org.jfleet.parameterized.Databases.Postgres; +import static org.jfleet.parameterized.IsMySql5Condition.isMySql5Present; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jfleet.parameterized.Databases; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.JdbcDatabaseContainer; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.containers.PostgreSQLContainer; + +public class DatabaseContainers { + + private static final String MYSQL_5_VERSION = "mysql:5.7.34"; + private static final String MYSQL_8_VERSION = "mysql:8.0.39"; + private static final String POSTGRES_12_VERSION = "postgres:12-alpine"; + + private static final Map> map = new HashMap<>(); + static { + PostgreSQLContainer postgresContainer = createPostgresContainer(); + MySQLContainer mysqlContainer = createMySqlContainer(); + map.put(Postgres, postgresContainer); + map.put(JdbcPosgres, postgresContainer); + map.put(MySql, mysqlContainer); + map.put(JdbcMySql, mysqlContainer); + + List.of(postgresContainer, mysqlContainer).parallelStream().forEach(GenericContainer::start); + } + + public static JdbcDatabaseContainer getContainer(Databases database) { + return map.get(database); + } + + private static PostgreSQLContainer createPostgresContainer() { + return new PostgreSQLContainer<>(POSTGRES_12_VERSION) + .withUsername("test") + .withPassword("test") + .withPassword("test") + .withDatabaseName("postgresdb") + .withUrlParam("reWriteBatchedInserts", "true"); + } + + private static MySQLContainer createMySqlContainer() { + return new MySQLContainer<>(getMysqlVersion()) + .withConfigurationOverride("my-sql-config") + .withUsername("test") + .withPassword("test") + .withDatabaseName("testdb") + .withUrlParam("useSSL", "false") + .withUrlParam("allowPublicKeyRetrieval", "true") + .withUrlParam("useUnicode", "true") + .withUrlParam("characterEncoding", "utf-8") + .withUrlParam("allowLoadLocalInfile", "true"); + } + + private static String getMysqlVersion() { + return isMySql5Present() ? MYSQL_5_VERSION: MYSQL_8_VERSION; + } + +} diff --git a/jfleet-core/src/test/java/org/jfleet/util/DatabaseTestConnectionProvider.java b/jfleet-core/src/test/java/org/jfleet/util/DatabaseTestConnectionProvider.java index 62e2ea1..f218031 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/DatabaseTestConnectionProvider.java +++ b/jfleet-core/src/test/java/org/jfleet/util/DatabaseTestConnectionProvider.java @@ -15,32 +15,28 @@ */ package org.jfleet.util; -import java.io.IOException; -import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; -import java.util.Properties; import java.util.function.Supplier; +import org.testcontainers.containers.JdbcDatabaseContainer; + public class DatabaseTestConnectionProvider implements Supplier { - private Properties prop; + private final JdbcDatabaseContainer container; - public DatabaseTestConnectionProvider(String propertiesName) throws IOException { - InputStream is = this.getClass().getClassLoader().getResourceAsStream(propertiesName); - Properties p = new Properties(); - p.load(is); - prop = p; + public DatabaseTestConnectionProvider(JdbcDatabaseContainer container) { + this.container = container; } @Override public Connection get() { - String driver = prop.getProperty("driver"); + String driver = container.getDriverClassName(); try { Class.forName(driver).newInstance(); - Connection conn = DriverManager.getConnection(prop.getProperty("urlConnection"), prop.getProperty("user"), - prop.getProperty("password")); + Connection conn = DriverManager.getConnection(container.getJdbcUrl(), container.getUsername(), + container.getPassword()); return conn; } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ex) { throw new RuntimeException("Can not instantiate driver " + driver, ex); diff --git a/jfleet-core/src/test/java/org/jfleet/util/JdbcDatabase.java b/jfleet-core/src/test/java/org/jfleet/util/JdbcDatabase.java index 6f442b3..190680a 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/JdbcDatabase.java +++ b/jfleet-core/src/test/java/org/jfleet/util/JdbcDatabase.java @@ -18,11 +18,12 @@ import org.jfleet.BulkInsert; import org.jfleet.jdbc.JdbcBulkInsert; import org.jfleet.jdbc.JdbcConfiguration; +import org.testcontainers.containers.JdbcDatabaseContainer; public abstract class JdbcDatabase extends Database { - public JdbcDatabase(String properties) { - super(properties); + public JdbcDatabase(JdbcDatabaseContainer container) { + super(container); } @Override diff --git a/jfleet-core/src/test/java/org/jfleet/util/JdbcMysqlDatabase.java b/jfleet-core/src/test/java/org/jfleet/util/JdbcMysqlDatabase.java index dd9811b..4dd6817 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/JdbcMysqlDatabase.java +++ b/jfleet-core/src/test/java/org/jfleet/util/JdbcMysqlDatabase.java @@ -15,14 +15,12 @@ */ package org.jfleet.util; -public class JdbcMysqlDatabase extends JdbcDatabase { +import org.testcontainers.containers.JdbcDatabaseContainer; - public JdbcMysqlDatabase(String properties) { - super(properties); - } +public class JdbcMysqlDatabase extends JdbcDatabase { - public JdbcMysqlDatabase() { - super("mysql-test.properties"); + public JdbcMysqlDatabase(JdbcDatabaseContainer container) { + super(container); } } diff --git a/jfleet-core/src/test/java/org/jfleet/util/JdbcPostgresDatabase.java b/jfleet-core/src/test/java/org/jfleet/util/JdbcPostgresDatabase.java index 137b331..632f1fe 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/JdbcPostgresDatabase.java +++ b/jfleet-core/src/test/java/org/jfleet/util/JdbcPostgresDatabase.java @@ -15,14 +15,12 @@ */ package org.jfleet.util; -public class JdbcPostgresDatabase extends JdbcDatabase { +import org.testcontainers.containers.JdbcDatabaseContainer; - public JdbcPostgresDatabase(String properties) { - super(properties); - } +public class JdbcPostgresDatabase extends JdbcDatabase { - public JdbcPostgresDatabase() { - super("postgres-test.properties"); + public JdbcPostgresDatabase(JdbcDatabaseContainer postgresContainer) { + super(postgresContainer); } } diff --git a/jfleet-core/src/test/java/org/jfleet/util/MySqlDatabase.java b/jfleet-core/src/test/java/org/jfleet/util/MySqlDatabase.java index ff34b6e..9469b10 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/MySqlDatabase.java +++ b/jfleet-core/src/test/java/org/jfleet/util/MySqlDatabase.java @@ -17,15 +17,12 @@ import org.jfleet.BulkInsert; import org.jfleet.mysql.LoadDataBulkInsert; +import org.testcontainers.containers.JdbcDatabaseContainer; public class MySqlDatabase extends Database { - public MySqlDatabase(String properties) { - super(properties); - } - - public MySqlDatabase() { - super("mysql-test.properties"); + public MySqlDatabase(JdbcDatabaseContainer mySQLContainer) { + super(mySQLContainer); } @Override diff --git a/jfleet-core/src/test/java/org/jfleet/util/PostgresDatabase.java b/jfleet-core/src/test/java/org/jfleet/util/PostgresDatabase.java index c4580f3..d56712c 100644 --- a/jfleet-core/src/test/java/org/jfleet/util/PostgresDatabase.java +++ b/jfleet-core/src/test/java/org/jfleet/util/PostgresDatabase.java @@ -17,15 +17,12 @@ import org.jfleet.BulkInsert; import org.jfleet.postgres.PgCopyBulkInsert; +import org.testcontainers.containers.JdbcDatabaseContainer; public class PostgresDatabase extends Database { - public PostgresDatabase(String properties) { - super(properties); - } - - public PostgresDatabase() { - super("postgres-test.properties"); + public PostgresDatabase(JdbcDatabaseContainer postgresContainer) { + super(postgresContainer); } @Override diff --git a/jfleet-core/src/test/resources/my-sql-config/my.cnf b/jfleet-core/src/test/resources/my-sql-config/my.cnf new file mode 100644 index 0000000..dcb67a1 --- /dev/null +++ b/jfleet-core/src/test/resources/my-sql-config/my.cnf @@ -0,0 +1,2 @@ +[mysqld] +local-infile=1 \ No newline at end of file diff --git a/jfleet-core/src/test/resources/mysql-test.properties b/jfleet-core/src/test/resources/mysql-test.properties deleted file mode 100644 index d04c24e..0000000 --- a/jfleet-core/src/test/resources/mysql-test.properties +++ /dev/null @@ -1,4 +0,0 @@ -driver=com.mysql.jdbc.Driver -user=test -password=test -urlConnection=jdbc:mysql://localhost/testdb?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&allowLoadLocalInfile=true \ No newline at end of file diff --git a/jfleet-core/src/test/resources/postgres-test.properties b/jfleet-core/src/test/resources/postgres-test.properties deleted file mode 100644 index c55f2bc..0000000 --- a/jfleet-core/src/test/resources/postgres-test.properties +++ /dev/null @@ -1,4 +0,0 @@ -driver=org.postgresql.Driver -user=test -password=test -urlConnection=jdbc:postgresql://localhost:5432/testdb?reWriteBatchedInserts=true \ No newline at end of file