Files
git.stella-ops.org/src/Concelier/__Tests/StellaOps.Concelier.ConfigDiff.Tests/ConcelierConfigDiffTests.cs
StellaOps Bot 37e11918e0 save progress
2026-01-06 09:42:20 +02:00

226 lines
7.9 KiB
C#

// <copyright file="ConcelierConfigDiffTests.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under AGPL-3.0-or-later.
// </copyright>
// Sprint: SPRINT_20260105_002_005_TEST_cross_cutting
// Task: CCUT-020
using System.Collections.Immutable;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.TestKit;
using StellaOps.Testing.ConfigDiff;
using Xunit;
namespace StellaOps.Concelier.ConfigDiff.Tests;
/// <summary>
/// Config-diff tests for the Concelier module.
/// Verifies that configuration changes produce only expected behavioral deltas.
/// </summary>
[Trait("Category", TestCategories.ConfigDiff)]
[Trait("Category", TestCategories.Integration)]
[Trait("BlastRadius", TestCategories.BlastRadius.Advisories)]
public class ConcelierConfigDiffTests : ConfigDiffTestBase
{
/// <summary>
/// Initializes a new instance of the <see cref="ConcelierConfigDiffTests"/> class.
/// </summary>
public ConcelierConfigDiffTests()
: base(
new ConfigDiffTestConfig(StrictMode: true),
NullLogger.Instance)
{
}
/// <summary>
/// Verifies that changing cache timeout only affects cache behavior.
/// </summary>
[Fact]
public async Task ChangingCacheTimeout_OnlyAffectsCacheBehavior()
{
// Arrange
var baselineConfig = new ConcelierTestConfig
{
CacheTimeoutMinutes = 30,
MaxConcurrentDownloads = 10,
RetryCount = 3
};
var changedConfig = baselineConfig with
{
CacheTimeoutMinutes = 60
};
// Act
var result = await TestConfigIsolationAsync(
baselineConfig,
changedConfig,
changedSetting: "CacheTimeoutMinutes",
unrelatedBehaviors:
[
async config => await GetDownloadBehaviorAsync(config),
async config => await GetRetryBehaviorAsync(config),
async config => await GetParseBehaviorAsync(config)
]);
// Assert
result.IsSuccess.Should().BeTrue(
because: "changing cache timeout should not affect other behaviors");
}
/// <summary>
/// Verifies that changing retry count produces expected behavioral delta.
/// </summary>
[Fact]
public async Task ChangingRetryCount_ProducesExpectedDelta()
{
// Arrange
var baselineConfig = new ConcelierTestConfig { RetryCount = 3 };
var changedConfig = new ConcelierTestConfig { RetryCount = 5 };
var expectedDelta = new ConfigDelta(
ChangedBehaviors: ["MaxRetryAttempts", "FailureRecoveryWindow"],
BehaviorDeltas:
[
new BehaviorDelta("MaxRetryAttempts", "3", "5", null),
new BehaviorDelta("FailureRecoveryWindow", "increase", null,
"More retries extend recovery window")
]);
// Act
var result = await TestConfigBehavioralDeltaAsync(
baselineConfig,
changedConfig,
getBehavior: async config => await CaptureRetryBehaviorAsync(config),
computeDelta: ComputeBehaviorSnapshotDelta,
expectedDelta: expectedDelta);
// Assert
result.IsSuccess.Should().BeTrue(
because: "retry count change should produce expected behavioral delta");
}
/// <summary>
/// Verifies that changing max concurrent downloads only affects concurrency.
/// </summary>
[Fact]
public async Task ChangingMaxConcurrentDownloads_OnlyAffectsConcurrency()
{
// Arrange
var baselineConfig = new ConcelierTestConfig { MaxConcurrentDownloads = 5 };
var changedConfig = new ConcelierTestConfig { MaxConcurrentDownloads = 20 };
// Act
var result = await TestConfigIsolationAsync(
baselineConfig,
changedConfig,
changedSetting: "MaxConcurrentDownloads",
unrelatedBehaviors:
[
async config => await GetCacheBehaviorAsync(config),
async config => await GetRetryBehaviorAsync(config),
async config => await GetParseBehaviorAsync(config)
]);
// Assert
result.IsSuccess.Should().BeTrue(
because: "changing concurrency should not affect cache, retry, or parsing");
}
/// <summary>
/// Verifies that enabling strict validation produces expected changes.
/// </summary>
[Fact]
public async Task EnablingStrictValidation_ProducesExpectedDelta()
{
// Arrange
var baselineConfig = new ConcelierTestConfig { StrictValidation = false };
var changedConfig = new ConcelierTestConfig { StrictValidation = true };
var expectedDelta = new ConfigDelta(
ChangedBehaviors: ["ValidationStrictness", "RejectionRate"],
BehaviorDeltas:
[
new BehaviorDelta("ValidationStrictness", "relaxed", "strict", null),
new BehaviorDelta("RejectionRate", "increase", null,
"Strict validation rejects more malformed advisories")
]);
// Act
var result = await TestConfigBehavioralDeltaAsync(
baselineConfig,
changedConfig,
getBehavior: async config => await CaptureValidationBehaviorAsync(config),
computeDelta: ComputeBehaviorSnapshotDelta,
expectedDelta: expectedDelta);
// Assert
result.IsSuccess.Should().BeTrue();
}
// Helper methods to capture behaviors
private static Task<object> GetDownloadBehaviorAsync(ConcelierTestConfig config)
{
return Task.FromResult<object>(new { MaxConcurrent = config.MaxConcurrentDownloads });
}
private static Task<object> GetRetryBehaviorAsync(ConcelierTestConfig config)
{
return Task.FromResult<object>(new { RetryCount = config.RetryCount });
}
private static Task<object> GetCacheBehaviorAsync(ConcelierTestConfig config)
{
return Task.FromResult<object>(new { CacheTimeout = config.CacheTimeoutMinutes });
}
private static Task<object> GetParseBehaviorAsync(ConcelierTestConfig config)
{
return Task.FromResult<object>(new { ParseMode = "standard" });
}
private static Task<BehaviorSnapshot> CaptureRetryBehaviorAsync(ConcelierTestConfig config)
{
var snapshot = new BehaviorSnapshot(
ConfigurationId: $"retry-{config.RetryCount}",
Behaviors:
[
new CapturedBehavior("MaxRetryAttempts", config.RetryCount.ToString(), DateTimeOffset.UtcNow),
new CapturedBehavior("FailureRecoveryWindow",
config.RetryCount > 3 ? "increase" : "standard", DateTimeOffset.UtcNow)
],
CapturedAt: DateTimeOffset.UtcNow);
return Task.FromResult(snapshot);
}
private static Task<BehaviorSnapshot> CaptureValidationBehaviorAsync(ConcelierTestConfig config)
{
var snapshot = new BehaviorSnapshot(
ConfigurationId: $"validation-{config.StrictValidation}",
Behaviors:
[
new CapturedBehavior("ValidationStrictness",
config.StrictValidation ? "strict" : "relaxed", DateTimeOffset.UtcNow),
new CapturedBehavior("RejectionRate",
config.StrictValidation ? "increase" : "standard", DateTimeOffset.UtcNow)
],
CapturedAt: DateTimeOffset.UtcNow);
return Task.FromResult(snapshot);
}
}
/// <summary>
/// Test configuration for Concelier module.
/// </summary>
public sealed record ConcelierTestConfig
{
public int CacheTimeoutMinutes { get; init; } = 30;
public int MaxConcurrentDownloads { get; init; } = 10;
public int RetryCount { get; init; } = 3;
public bool StrictValidation { get; init; } = false;
public TimeSpan RequestTimeout { get; init; } = TimeSpan.FromSeconds(30);
}