Initial curated itworx-knowledge-hub source from 3b1751d0d9dee551aa6994eee0093704dc334817
This commit is contained in:
commit
ad8ad252a9
825 files changed
+124216
No files matched your search
@@ -0,0 +1,89 @@
|
||||
using ItWorx.KnowledgeHub.Infrastructure.Persistence;
|
||||
using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
|
||||
namespace ItWorx.KnowledgeHub.IntegrationTests.Operations;
|
||||
|
||||
/// <summary>Proves M7-A02 ("Startup refuses unsafe schema drift") against a real,
|
||||
/// freshly migrated PostgreSQL database — forward migration (the normal path) must
|
||||
/// stay silent, and a database with an applied migration this build's assembly does
|
||||
/// not know about must be refused before any data-mutating call.</summary>
|
||||
[Collection(PostgresTestGroup.Name)]
|
||||
public sealed class SchemaGuardTests(PostgresContainerFixture postgres)
|
||||
{
|
||||
[Fact]
|
||||
public async Task A_freshly_migrated_database_with_only_known_migrations_is_accepted()
|
||||
{
|
||||
await using var target = await RestoreTargetDatabase.CreateAsync(postgres);
|
||||
var options = new DbContextOptionsBuilder<KnowledgeHubDbContext>()
|
||||
.UseNpgsql(target.ConnectionString, npgsql => npgsql.MigrationsAssembly(typeof(KnowledgeHubDbContext).Assembly.GetName().Name))
|
||||
.UseSnakeCaseNamingConvention()
|
||||
.Options;
|
||||
await using var db = new KnowledgeHubDbContext(options);
|
||||
|
||||
await SchemaGuard.EnsureCompatibleAsync(db.Database, CancellationToken.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task An_unmigrated_brand_new_database_is_accepted_nothing_can_be_ahead_of_an_empty_history()
|
||||
{
|
||||
var databaseName = $"schema_guard_fresh_{Guid.NewGuid():N}";
|
||||
await using (var admin = new NpgsqlConnection(postgres.AdminConnectionString))
|
||||
{
|
||||
await admin.OpenAsync();
|
||||
await using var create = new NpgsqlCommand($"CREATE DATABASE \"{databaseName}\"", admin);
|
||||
await create.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var connectionString = new NpgsqlConnectionStringBuilder(postgres.AdminConnectionString) { Database = databaseName }.ConnectionString;
|
||||
var options = new DbContextOptionsBuilder<KnowledgeHubDbContext>()
|
||||
.UseNpgsql(connectionString, npgsql => npgsql.MigrationsAssembly(typeof(KnowledgeHubDbContext).Assembly.GetName().Name))
|
||||
.UseSnakeCaseNamingConvention()
|
||||
.Options;
|
||||
await using var db = new KnowledgeHubDbContext(options);
|
||||
|
||||
// No exception, even though the migrations-history table does not exist yet.
|
||||
await SchemaGuard.EnsureCompatibleAsync(db.Database, CancellationToken.None);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await using var admin = new NpgsqlConnection(postgres.AdminConnectionString);
|
||||
await admin.OpenAsync();
|
||||
await using var drop = new NpgsqlCommand($"DROP DATABASE IF EXISTS \"{databaseName}\" WITH (FORCE)", admin);
|
||||
await drop.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_database_with_an_applied_migration_unknown_to_this_build_is_refused()
|
||||
{
|
||||
await using var target = await RestoreTargetDatabase.CreateAsync(postgres);
|
||||
|
||||
// Simulate a database that is ahead of this build (e.g. rolled back to an
|
||||
// older image against a newer database) by recording a migration this
|
||||
// assembly has never heard of.
|
||||
await using (var connection = new NpgsqlConnection(target.ConnectionString))
|
||||
{
|
||||
await connection.OpenAsync();
|
||||
await using var insert = new NpgsqlCommand(
|
||||
"INSERT INTO \"public\".\"__EFMigrationsHistory\" (migration_id, product_version) VALUES (@id, @version)",
|
||||
connection);
|
||||
insert.Parameters.AddWithValue("id", "99999999999999_FutureMigrationFromAnUnreleasedBuild");
|
||||
insert.Parameters.AddWithValue("version", "99.0.0");
|
||||
await insert.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
var options = new DbContextOptionsBuilder<KnowledgeHubDbContext>()
|
||||
.UseNpgsql(target.ConnectionString, npgsql => npgsql.MigrationsAssembly(typeof(KnowledgeHubDbContext).Assembly.GetName().Name))
|
||||
.UseSnakeCaseNamingConvention()
|
||||
.Options;
|
||||
await using var db = new KnowledgeHubDbContext(options);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<SchemaDriftException>(
|
||||
() => SchemaGuard.EnsureCompatibleAsync(db.Database, CancellationToken.None));
|
||||
Assert.Contains("FutureMigrationFromAnUnreleasedBuild", exception.Message, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user