diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 8a8b92c6110..135c8323866 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -38,7 +38,8 @@ body: - MySQL - Neo4j - NGINX - - Oracle-XE + - Oracle Free + - Oracle XE - OrientDB - PostgreSQL - Presto diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml index 56391755f2e..d77b4ce07a2 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yaml +++ b/.github/ISSUE_TEMPLATE/enhancement.yaml @@ -38,7 +38,8 @@ body: - MySQL - Neo4j - NGINX - - Oracle-XE + - Oracle Free + - Oracle XE - OrientDB - PostgreSQL - Presto diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml index 3d5e6bd44b6..65a27e5f99a 100644 --- a/.github/ISSUE_TEMPLATE/feature.yaml +++ b/.github/ISSUE_TEMPLATE/feature.yaml @@ -38,7 +38,8 @@ body: - MySQL - Neo4j - NGINX - - Oracle-XE + - Oracle Free + - Oracle XE - OrientDB - PostgreSQL - QuestDB diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4eb1900e45e..3cb3e0fd222 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -194,6 +194,10 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 10 + - package-ecosystem: "gradle" + directory: "/modules/oracle-free" + schedule: + interval: "weekly" - package-ecosystem: "gradle" directory: "/modules/oracle-xe" schedule: diff --git a/.github/labeler.yml b/.github/labeler.yml index 748037f2d39..3b4c1924df1 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -62,6 +62,7 @@ "modules/nginx": - modules/nginx/**/* "modules/oracle": + - modules/oracle-free/**/* - modules/oracle-xe/**/* "modules/orientdb": - modules/orientdb/**/* diff --git a/docs/modules/databases/oraclefree.md b/docs/modules/databases/oraclefree.md new file mode 100644 index 00000000000..c85d672f140 --- /dev/null +++ b/docs/modules/databases/oraclefree.md @@ -0,0 +1,33 @@ +# Oracle Database Free Module + +See [Database containers](./index.md) for documentation and usage that is common to all relational database container types. + +## Usage example + +You can use `OracleContainer` like any other JDBC container: + +[Container creation](../../../modules/oracle-free/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java) inside_block:constructor + + +## Adding this module to your project dependencies + +Add the following dependency to your `pom.xml`/`build.gradle` file: + +=== "Gradle" + ```groovy + testImplementation "org.testcontainers:oracle-free:{{latest_version}}" + ``` +=== "Maven" + ```xml + + org.testcontainers + oracle-free + {{latest_version}} + test + + ``` + +!!! hint + Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency. + + diff --git a/modules/oracle-free/build.gradle b/modules/oracle-free/build.gradle new file mode 100644 index 00000000000..cf572558307 --- /dev/null +++ b/modules/oracle-free/build.gradle @@ -0,0 +1,32 @@ +description = "Testcontainers :: JDBC :: Oracle Database Free" + +dependencies { + annotationProcessor 'com.google.auto.service:auto-service:1.1.1' + compileOnly 'com.google.auto.service:auto-service:1.1.1' + + api project(':jdbc') + + compileOnly project(':r2dbc') + compileOnly 'com.oracle.database.r2dbc:oracle-r2dbc:1.1.1' + + testImplementation project(':jdbc-test') + testImplementation 'com.oracle.database.jdbc:ojdbc11:23.3.0.23.09' + + compileOnly 'org.jetbrains:annotations:24.0.1' + + testImplementation testFixtures(project(':r2dbc')) + testRuntimeOnly 'com.oracle.database.r2dbc:oracle-r2dbc:1.1.1' +} + +test { + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(11) + } +} + +compileTestJava { + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(11) + } + options.release.set(11) +} diff --git a/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainer.java b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainer.java new file mode 100644 index 00000000000..1130072be12 --- /dev/null +++ b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainer.java @@ -0,0 +1,194 @@ +package org.testcontainers.oracle; + +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.testcontainers.containers.JdbcDatabaseContainer; +import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; +import org.testcontainers.utility.DockerImageName; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * Testcontainers implementation for Oracle Database Free. + *

+ * Supported image: {@code gvenzl/oracle-free} + *

+ * Exposed ports: 1521 + */ +public class OracleContainer extends JdbcDatabaseContainer { + + static final String NAME = "oracle"; + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gvenzl/oracle-free"); + + static final String DEFAULT_TAG = "slim"; + + static final String IMAGE = DEFAULT_IMAGE_NAME.getUnversionedPart(); + + static final int ORACLE_PORT = 1521; + + private static final int DEFAULT_STARTUP_TIMEOUT_SECONDS = 60; + + private static final int DEFAULT_CONNECT_TIMEOUT_SECONDS = 60; + + // Container defaults + static final String DEFAULT_DATABASE_NAME = "freepdb1"; + + static final String DEFAULT_SID = "free"; + + static final String DEFAULT_SYSTEM_USER = "system"; + + static final String DEFAULT_SYS_USER = "sys"; + + // Test container defaults + static final String APP_USER = "test"; + + static final String APP_USER_PASSWORD = "test"; + + // Restricted user and database names + private static final List ORACLE_SYSTEM_USERS = Arrays.asList(DEFAULT_SYSTEM_USER, DEFAULT_SYS_USER); + + private String databaseName = DEFAULT_DATABASE_NAME; + + private String username = APP_USER; + + private String password = APP_USER_PASSWORD; + + private boolean usingSid = false; + + public OracleContainer(String dockerImageName) { + this(DockerImageName.parse(dockerImageName)); + } + + public OracleContainer(final DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + this.waitStrategy = + new LogMessageWaitStrategy() + .withRegEx(".*DATABASE IS READY TO USE!.*\\s") + .withTimes(1) + .withStartupTimeout(Duration.of(DEFAULT_STARTUP_TIMEOUT_SECONDS, ChronoUnit.SECONDS)); + withConnectTimeoutSeconds(DEFAULT_CONNECT_TIMEOUT_SECONDS); + addExposedPorts(ORACLE_PORT); + } + + @Override + protected void waitUntilContainerStarted() { + getWaitStrategy().waitUntilReady(this); + } + + @NotNull + @Override + public Set getLivenessCheckPortNumbers() { + return Collections.singleton(getMappedPort(ORACLE_PORT)); + } + + @Override + public String getDriverClassName() { + return "oracle.jdbc.driver.OracleDriver"; + } + + @Override + public String getJdbcUrl() { + return isUsingSid() + ? "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + ":" + getSid() + : "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + "/" + getDatabaseName(); + } + + @Override + public String getUsername() { + // An application user is tied to the database, and therefore not authenticated to connect to SID. + return isUsingSid() ? DEFAULT_SYSTEM_USER : username; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getDatabaseName() { + return databaseName; + } + + protected boolean isUsingSid() { + return usingSid; + } + + @Override + public OracleContainer withUsername(String username) { + if (StringUtils.isEmpty(username)) { + throw new IllegalArgumentException("Username cannot be null or empty"); + } + if (ORACLE_SYSTEM_USERS.contains(username.toLowerCase())) { + throw new IllegalArgumentException("Username cannot be one of " + ORACLE_SYSTEM_USERS); + } + this.username = username; + return self(); + } + + @Override + public OracleContainer withPassword(String password) { + if (StringUtils.isEmpty(password)) { + throw new IllegalArgumentException("Password cannot be null or empty"); + } + this.password = password; + return self(); + } + + @Override + public OracleContainer withDatabaseName(String databaseName) { + if (StringUtils.isEmpty(databaseName)) { + throw new IllegalArgumentException("Database name cannot be null or empty"); + } + + if (DEFAULT_DATABASE_NAME.equals(databaseName.toLowerCase())) { + throw new IllegalArgumentException("Database name cannot be set to " + DEFAULT_DATABASE_NAME); + } + + this.databaseName = databaseName; + return self(); + } + + public OracleContainer usingSid() { + this.usingSid = true; + return self(); + } + + @Override + public OracleContainer withUrlParam(String paramName, String paramValue) { + throw new UnsupportedOperationException("The Oracle Database driver does not support this"); + } + + @SuppressWarnings("SameReturnValue") + public String getSid() { + return DEFAULT_SID; + } + + public Integer getOraclePort() { + return getMappedPort(ORACLE_PORT); + } + + @Override + public String getTestQueryString() { + return "SELECT 1 FROM DUAL"; + } + + @Override + protected void configure() { + withEnv("ORACLE_PASSWORD", password); + + // Only set ORACLE_DATABASE if different than the default. + if (databaseName != DEFAULT_DATABASE_NAME) { + withEnv("ORACLE_DATABASE", databaseName); + } + + withEnv("APP_USER", username); + withEnv("APP_USER_PASSWORD", password); + } +} diff --git a/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainerProvider.java b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainerProvider.java new file mode 100644 index 00000000000..031d3471cc5 --- /dev/null +++ b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleContainerProvider.java @@ -0,0 +1,29 @@ +package org.testcontainers.oracle; + +import org.testcontainers.containers.JdbcDatabaseContainer; +import org.testcontainers.containers.JdbcDatabaseContainerProvider; +import org.testcontainers.utility.DockerImageName; + +/** + * Factory for Oracle containers. + */ +public class OracleContainerProvider extends JdbcDatabaseContainerProvider { + + @Override + public boolean supports(String databaseType) { + return databaseType.equals(OracleContainer.NAME); + } + + @Override + public JdbcDatabaseContainer newInstance() { + return newInstance(OracleContainer.DEFAULT_TAG); + } + + @Override + public JdbcDatabaseContainer newInstance(String tag) { + if (tag != null) { + return new OracleContainer(DockerImageName.parse(OracleContainer.IMAGE).withTag(tag)); + } + return newInstance(); + } +} diff --git a/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainer.java b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainer.java new file mode 100644 index 00000000000..f9c12955653 --- /dev/null +++ b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainer.java @@ -0,0 +1,35 @@ +package org.testcontainers.oracle; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Delegate; +import org.testcontainers.lifecycle.Startable; +import org.testcontainers.r2dbc.R2DBCDatabaseContainer; + +@RequiredArgsConstructor +public class OracleR2DBCDatabaseContainer implements R2DBCDatabaseContainer { + + @Delegate(types = Startable.class) + private final OracleContainer container; + + public static ConnectionFactoryOptions getOptions(OracleContainer container) { + ConnectionFactoryOptions options = ConnectionFactoryOptions + .builder() + .option(ConnectionFactoryOptions.DRIVER, OracleR2DBCDatabaseContainerProvider.DRIVER) + .build(); + + return new OracleR2DBCDatabaseContainer(container).configure(options); + } + + @Override + public ConnectionFactoryOptions configure(ConnectionFactoryOptions options) { + return options + .mutate() + .option(ConnectionFactoryOptions.HOST, container.getHost()) + .option(ConnectionFactoryOptions.PORT, container.getMappedPort(OracleContainer.ORACLE_PORT)) + .option(ConnectionFactoryOptions.DATABASE, container.getDatabaseName()) + .option(ConnectionFactoryOptions.USER, container.getUsername()) + .option(ConnectionFactoryOptions.PASSWORD, container.getPassword()) + .build(); + } +} diff --git a/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainerProvider.java b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainerProvider.java new file mode 100644 index 00000000000..6fe809aa214 --- /dev/null +++ b/modules/oracle-free/src/main/java/org/testcontainers/oracle/OracleR2DBCDatabaseContainerProvider.java @@ -0,0 +1,43 @@ +package org.testcontainers.oracle; + +import com.google.auto.service.AutoService; +import io.r2dbc.spi.ConnectionFactoryMetadata; +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.jetbrains.annotations.Nullable; +import org.testcontainers.r2dbc.R2DBCDatabaseContainer; +import org.testcontainers.r2dbc.R2DBCDatabaseContainerProvider; + +@AutoService(R2DBCDatabaseContainerProvider.class) +public class OracleR2DBCDatabaseContainerProvider implements R2DBCDatabaseContainerProvider { + + static final String DRIVER = "oracle"; + + @Override + public boolean supports(ConnectionFactoryOptions options) { + return DRIVER.equals(options.getRequiredValue(ConnectionFactoryOptions.DRIVER)); + } + + @Override + public R2DBCDatabaseContainer createContainer(ConnectionFactoryOptions options) { + String image = OracleContainer.IMAGE + ":" + options.getRequiredValue(IMAGE_TAG_OPTION); + OracleContainer container = new OracleContainer(image) + .withDatabaseName((String) options.getRequiredValue(ConnectionFactoryOptions.DATABASE)); + if (Boolean.TRUE.equals(options.getValue(REUSABLE_OPTION))) { + container.withReuse(true); + } + return new OracleR2DBCDatabaseContainer(container); + } + + @Nullable + @Override + public ConnectionFactoryMetadata getMetadata(ConnectionFactoryOptions options) { + ConnectionFactoryOptions.Builder builder = options.mutate(); + if (!options.hasOption(ConnectionFactoryOptions.USER)) { + builder.option(ConnectionFactoryOptions.USER, OracleContainer.APP_USER); + } + if (!options.hasOption(ConnectionFactoryOptions.PASSWORD)) { + builder.option(ConnectionFactoryOptions.PASSWORD, OracleContainer.APP_USER_PASSWORD); + } + return R2DBCDatabaseContainerProvider.super.getMetadata(builder.build()); + } +} diff --git a/modules/oracle-free/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider b/modules/oracle-free/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider new file mode 100644 index 00000000000..fd3e21bca3d --- /dev/null +++ b/modules/oracle-free/src/main/resources/META-INF/services/org.testcontainers.containers.JdbcDatabaseContainerProvider @@ -0,0 +1 @@ +org.testcontainers.oracle.OracleContainerProvider diff --git a/modules/oracle-free/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java b/modules/oracle-free/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java new file mode 100644 index 00000000000..5ef276c0157 --- /dev/null +++ b/modules/oracle-free/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java @@ -0,0 +1,145 @@ +package org.testcontainers.junit.oracle; + +import org.junit.Test; +import org.testcontainers.db.AbstractContainerDatabaseTest; +import org.testcontainers.oracle.OracleContainer; +import org.testcontainers.utility.DockerImageName; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +public class SimpleOracleTest extends AbstractContainerDatabaseTest { + + public static final DockerImageName ORACLE_DOCKER_IMAGE_NAME = DockerImageName.parse( + "gvenzl/oracle-free:slim-faststart" + ); + + private void runTest(OracleContainer container, String databaseName, String username, String password) + throws SQLException { + //Test config was honored + assertThat(container.getDatabaseName()).isEqualTo(databaseName); + assertThat(container.getUsername()).isEqualTo(username); + assertThat(container.getPassword()).isEqualTo(password); + + //Test we can get a connection + container.start(); + ResultSet resultSet = performQuery(container, "SELECT 1 FROM dual"); + int resultSetInt = resultSet.getInt(1); + assertThat(resultSetInt).as("A basic SELECT query succeeds").isEqualTo(1); + } + + @Test + public void testDefaultSettings() throws SQLException { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME);) { + runTest(oracle, "freepdb1", "test", "test"); + + // Match against the last '/' + String urlSuffix = oracle.getJdbcUrl().split("(\\/)(?!.*\\/)", 2)[1]; + assertThat(urlSuffix).isEqualTo("freepdb1"); + } + } + + @Test + public void testPluggableDatabase() throws SQLException { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME).withDatabaseName("testDB")) { + runTest(oracle, "testDB", "test", "test"); + } + } + + @Test + public void testPluggableDatabaseAndCustomUser() throws SQLException { + try ( + // constructor { + OracleContainer oracle = new OracleContainer("gvenzl/oracle-free:slim-faststart") + .withDatabaseName("testDB") + .withUsername("testUser") + .withPassword("testPassword") + // } + ) { + runTest(oracle, "testDB", "testUser", "testPassword"); + } + } + + @Test + public void testCustomUser() throws SQLException { + try ( + OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME) + .withUsername("testUser") + .withPassword("testPassword") + ) { + runTest(oracle, "freepdb1", "testUser", "testPassword"); + } + } + + @Test + public void testSID() throws SQLException { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME).usingSid();) { + runTest(oracle, "freepdb1", "system", "test"); + + // Match against the last ':' + String urlSuffix = oracle.getJdbcUrl().split("(\\:)(?!.*\\:)", 2)[1]; + assertThat(urlSuffix).isEqualTo("free"); + } + } + + @Test + public void testSIDAndCustomPassword() throws SQLException { + try ( + OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME) + .usingSid() + .withPassword("testPassword"); + ) { + runTest(oracle, "freepdb1", "system", "testPassword"); + } + } + + @Test + public void testErrorPaths() throws SQLException { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)) { + try { + oracle.withDatabaseName("FREEPDB1"); + fail("Should not have been able to set database name to freepdb1."); + } catch (IllegalArgumentException e) { + //expected + } + + try { + oracle.withDatabaseName(""); + fail("Should not have been able to set database name to nothing."); + } catch (IllegalArgumentException e) { + //expected + } + + try { + oracle.withUsername("SYSTEM"); + fail("Should not have been able to set username to system."); + } catch (IllegalArgumentException e) { + //expected + } + + try { + oracle.withUsername("SYS"); + fail("Should not have been able to set username to sys."); + } catch (IllegalArgumentException e) { + //expected + } + + try { + oracle.withUsername(""); + fail("Should not have been able to set username to nothing."); + } catch (IllegalArgumentException e) { + //expected + } + + try { + oracle.withPassword(""); + fail("Should not have been able to set password to nothing."); + } catch (IllegalArgumentException e) { + //expected + } + } + } +} diff --git a/modules/oracle-free/src/test/java/org/testcontainers/oracle/jdbc/OracleJDBCDriverTest.java b/modules/oracle-free/src/test/java/org/testcontainers/oracle/jdbc/OracleJDBCDriverTest.java new file mode 100644 index 00000000000..6f6157c61c8 --- /dev/null +++ b/modules/oracle-free/src/test/java/org/testcontainers/oracle/jdbc/OracleJDBCDriverTest.java @@ -0,0 +1,48 @@ +package org.testcontainers.oracle.jdbc; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.apache.commons.dbutils.QueryRunner; +import org.apache.commons.dbutils.ResultSetHandler; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OracleJDBCDriverTest { + + @Test + public void testOracleWithNoSpecifiedVersion() throws SQLException { + performSimpleTest("jdbc:tc:oracle://hostname/databasename"); + } + + private void performSimpleTest(String jdbcUrl) throws SQLException { + HikariDataSource dataSource = getDataSource(jdbcUrl, 1); + new QueryRunner(dataSource) + .query( + "SELECT 1 FROM dual", + new ResultSetHandler() { + @Override + public Object handle(ResultSet rs) throws SQLException { + rs.next(); + int resultSetInt = rs.getInt(1); + assertThat(resultSetInt).as("A basic SELECT query succeeds").isEqualTo(1); + return true; + } + } + ); + dataSource.close(); + } + + private HikariDataSource getDataSource(String jdbcUrl, int poolSize) { + HikariConfig hikariConfig = new HikariConfig(); + hikariConfig.setJdbcUrl(jdbcUrl); + hikariConfig.setConnectionTestQuery("SELECT 1 FROM dual"); + hikariConfig.setMinimumIdle(1); + hikariConfig.setMaximumPoolSize(poolSize); + + return new HikariDataSource(hikariConfig); + } +} diff --git a/modules/oracle-free/src/test/java/org/testcontainers/oracle/r2dbc/OracleR2DBCDatabaseContainerTest.java b/modules/oracle-free/src/test/java/org/testcontainers/oracle/r2dbc/OracleR2DBCDatabaseContainerTest.java new file mode 100644 index 00000000000..a3933cdfe39 --- /dev/null +++ b/modules/oracle-free/src/test/java/org/testcontainers/oracle/r2dbc/OracleR2DBCDatabaseContainerTest.java @@ -0,0 +1,30 @@ +package org.testcontainers.oracle.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.oracle.OracleContainer; +import org.testcontainers.oracle.OracleR2DBCDatabaseContainer; +import org.testcontainers.r2dbc.AbstractR2DBCDatabaseContainerTest; + +public class OracleR2DBCDatabaseContainerTest extends AbstractR2DBCDatabaseContainerTest { + + @Override + protected OracleContainer createContainer() { + return new OracleContainer("gvenzl/oracle-free:slim-faststart"); + } + + @Override + protected ConnectionFactoryOptions getOptions(OracleContainer container) { + ConnectionFactoryOptions options = OracleR2DBCDatabaseContainer.getOptions(container); + + return options; + } + + protected String createR2DBCUrl() { + return "r2dbc:tc:oracle:///db?TC_IMAGE_TAG=slim-faststart"; + } + + @Override + protected String query() { + return "SELECT %s from dual"; + } +} diff --git a/modules/oracle-free/src/test/resources/logback-test.xml b/modules/oracle-free/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..83ef7a1a3ef --- /dev/null +++ b/modules/oracle-free/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + %d{HH:mm:ss.SSS} %-5level %logger - %msg%n + + + + + + + + +