Initial curated itworx-knowledge-hub source from 3b1751d0d9dee551aa6994eee0093704dc334817

This commit is contained in:
Public Source Publisher committed 2026-10-01 01:37:37 +02:00
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);
}
}