diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml
index e1f122658..7b75c21e3 100644
--- a/.github/workflows/cicd.yml
+++ b/.github/workflows/cicd.yml
@@ -72,6 +72,10 @@ jobs:
{ name: "Testcontainers.Nats", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.Neo4j", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.Oracle", runs-on: "ubuntu-22.04" },
+ { name: "Testcontainers.Oracle11", runs-on: "ubuntu-22.04" },
+ { name: "Testcontainers.Oracle18", runs-on: "ubuntu-22.04" },
+ { name: "Testcontainers.Oracle21", runs-on: "ubuntu-22.04" },
+ { name: "Testcontainers.Oracle23", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.Papercut", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.PostgreSql", runs-on: "ubuntu-22.04" },
{ name: "Testcontainers.PubSub", runs-on: "ubuntu-22.04" },
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0a4db1cff..7478929fd 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -68,7 +68,7 @@
-
+
diff --git a/Testcontainers.sln b/Testcontainers.sln
index 96eb3545f..138c3c0e1 100644
--- a/Testcontainers.sln
+++ b/Testcontainers.sln
@@ -187,6 +187,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Neo4j.Tests"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Oracle.Tests", "tests\Testcontainers.Oracle.Tests\Testcontainers.Oracle.Tests.csproj", "{4AC1088B-9965-4497-AC8E-570F1AD5631F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Oracle11.Tests", "tests\Testcontainers.Oracle11.Tests\Testcontainers.Oracle11.Tests.csproj", "{0A0AC20D-226B-46F9-B267-0D00964A7601}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Oracle18.Tests", "tests\Testcontainers.Oracle18.Tests\Testcontainers.Oracle18.Tests.csproj", "{E4C887A9-A44A-4641-BB9B-0664CC4C362F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Oracle21.Tests", "tests\Testcontainers.Oracle21.Tests\Testcontainers.Oracle21.Tests.csproj", "{1F6415BD-646E-436A-9F57-9AE30A0AA694}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Oracle23.Tests", "tests\Testcontainers.Oracle23.Tests\Testcontainers.Oracle23.Tests.csproj", "{FC417A93-4521-4FDB-943E-23886F3243C8}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Papercut.Tests", "tests\Testcontainers.Papercut.Tests\Testcontainers.Papercut.Tests.csproj", "{F03FA970-BE2B-4AE2-96FE-7E1F805CEA20}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Platform.Linux.Tests", "tests\Testcontainers.Platform.Linux.Tests\Testcontainers.Platform.Linux.Tests.csproj", "{DA1D7ADE-452C-4369-83CC-56289176EACD}"
@@ -578,6 +586,22 @@ Global
{4AC1088B-9965-4497-AC8E-570F1AD5631F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AC1088B-9965-4497-AC8E-570F1AD5631F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AC1088B-9965-4497-AC8E-570F1AD5631F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0A0AC20D-226B-46F9-B267-0D00964A7601}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0A0AC20D-226B-46F9-B267-0D00964A7601}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0A0AC20D-226B-46F9-B267-0D00964A7601}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0A0AC20D-226B-46F9-B267-0D00964A7601}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E4C887A9-A44A-4641-BB9B-0664CC4C362F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E4C887A9-A44A-4641-BB9B-0664CC4C362F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E4C887A9-A44A-4641-BB9B-0664CC4C362F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E4C887A9-A44A-4641-BB9B-0664CC4C362F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F6415BD-646E-436A-9F57-9AE30A0AA694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F6415BD-646E-436A-9F57-9AE30A0AA694}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F6415BD-646E-436A-9F57-9AE30A0AA694}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F6415BD-646E-436A-9F57-9AE30A0AA694}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC417A93-4521-4FDB-943E-23886F3243C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC417A93-4521-4FDB-943E-23886F3243C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC417A93-4521-4FDB-943E-23886F3243C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC417A93-4521-4FDB-943E-23886F3243C8}.Release|Any CPU.Build.0 = Release|Any CPU
{F03FA970-BE2B-4AE2-96FE-7E1F805CEA20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F03FA970-BE2B-4AE2-96FE-7E1F805CEA20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F03FA970-BE2B-4AE2-96FE-7E1F805CEA20}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -735,6 +759,10 @@ Global
{87A3F137-6DC3-4CE5-91E6-01797D076086} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{D3F63405-C0FA-4F83-8B79-E30BFF5FF5BF} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{4AC1088B-9965-4497-AC8E-570F1AD5631F} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {0A0AC20D-226B-46F9-B267-0D00964A7601} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {E4C887A9-A44A-4641-BB9B-0664CC4C362F} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {1F6415BD-646E-436A-9F57-9AE30A0AA694} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {FC417A93-4521-4FDB-943E-23886F3243C8} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{F03FA970-BE2B-4AE2-96FE-7E1F805CEA20} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{DA1D7ADE-452C-4369-83CC-56289176EACD} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{3E55CBE8-AFE8-426D-9470-49D63CD1051C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
diff --git a/src/Testcontainers.Oracle/OracleBuilder.cs b/src/Testcontainers.Oracle/OracleBuilder.cs
index c5cd3339e..e6c5710b5 100644
--- a/src/Testcontainers.Oracle/OracleBuilder.cs
+++ b/src/Testcontainers.Oracle/OracleBuilder.cs
@@ -8,6 +8,7 @@ public sealed class OracleBuilder : ContainerBuilder
protected override OracleConfiguration DockerResourceConfiguration { get; }
+ ///
+ /// Sets the Oracle database.
+ ///
+ ///
+ /// The database can only be set for Oracle 18 and onwards.
+ ///
+ /// The Oracle database.
+ /// A configured instance of .
+ public OracleBuilder WithDatabase(string database)
+ {
+ return Merge(DockerResourceConfiguration, new OracleConfiguration(database: database));
+ }
+
///
/// Sets the Oracle username.
///
@@ -63,6 +77,18 @@ public OracleBuilder WithPassword(string password)
public override OracleContainer Build()
{
Validate();
+
+ var defaultServiceName = GetDefaultServiceName();
+ if (DockerResourceConfiguration.Database == null)
+ {
+ return new OracleContainer(WithDatabase(defaultServiceName).DockerResourceConfiguration);
+ }
+
+ if (DockerResourceConfiguration.Database != defaultServiceName)
+ {
+ return new OracleContainer(WithEnvironment("ORACLE_DATABASE", DockerResourceConfiguration.Database).DockerResourceConfiguration);
+ }
+
return new OracleContainer(DockerResourceConfiguration);
}
@@ -72,7 +98,6 @@ protected override OracleBuilder Init()
return base.Init()
.WithImage(OracleImage)
.WithPortBinding(OraclePort, true)
- .WithDatabase(DefaultDatabase)
.WithUsername(DefaultUsername)
.WithPassword(DefaultPassword)
.WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("DATABASE IS READY TO USE!"));
@@ -83,6 +108,18 @@ protected override void Validate()
{
base.Validate();
+ const string message = "The image '{0}' does not support configuring the database. It is only supported on Oracle 18 and onwards.";
+
+ Predicate databaseConfigurationNotSupported = value =>
+ value.Database != null && value.Image.MatchVersion(v => v.Major < 18);
+
+ _ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Database))
+ .ThrowIf(argument => databaseConfigurationNotSupported(argument.Value), _ => throw new NotSupportedException(string.Format(message, DockerResourceConfiguration.Image.FullName)));
+
+ _ = Guard.Argument(DockerResourceConfiguration.Username, nameof(DockerResourceConfiguration.Username))
+ .NotNull()
+ .NotEmpty();
+
_ = Guard.Argument(DockerResourceConfiguration.Password, nameof(DockerResourceConfiguration.Password))
.NotNull()
.NotEmpty();
@@ -106,16 +143,18 @@ protected override OracleBuilder Merge(OracleConfiguration oldValue, OracleConfi
return new OracleBuilder(new OracleConfiguration(oldValue, newValue));
}
- ///
- /// Sets the Oracle database.
- ///
- ///
- /// The Docker image does not allow to configure the database.
- ///
- /// The Oracle database.
- /// A configured instance of .
- private OracleBuilder WithDatabase(string database)
+ private string GetDefaultServiceName()
{
- return Merge(DockerResourceConfiguration, new OracleConfiguration(database: database));
+ if (DockerResourceConfiguration.Image.MatchVersion(v => v.Major >= 23))
+ {
+ return "FREEPDB1";
+ }
+
+ if (DockerResourceConfiguration.Image.MatchVersion(v => v.Major > 11))
+ {
+ return "XEPDB1";
+ }
+
+ return "XE";
}
}
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle.Tests/OracleContainerTest.cs b/tests/Testcontainers.Oracle.Tests/OracleContainerTest.cs
index 5b6984dd0..e0bf81335 100644
--- a/tests/Testcontainers.Oracle.Tests/OracleContainerTest.cs
+++ b/tests/Testcontainers.Oracle.Tests/OracleContainerTest.cs
@@ -1,25 +1,13 @@
namespace Testcontainers.Oracle;
-public sealed class OracleContainerTest : IAsyncLifetime
+public abstract class OracleContainerTest(OracleContainerTest.OracleFixture oracleFixture)
{
- private readonly OracleContainer _oracleContainer = new OracleBuilder().Build();
-
- public Task InitializeAsync()
- {
- return _oracleContainer.StartAsync();
- }
-
- public Task DisposeAsync()
- {
- return _oracleContainer.DisposeAsync().AsTask();
- }
-
[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public void ConnectionStateReturnsOpen()
{
// Given
- using DbConnection connection = new OracleConnection(_oracleContainer.GetConnectionString());
+ using DbConnection connection = oracleFixture.CreateConnection();
// When
connection.Open();
@@ -36,11 +24,64 @@ public async Task ExecScriptReturnsSuccessful()
const string scriptContent = "SELECT 1 FROM DUAL;";
// When
- var execResult = await _oracleContainer.ExecScriptAsync(scriptContent)
+ var execResult = await oracleFixture.Container.ExecScriptAsync(scriptContent)
.ConfigureAwait(true);
// Then
Assert.True(0L.Equals(execResult.ExitCode), execResult.Stderr);
Assert.Empty(execResult.Stderr);
}
+
+ public abstract class OracleFixture(IMessageSink messageSink, string edition, int? version, string database = null) : DbContainerFixture(messageSink)
+ {
+ public override DbProviderFactory DbProviderFactory => OracleClientFactory.Instance;
+
+ protected override OracleBuilder Configure(OracleBuilder builder)
+ {
+ if (edition == null && version == null)
+ {
+ return builder;
+ }
+
+ var image = $"gvenzl/oracle-{edition}:{version}-slim-faststart";
+ return database == null ? builder.WithImage(image) : builder.WithImage(image).WithDatabase(database);
+ }
+ }
+
+#if ORACLE_DEFAULT
+ [UsedImplicitly] public sealed class OracleDefault(OracleDefaultFixture fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class OracleDefaultFixture(IMessageSink messageSink) : OracleFixture(messageSink, null, null);
+#endif
+
+#if ORACLE_11
+ [UsedImplicitly] public sealed class Oracle11(Oracle11Fixture fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle11Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 11);
+#endif
+
+#if ORACLE_18
+ [UsedImplicitly] public sealed class Oracle18(Oracle18Fixture fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle18Default(Oracle18FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle18Scott(Oracle18FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle18Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18);
+ [UsedImplicitly] public sealed class Oracle18FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18, "XEPDB1");
+ [UsedImplicitly] public sealed class Oracle18FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18, "SCOTT");
+#endif
+
+#if ORACLE_21
+ [UsedImplicitly] public sealed class Oracle21(Oracle21Fixture fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle21Default(Oracle21FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle21Scott(Oracle21FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle21Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21);
+ [UsedImplicitly] public sealed class Oracle21FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21, "XEPDB1");
+ [UsedImplicitly] public sealed class Oracle21FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21, "SCOTT");
+#endif
+
+#if ORACLE_23
+ [UsedImplicitly] public sealed class Oracle23(Oracle23Fixture fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle23Default(Oracle23FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle23Scott(Oracle23FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture;
+ [UsedImplicitly] public sealed class Oracle23Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23);
+ [UsedImplicitly] public sealed class Oracle23FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23, "FREEPDB1");
+ [UsedImplicitly] public sealed class Oracle23FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23, "SCOTT");
+#endif
}
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle.Tests/Testcontainers.Oracle.Tests.csproj b/tests/Testcontainers.Oracle.Tests/Testcontainers.Oracle.Tests.csproj
index 4d619cd84..914e234f4 100644
--- a/tests/Testcontainers.Oracle.Tests/Testcontainers.Oracle.Tests.csproj
+++ b/tests/Testcontainers.Oracle.Tests/Testcontainers.Oracle.Tests.csproj
@@ -3,6 +3,7 @@
net9.0
false
false
+ $(DefineConstants);ORACLE_DEFAULT
@@ -13,6 +14,7 @@
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle.Tests/Usings.cs b/tests/Testcontainers.Oracle.Tests/Usings.cs
index eb37bd7e3..e1e61a204 100644
--- a/tests/Testcontainers.Oracle.Tests/Usings.cs
+++ b/tests/Testcontainers.Oracle.Tests/Usings.cs
@@ -2,5 +2,8 @@
global using System.Data.Common;
global using System.Threading.Tasks;
global using DotNet.Testcontainers.Commons;
+global using JetBrains.Annotations;
global using Oracle.ManagedDataAccess.Client;
-global using Xunit;
\ No newline at end of file
+global using Testcontainers.Xunit;
+global using Xunit;
+global using Xunit.Abstractions;
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle11.Tests/.editorconfig b/tests/Testcontainers.Oracle11.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Oracle11.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle11.Tests/Testcontainers.Oracle11.Tests.csproj b/tests/Testcontainers.Oracle11.Tests/Testcontainers.Oracle11.Tests.csproj
new file mode 100644
index 000000000..3b6fae47e
--- /dev/null
+++ b/tests/Testcontainers.Oracle11.Tests/Testcontainers.Oracle11.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+ net9.0
+ false
+ false
+ $(DefineConstants);ORACLE_11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle18.Tests/.editorconfig b/tests/Testcontainers.Oracle18.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Oracle18.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle18.Tests/Testcontainers.Oracle18.Tests.csproj b/tests/Testcontainers.Oracle18.Tests/Testcontainers.Oracle18.Tests.csproj
new file mode 100644
index 000000000..cdd26379a
--- /dev/null
+++ b/tests/Testcontainers.Oracle18.Tests/Testcontainers.Oracle18.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+ net9.0
+ false
+ false
+ $(DefineConstants);ORACLE_18
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle21.Tests/.editorconfig b/tests/Testcontainers.Oracle21.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Oracle21.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle21.Tests/Testcontainers.Oracle21.Tests.csproj b/tests/Testcontainers.Oracle21.Tests/Testcontainers.Oracle21.Tests.csproj
new file mode 100644
index 000000000..a75f705bc
--- /dev/null
+++ b/tests/Testcontainers.Oracle21.Tests/Testcontainers.Oracle21.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+ net9.0
+ false
+ false
+ $(DefineConstants);ORACLE_21
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle23.Tests/.editorconfig b/tests/Testcontainers.Oracle23.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Oracle23.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Oracle23.Tests/Testcontainers.Oracle23.Tests.csproj b/tests/Testcontainers.Oracle23.Tests/Testcontainers.Oracle23.Tests.csproj
new file mode 100644
index 000000000..60f0cfc65
--- /dev/null
+++ b/tests/Testcontainers.Oracle23.Tests/Testcontainers.Oracle23.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+ net9.0
+ false
+ false
+ $(DefineConstants);ORACLE_23
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file