fix(database): qualify RD21 saves against pinned MariaDB 12.2.2
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
using JobTrackerApi.Data;
|
||||
using JobTrackerApi.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace JobTrackerApi.Tests;
|
||||
|
||||
public sealed class DatabaseConfigurationTests
|
||||
{
|
||||
private const string UnreachableMariaDb = "Server=127.0.0.1;Port=1;Database=jt_config_test;User=config_test;Password=synthetic;Connection Timeout=1";
|
||||
private static IConfiguration Config(string? provider = null, string? connection = null, string? version = null) =>
|
||||
new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Database:Provider"] = provider,
|
||||
["ConnectionStrings:JobTracker"] = connection,
|
||||
["Database:ServerVersion"] = version,
|
||||
}).Build();
|
||||
|
||||
[Fact]
|
||||
public void Default_registration_uses_pinned_MariaDb_without_connecting_to_a_server()
|
||||
{
|
||||
var configuration = Config(connection: UnreachableMariaDb);
|
||||
var options = new DbContextOptionsBuilder<JobTrackerContext>();
|
||||
DatabaseConfiguration.Configure(options, configuration, "unused.db");
|
||||
Assert.Equal("mariadb", DatabaseConfiguration.GetProvider(configuration));
|
||||
var relational = Assert.Single(options.Options.Extensions.OfType<RelationalOptionsExtension>());
|
||||
Assert.Equal(UnreachableMariaDb, relational.ConnectionString);
|
||||
// Inspect the provider's configured version without opening a connection or generating SQL.
|
||||
#pragma warning disable EF1001
|
||||
var mysql = Assert.IsType<MySqlOptionsExtension>(relational);
|
||||
Assert.IsType<MariaDbServerVersion>(mysql.ServerVersion);
|
||||
Assert.Equal(new Version(12, 2, 2), mysql.ServerVersion!.Version);
|
||||
#pragma warning restore EF1001
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("mariadb")]
|
||||
[InlineData("mysql")]
|
||||
public void Missing_MariaDb_connection_fails_closed_instead_of_creating_a_Sqlite_database(string? provider)
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<JobTrackerContext>();
|
||||
Assert.Throws<InvalidOperationException>(() => DatabaseConfiguration.Configure(options, Config(provider), "must-not-create.db"));
|
||||
Assert.Empty(options.Options.Extensions.OfType<RelationalOptionsExtension>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("postgres")]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("maria-db")]
|
||||
public void Unknown_provider_is_rejected_even_when_a_connection_is_configured(string provider)
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => DatabaseConfiguration.Configure(
|
||||
new DbContextOptionsBuilder<JobTrackerContext>(), Config(provider, "Data Source=must-not-create.db"), "unused.db"));
|
||||
Assert.Throws<InvalidOperationException>(() => DatabaseConfiguration.GetProvider(Config(provider)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("mariadb")]
|
||||
[InlineData(" MYSQL ")]
|
||||
public void MariaDb_server_version_is_configurable_without_auto_detection(string provider)
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<JobTrackerContext>();
|
||||
DatabaseConfiguration.Configure(options, Config(provider, UnreachableMariaDb, "11.4.10"), "unused.db");
|
||||
#pragma warning disable EF1001
|
||||
Assert.Equal(new Version(11, 4, 10), options.Options.Extensions.OfType<MySqlOptionsExtension>().Single().ServerVersion!.Version);
|
||||
#pragma warning restore EF1001
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Invalid_server_version_fails_during_configuration()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => DatabaseConfiguration.Configure(
|
||||
new DbContextOptionsBuilder<JobTrackerContext>(), Config("mariadb", UnreachableMariaDb, "latest"), "unused.db"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Data Source=preserved.db")]
|
||||
[InlineData("Data Source=explicit.db", "Data Source=explicit.db")]
|
||||
public void Explicit_Sqlite_preserves_existing_file_selection(string? connection, string expected)
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<JobTrackerContext>();
|
||||
DatabaseConfiguration.Configure(options, Config(" SQLITE ", connection), "preserved.db");
|
||||
var relational = Assert.Single(options.Options.Extensions.OfType<RelationalOptionsExtension>());
|
||||
Assert.Equal("SqliteOptionsExtension", relational.GetType().Name);
|
||||
Assert.Equal(expected, relational.ConnectionString);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Default_MariaDb_backup_selection_cannot_run_the_Sqlite_backup_path()
|
||||
{
|
||||
var root = Path.Combine(Path.GetTempPath(), $"jt-config-backup-{Guid.NewGuid():N}");
|
||||
var configuration = new ConfigurationBuilder().AddConfiguration(Config(connection: UnreachableMariaDb))
|
||||
.AddInMemoryCollection(new Dictionary<string, string?> { ["Data:Root"] = root }).Build();
|
||||
var environment = new Mock<IHostEnvironment>();
|
||||
environment.SetupGet(x => x.ContentRootPath).Returns(root);
|
||||
try
|
||||
{
|
||||
var runner = new SqliteDatabaseBackupRunner(configuration, new AppPaths(configuration, environment.Object), NullLogger<SqliteDatabaseBackupRunner>.Instance);
|
||||
Assert.False(runner.IsSupported);
|
||||
Assert.Null(await runner.RunOnceAsync(default));
|
||||
Assert.False(Directory.Exists(runner.BackupsRoot));
|
||||
}
|
||||
finally { if (Directory.Exists(root)) Directory.Delete(root, true); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user