Skip to content

Commit

Permalink
Modernize Oracle Container Logic
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleAure committed Sep 22, 2021
1 parent 0ad8154 commit d12bde1
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 19 deletions.
2 changes: 2 additions & 0 deletions modules/oracle-xe/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ dependencies {

testImplementation project(':jdbc-test')
testImplementation 'com.oracle.ojdbc:ojdbc8:19.3.0.0'

compileOnly 'org.jetbrains:annotations:21.0.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@

import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;

import static java.time.temporal.ChronoUnit.SECONDS;
import static java.util.Collections.singleton;

public class OracleContainer extends JdbcDatabaseContainer<OracleContainer> {

public static final String NAME = "oracle";
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gvenzl/oracle-xe");


static final String DEFAULT_TAG = "18.4.0-slim";
static final String IMAGE = DEFAULT_IMAGE_NAME.getUnversionedPart();

Expand All @@ -23,10 +28,25 @@ public class OracleContainer extends JdbcDatabaseContainer<OracleContainer> {

private static final int DEFAULT_STARTUP_TIMEOUT_SECONDS = 240;
private static final int DEFAULT_CONNECT_TIMEOUT_SECONDS = 120;
private static final List<String> ORACLE_SYSTEM_USERS = Arrays.asList("system", "sys");

private String username = "test";
private String password = "test";
// Container defaults
static final String DEFAULT_DATABASE_NAME = "xepdb1";
static final String DEFAULT_SID = "xe";
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<String> ORACLE_SYSTEM_USERS = Arrays.asList(DEFAULT_SYSTEM_USER, DEFAULT_SYS_USER);
private static final List<String> ORACLE_DEFAULT_DBS = Arrays.asList(DEFAULT_DATABASE_NAME);

private String databaseName = DEFAULT_DATABASE_NAME;
private String username = APP_USER;
private String password = APP_USER_PASSWORD;
private boolean usingSid = false;

/**
* @deprecated use {@link OracleContainer(DockerImageName)} instead
Expand All @@ -42,6 +62,7 @@ public OracleContainer(String dockerImageName) {

public OracleContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
preconfigure();
}

Expand All @@ -51,14 +72,24 @@ public OracleContainer(Future<String> dockerImageName) {
}

private void preconfigure() {
withStartupTimeoutSeconds(DEFAULT_STARTUP_TIMEOUT_SECONDS);
this.waitStrategy = new LogMessageWaitStrategy()
.withRegEx(".*DATABASE IS READY TO USE!.*\\s")
.withTimes(1)
.withStartupTimeout(Duration.of(DEFAULT_STARTUP_TIMEOUT_SECONDS, SECONDS));

withConnectTimeoutSeconds(DEFAULT_CONNECT_TIMEOUT_SECONDS);
addExposedPorts(ORACLE_PORT, APEX_HTTP_PORT);
}

@Override
protected void waitUntilContainerStarted() {
getWaitStrategy().waitUntilReady(this);
}

@NotNull
@Override
public Set<Integer> getLivenessCheckPortNumbers() {
return Sets.newHashSet(ORACLE_PORT);
return singleton(getMappedPort(ORACLE_PORT));
}

@Override
Expand All @@ -68,19 +99,31 @@ public String getDriverClassName() {

@Override
public String getJdbcUrl() {
return "jdbc:oracle:thin:" + getUsername() + "/" + getPassword() + "@" + getHost() + ":" + getOraclePort() + "/xepdb1";
return isUsingSid() ?
"jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + ":" + getSid() :
"jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + "/" + getDatabaseName();
}

@Override
public String getUsername() {
return username;
//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;
}

public boolean isUsingSid() {
return usingSid;
}

@Override
public OracleContainer withUsername(String username) {
if (StringUtils.isEmpty(username)) {
Expand All @@ -102,14 +145,33 @@ public OracleContainer withPassword(String password) {
return self();
}

@Override
public OracleContainer withDatabaseName(String databaseName) {
if (StringUtils.isEmpty(databaseName)) {
throw new IllegalArgumentException("Database name cannot be null or empty");
}

if (ORACLE_DEFAULT_DBS.contains(databaseName.toLowerCase())) {
throw new IllegalArgumentException("Database name cannot be one of " + ORACLE_DEFAULT_DBS);
}

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 OracleDb does not support this");
throw new UnsupportedOperationException("The Oracle Database driver does not support this");
}

@SuppressWarnings("SameReturnValue")
public String getSid() {
return "xe";
return DEFAULT_SID;
}

public Integer getOraclePort() {
Expand All @@ -129,6 +191,12 @@ public String getTestQueryString() {
@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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.testcontainers.junit.oracle;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.testcontainers.containers.OracleContainer;
import org.testcontainers.db.AbstractContainerDatabaseTest;
Expand All @@ -8,26 +12,86 @@
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;

public class SimpleOracleTest extends AbstractContainerDatabaseTest {

public static final DockerImageName ORACLE_DOCKER_IMAGE_NAME = DockerImageName.parse("gvenzl/oracle-xe:18.4.0-slim");

private void runTest(OracleContainer container, String databaseName, String username, String password) throws SQLException {
//Test config was honored
assertEquals(container.getDatabaseName(), databaseName);
assertEquals(container.getUsername(), username);
assertEquals(container.getPassword(), password);

//Test we can get a connection
container.start();
ResultSet resultSet = performQuery(container, "SELECT 1 FROM dual");
int resultSetInt = resultSet.getInt(1);
assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
}

@Test
public void testSimple() throws SQLException {
public void testDefaultSettings() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME);
) {
assertFalse(oracle.isUsingSid());
runTest(oracle, "xepdb1", "test", "test");
}
}

@Test
public void testPluggableDatabase() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)
.withUsername("baz")
.withPassword("bar")
.withDatabaseName("testDB")
) {
oracle.start();
ResultSet resultSet = performQuery(oracle, "SELECT 1 FROM dual");
runTest(oracle, "testDB", "test", "test");
}
}

int resultSetInt = resultSet.getInt(1);
@Test
public void testPluggableDatabaseAndCustomUser() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)
.withDatabaseName("testDB")
.withUsername("testUser")
.withPassword("testPassword")
) {
runTest(oracle, "testDB", "testUser", "testPassword");
}
}

assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
@Test
public void testCustomUser() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)
.withUsername("testUser")
.withPassword("testPassword")
) {
runTest(oracle, "xepdb1", "testUser", "testPassword");
}
}

@Test
public void testSID() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)
.usingSid();
) {
assertTrue(oracle.isUsingSid());
runTest(oracle, "xepdb1", "system", "test");
}
}

@Test
public void testSIDAndCustomPassword() throws SQLException {
try (
OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME)
.usingSid()
.withPassword("testPassword");
) {
assertTrue(oracle.isUsingSid());
runTest(oracle, "xepdb1", "system", "testPassword");
}
}
}

0 comments on commit d12bde1

Please sign in to comment.