Skip to content

Commit 0ade2f4

Browse files
committed
Improve Oracle support
Use the correct database default name depending on the Docker image version and enable setting a custom database name for Oracle 18 and onwards. Fixes #1233
1 parent 068b083 commit 0ade2f4

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
<PackageVersion Include="NATS.Client" Version="1.0.8"/>
6363
<PackageVersion Include="Neo4j.Driver" Version="5.5.0"/>
6464
<PackageVersion Include="Npgsql" Version="6.0.11"/>
65-
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="3.21.160"/>
65+
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="23.6.1"/>
6666
<PackageVersion Include="RabbitMQ.Client" Version="6.4.0"/>
6767
<PackageVersion Include="RavenDB.Client" Version="5.4.100"/>
6868
<PackageVersion Include="Selenium.WebDriver" Version="4.8.1"/>

src/Testcontainers.Oracle/OracleBuilder.cs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public sealed class OracleBuilder : ContainerBuilder<OracleBuilder, OracleContai
88

99
public const ushort OraclePort = 1521;
1010

11+
[Obsolete("Not used anymore. Only valid for Oracle images > 11 and < 23")]
1112
public const string DefaultDatabase = "XEPDB1";
1213

1314
public const string DefaultUsername = "oracle";
@@ -59,20 +60,63 @@ public OracleBuilder WithPassword(string password)
5960
.WithEnvironment("APP_USER_PASSWORD", password);
6061
}
6162

63+
/// <summary>
64+
/// Sets the Oracle database.
65+
/// </summary>
66+
/// <remarks>
67+
/// The database can only be set for Oracle 18 and onwards.
68+
/// </remarks>
69+
/// <param name="database">The Oracle database.</param>
70+
/// <returns>A configured instance of <see cref="OracleBuilder" />.</returns>
71+
public OracleBuilder WithDatabase(string database)
72+
{
73+
if (DockerResourceConfiguration.Image.MatchVersion(v => v.Major < 18))
74+
throw new NotSupportedException("Setting the database is only supported on Oracle 18 and onwards.");
75+
76+
return WithDatabaseUnchecked(database);
77+
}
78+
79+
private OracleBuilder WithDatabaseUnchecked(string database)
80+
{
81+
return Merge(DockerResourceConfiguration, new OracleConfiguration(database: database));
82+
}
83+
6284
/// <inheritdoc />
6385
public override OracleContainer Build()
6486
{
6587
Validate();
88+
89+
var defaultServiceName = GetDefaultServiceName();
90+
if (DockerResourceConfiguration.Database == null)
91+
{
92+
return new OracleContainer(WithDatabaseUnchecked(defaultServiceName).DockerResourceConfiguration);
93+
}
94+
95+
if (DockerResourceConfiguration.Database != defaultServiceName)
96+
{
97+
return new OracleContainer(WithEnvironment("ORACLE_DATABASE", DockerResourceConfiguration.Database).DockerResourceConfiguration);
98+
}
99+
66100
return new OracleContainer(DockerResourceConfiguration);
67101
}
68102

103+
private string GetDefaultServiceName()
104+
{
105+
if (DockerResourceConfiguration.Image.MatchVersion(v => v.Major >= 23))
106+
return "FREEPDB1";
107+
108+
if (DockerResourceConfiguration.Image.MatchVersion(v => v.Major > 11))
109+
return "XEPDB1";
110+
111+
return "XE";
112+
}
113+
69114
/// <inheritdoc />
70115
protected override OracleBuilder Init()
71116
{
72117
return base.Init()
73118
.WithImage(OracleImage)
74119
.WithPortBinding(OraclePort, true)
75-
.WithDatabase(DefaultDatabase)
76120
.WithUsername(DefaultUsername)
77121
.WithPassword(DefaultPassword)
78122
.WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("DATABASE IS READY TO USE!"));
@@ -105,17 +149,4 @@ protected override OracleBuilder Merge(OracleConfiguration oldValue, OracleConfi
105149
{
106150
return new OracleBuilder(new OracleConfiguration(oldValue, newValue));
107151
}
108-
109-
/// <summary>
110-
/// Sets the Oracle database.
111-
/// </summary>
112-
/// <remarks>
113-
/// The Docker image does not allow to configure the database.
114-
/// </remarks>
115-
/// <param name="database">The Oracle database.</param>
116-
/// <returns>A configured instance of <see cref="OracleBuilder" />.</returns>
117-
private OracleBuilder WithDatabase(string database)
118-
{
119-
return Merge(DockerResourceConfiguration, new OracleConfiguration(database: database));
120-
}
121152
}

tests/Testcontainers.Oracle.Tests/OracleContainerTest.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Testcontainers.Oracle;
22

3-
public sealed class OracleContainerTest(OracleContainerTest.OracleFixture oracleFixture) : IClassFixture<OracleContainerTest.OracleFixture>
3+
public abstract class OracleContainerTest(OracleContainerTest.OracleFixture oracleFixture)
44
{
55
[Fact]
66
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
@@ -32,9 +32,43 @@ public async Task ExecScriptReturnsSuccessful()
3232
Assert.Empty(execResult.Stderr);
3333
}
3434

35-
[UsedImplicitly]
36-
public class OracleFixture(IMessageSink messageSink) : DbContainerFixture<OracleBuilder, OracleContainer>(messageSink)
35+
public abstract class OracleFixture(IMessageSink messageSink, string edition, int? version, string database = null) : DbContainerFixture<OracleBuilder, OracleContainer>(messageSink)
3736
{
3837
public override DbProviderFactory DbProviderFactory => OracleClientFactory.Instance;
38+
39+
protected override OracleBuilder Configure(OracleBuilder builder)
40+
{
41+
if (edition == default && version == default)
42+
{
43+
return builder;
44+
}
45+
46+
var image = $"gvenzl/oracle-{edition}:{version}-slim-faststart";
47+
return database == null ? builder.WithImage(image) : builder.WithImage(image).WithDatabase(database);
48+
}
3949
}
50+
51+
[UsedImplicitly] public sealed class OracleDefault(OracleDefaultFixture fixture) : OracleContainerTest(fixture), IClassFixture<OracleDefaultFixture>;
52+
[UsedImplicitly] public sealed class Oracle11(Oracle11Fixture fixture) : OracleContainerTest(fixture), IClassFixture<Oracle11Fixture>;
53+
[UsedImplicitly] public sealed class Oracle18(Oracle18Fixture fixture) : OracleContainerTest(fixture), IClassFixture<Oracle18Fixture>;
54+
[UsedImplicitly] public sealed class Oracle21(Oracle21Fixture fixture) : OracleContainerTest(fixture), IClassFixture<Oracle21Fixture>;
55+
[UsedImplicitly] public sealed class Oracle23(Oracle23Fixture fixture) : OracleContainerTest(fixture), IClassFixture<Oracle23Fixture>;
56+
[UsedImplicitly] public sealed class Oracle18Default(Oracle18FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture<Oracle18FixtureDefault>;
57+
[UsedImplicitly] public sealed class Oracle21Default(Oracle21FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture<Oracle21FixtureDefault>;
58+
[UsedImplicitly] public sealed class Oracle23Default(Oracle23FixtureDefault fixture) : OracleContainerTest(fixture), IClassFixture<Oracle23FixtureDefault>;
59+
[UsedImplicitly] public sealed class Oracle18Scott(Oracle18FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture<Oracle18FixtureScott>;
60+
[UsedImplicitly] public sealed class Oracle21Scott(Oracle21FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture<Oracle21FixtureScott>;
61+
[UsedImplicitly] public sealed class Oracle23Scott(Oracle23FixtureScott fixture) : OracleContainerTest(fixture), IClassFixture<Oracle23FixtureScott>;
62+
63+
[UsedImplicitly] public class OracleDefaultFixture(IMessageSink messageSink) : OracleFixture(messageSink, default, default);
64+
[UsedImplicitly] public class Oracle11Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 11);
65+
[UsedImplicitly] public class Oracle18Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18);
66+
[UsedImplicitly] public class Oracle21Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21);
67+
[UsedImplicitly] public class Oracle23Fixture(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23);
68+
[UsedImplicitly] public class Oracle18FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18, "XEPDB1");
69+
[UsedImplicitly] public class Oracle21FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21, "XEPDB1");
70+
[UsedImplicitly] public class Oracle23FixtureDefault(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23, "FREEPDB1");
71+
[UsedImplicitly] public class Oracle18FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 18, "SCOTT");
72+
[UsedImplicitly] public class Oracle21FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "xe", 21, "SCOTT");
73+
[UsedImplicitly] public class Oracle23FixtureScott(IMessageSink messageSink) : OracleFixture(messageSink, "free", 23, "SCOTT");
4074
}

0 commit comments

Comments
 (0)