save progress
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
// <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);
|
||||
}
|
||||
Reference in New Issue
Block a user