Frontend gaps fill work. Testing fixes work. Auditing in progress.

This commit is contained in:
StellaOps Bot
2025-12-30 01:22:58 +02:00
parent 1dc4bcbf10
commit 7a5210e2aa
928 changed files with 183942 additions and 3941 deletions

View File

@@ -160,33 +160,43 @@ public sealed class PostgresFixture : IAsyncDisposable
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
// Get all tables in the schema
// Get all non-system tables so hard-coded schemas (e.g., vuln) are also truncated.
await using var getTablesCmd = new NpgsqlCommand(
"""
SELECT table_name FROM information_schema.tables
WHERE table_schema = @schema AND table_type = 'BASE TABLE'
AND table_name != 'schema_migrations';
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_schema NOT IN ('pg_catalog', 'information_schema')
AND table_schema NOT LIKE 'pg_%'
AND table_name != 'schema_migrations';
""",
connection);
getTablesCmd.Parameters.AddWithValue("schema", _schemaName);
var tables = new List<string>();
await using (var reader = await getTablesCmd.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
{
while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
{
tables.Add(reader.GetString(0));
var schema = reader.GetString(0);
var table = reader.GetString(1);
tables.Add($"{QuoteIdentifier(schema)}.{QuoteIdentifier(table)}");
}
}
if (tables.Count == 0) return;
// Truncate all tables
var truncateSql = $"TRUNCATE TABLE {string.Join(", ", tables.Select(t => $"{_schemaName}.{t}"))} CASCADE;";
var truncateSql = $"TRUNCATE TABLE {string.Join(", ", tables)} CASCADE;";
await using var truncateCmd = new NpgsqlCommand(truncateSql, connection);
await truncateCmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
_logger.LogDebug("Truncated {Count} tables in schema {Schema}", tables.Count, _schemaName);
_logger.LogDebug("Truncated {Count} tables across non-system schemas", tables.Count);
}
private static string QuoteIdentifier(string identifier)
{
var escaped = identifier.Replace("\"", "\"\"", StringComparison.Ordinal);
return $"\"{escaped}\"";
}
/// <summary>

View File

@@ -9,11 +9,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FsCheck.Xunit" />
<PackageReference Include="FsCheck.Xunit.v3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StellaOps.Resolver\StellaOps.Resolver.csproj" />
<ProjectReference Include="../StellaOps.TestKit/StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -134,19 +134,19 @@ public abstract class ConnectorLiveSchemaTestBase : IAsyncLifetime
/// </summary>
public IReadOnlyList<FixtureDriftReport> DriftReports => _driftReports.AsReadOnly();
public Task InitializeAsync()
public ValueTask InitializeAsync()
{
foreach (var (key, value) in RequestHeaders)
{
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value);
}
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
public Task DisposeAsync()
public ValueTask DisposeAsync()
{
_httpClient.Dispose();
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
}
@@ -191,3 +191,7 @@ public sealed class LiveTheoryAttribute : TheoryAttribute
}
}
}

View File

@@ -69,12 +69,12 @@ public sealed class PostgresFixture : IAsyncLifetime
/// </summary>
public ushort Port => _container.GetMappedPublicPort(5432);
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
await _container.StartAsync();
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
await _container.DisposeAsync();
}
@@ -336,3 +336,5 @@ public class PostgresCollection : ICollectionFixture<PostgresFixture>
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}

View File

@@ -78,7 +78,7 @@ public sealed class ValkeyFixture : IAsyncLifetime, IDisposable
/// <summary>
/// Initializes the Valkey container asynchronously.
/// </summary>
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
// Use official Redis image (Valkey is Redis-compatible)
// In production deployments, substitute with valkey/valkey image if needed
@@ -191,7 +191,7 @@ public sealed class ValkeyFixture : IAsyncLifetime, IDisposable
/// <summary>
/// Disposes the Valkey container asynchronously.
/// </summary>
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (_connection != null)
{
@@ -263,3 +263,5 @@ public sealed class ValkeyTestSession : IAsyncDisposable
await _fixture.FlushDatabaseAsync(DatabaseIndex);
}
}

View File

@@ -71,9 +71,8 @@ public class WebServiceFixture<TProgram> : WebApplicationFactory<TProgram>, IAsy
return client;
}
public virtual Task InitializeAsync() => Task.CompletedTask;
public virtual ValueTask InitializeAsync() => ValueTask.CompletedTask;
Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask;
}
/// <summary>
@@ -178,3 +177,7 @@ public static class WebServiceTestExtensions
return await client.GetAsync(url);
}
}

View File

@@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<UseAppHost>true</UseAppHost>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
@@ -8,12 +10,11 @@
<Description>Testing infrastructure and utilities for StellaOps</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="xunit" PrivateAssets="all" />
<PackageReference Include="xunit.extensibility.core" PrivateAssets="all" />
<PackageReference Include="xunit.assert" PrivateAssets="all" />
<PackageReference Include="xunit.v3.assert" PrivateAssets="all" />
<PackageReference Include="xunit.v3.core" PrivateAssets="all" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="FsCheck" />
<PackageReference Include="FsCheck.Xunit" PrivateAssets="all" />
<PackageReference Include="FsCheck.Xunit.v3" PrivateAssets="all" />
<PackageReference Include="Testcontainers" />
<PackageReference Include="Testcontainers.PostgreSql" />
<PackageReference Include="Npgsql" />
@@ -26,3 +27,9 @@
<ProjectReference Include="..\StellaOps.Canonical.Json\StellaOps.Canonical.Json.csproj" />
</ItemGroup>
</Project>

View File

@@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FsCheck.Xunit" />
<PackageReference Include="FsCheck.Xunit.v3" />
<PackageReference Include="FluentAssertions" />
</ItemGroup>
@@ -14,4 +14,6 @@
<ProjectReference Include="..\..\StellaOps.Canonicalization\StellaOps.Canonicalization.csproj" />
<ProjectReference Include="../../StellaOps.TestKit/StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -5,9 +5,7 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="Xunit.Abstractions" />
</ItemGroup>
<ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" />

View File

@@ -39,13 +39,13 @@ public sealed class CrossModuleEvidenceLinkingTests : IAsyncLifetime
_output = output;
}
public Task InitializeAsync()
public ValueTask InitializeAsync()
{
_store = _fixture.CreateStore(_tenantId);
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
await _fixture.TruncateAllTablesAsync();
}
@@ -546,3 +546,6 @@ public sealed class CrossModuleEvidenceLinkingTests : IAsyncLifetime
#endregion
}

View File

@@ -34,13 +34,13 @@ public sealed class PostgresEvidenceStoreIntegrationTests : IAsyncLifetime
_output = output;
}
public Task InitializeAsync()
public ValueTask InitializeAsync()
{
_store = _fixture.CreateStore(_tenantId);
return Task.CompletedTask;
return ValueTask.CompletedTask;
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
await _fixture.TruncateAllTablesAsync();
}
@@ -551,3 +551,6 @@ public sealed class PostgresEvidenceStoreIntegrationTests : IAsyncLifetime
#endregion
}

View File

@@ -20,7 +20,7 @@ public sealed class StartupMigrationHostTests : IAsyncLifetime
private string ConnectionString => _container?.GetConnectionString()
?? throw new InvalidOperationException("Container not initialized");
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
_container = new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
@@ -29,7 +29,7 @@ public sealed class StartupMigrationHostTests : IAsyncLifetime
await _container.StartAsync();
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (_container != null)
{
@@ -546,3 +546,6 @@ internal sealed class TestMigrationHost : StartupMigrationHost
{
}
}

View File

@@ -15,7 +15,7 @@ public sealed class PostgresFixtureTests : IAsyncLifetime
{
private PostgreSqlContainer? _container;
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
_container = new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
@@ -24,7 +24,7 @@ public sealed class PostgresFixtureTests : IAsyncLifetime
await _container.StartAsync();
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (_container != null)
{
@@ -104,3 +104,6 @@ public sealed class PostgresFixtureTests : IAsyncLifetime
exists.Should().Be(false);
}
}

View File

@@ -32,7 +32,7 @@ public sealed class MinimalApiBindingIntegrationTests : IAsyncLifetime
};
}
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
// Build a real WebApplication with Minimal APIs
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
@@ -68,7 +68,7 @@ public sealed class MinimalApiBindingIntegrationTests : IAsyncLifetime
NullLogger<AspNetRouterRequestDispatcher>.Instance);
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (_app is not null)
{
@@ -1002,3 +1002,6 @@ public sealed class MinimalApiBindingIntegrationTests : IAsyncLifetime
#endregion
}

View File

@@ -30,7 +30,7 @@ public sealed class StellaRouterBridgeIntegrationTests : IAsyncLifetime
PropertyNameCaseInsensitive = true
};
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
// Build a real WebApplication with the Router bridge
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
@@ -74,7 +74,7 @@ public sealed class StellaRouterBridgeIntegrationTests : IAsyncLifetime
NullLogger<AspNetRouterRequestDispatcher>.Instance);
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (_app is not null)
{
@@ -612,3 +612,6 @@ public sealed class StellaRouterBridgeOptionsValidationTests
Assert.NotNull(provider.GetService<StellaRouterBridgeOptions>());
}
}

View File

@@ -23,7 +23,7 @@ public sealed class EvidenceApiTests : IAsyncLifetime
private Mock<IEvidenceChunkRepository>? _mockChunkRepository;
private Mock<IEvidenceChunker>? _mockChunker;
public async Task InitializeAsync()
public async ValueTask InitializeAsync()
{
_mockChunkRepository = new Mock<IEvidenceChunkRepository>();
_mockChunker = new Mock<IEvidenceChunker>();
@@ -58,7 +58,7 @@ public sealed class EvidenceApiTests : IAsyncLifetime
_client = _host.GetTestClient();
}
public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
_client?.Dispose();
if (_host != null)
@@ -385,3 +385,6 @@ public sealed class EvidenceApiTests : IAsyncLifetime
};
}
}

View File

@@ -35,9 +35,9 @@ public sealed class SignalsTestFactory : WebApplicationFactory<Program>, IAsyncL
});
}
public Task InitializeAsync() => Task.CompletedTask;
public ValueTask InitializeAsync() => ValueTask.CompletedTask;
public new async Task DisposeAsync()
public new async ValueTask DisposeAsync()
{
try
{
@@ -52,3 +52,6 @@ public sealed class SignalsTestFactory : WebApplicationFactory<Program>, IAsyncL
}
}
}

View File

@@ -11,11 +11,13 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="FsCheck" />
<PackageReference Include="FsCheck.Xunit" />
<PackageReference Include="FsCheck.Xunit.v3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\StellaOps.VersionComparison\StellaOps.VersionComparison.csproj" />
<ProjectReference Include="../../StellaOps.TestKit/StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>
</Project>