Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling.
- Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options.
- Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation.
- Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios.
- Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling.
- Included tests for UdpTransportOptions to verify default values and modification capabilities.
- Enhanced service registration tests for Udp transport services in the dependency injection container.
This commit is contained in:
master
2025-12-05 19:01:12 +02:00
parent 53508ceccb
commit cc69d332e3
245 changed files with 22440 additions and 27719 deletions

View File

@@ -0,0 +1,165 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace StellaOps.Cryptography;
/// <summary>
/// Service for resolving cryptographic algorithms based on the active compliance profile.
/// </summary>
public sealed class CryptoComplianceService : ICryptoComplianceService
{
private readonly IOptionsMonitor<CryptoComplianceOptions> _options;
private readonly ILogger<CryptoComplianceService> _logger;
public CryptoComplianceService(
IOptionsMonitor<CryptoComplianceOptions> options,
ILogger<CryptoComplianceService>? logger = null)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? NullLogger<CryptoComplianceService>.Instance;
}
/// <summary>
/// Gets the currently active compliance profile.
/// </summary>
public ComplianceProfile ActiveProfile
{
get
{
var opts = _options.CurrentValue;
opts.ApplyEnvironmentOverrides();
return ComplianceProfiles.GetProfile(opts.ProfileId);
}
}
/// <summary>
/// Gets the algorithm for a given purpose based on the active profile.
/// </summary>
/// <param name="purpose">The hash purpose.</param>
/// <returns>The algorithm identifier.</returns>
public string GetAlgorithmForPurpose(string purpose)
{
if (string.IsNullOrWhiteSpace(purpose))
{
throw new ArgumentException("Purpose cannot be null or empty.", nameof(purpose));
}
var opts = _options.CurrentValue;
opts.ApplyEnvironmentOverrides();
// Check for purpose overrides first
if (opts.PurposeOverrides?.TryGetValue(purpose, out var overrideAlgorithm) == true &&
!string.IsNullOrWhiteSpace(overrideAlgorithm))
{
_logger.LogDebug(
"Using purpose override for {Purpose}: {Algorithm} (profile: {Profile})",
purpose, overrideAlgorithm, opts.ProfileId);
return overrideAlgorithm;
}
// Get from active profile
var profile = ComplianceProfiles.GetProfile(opts.ProfileId);
return profile.GetAlgorithmForPurpose(purpose);
}
/// <summary>
/// Gets the hash prefix for a given purpose (e.g., "blake3:", "sha256:").
/// </summary>
/// <param name="purpose">The hash purpose.</param>
/// <returns>The hash prefix string.</returns>
public string GetHashPrefix(string purpose)
{
if (string.IsNullOrWhiteSpace(purpose))
{
throw new ArgumentException("Purpose cannot be null or empty.", nameof(purpose));
}
var profile = ActiveProfile;
return profile.GetHashPrefix(purpose);
}
/// <summary>
/// Validates an algorithm request against the active compliance profile.
/// </summary>
/// <param name="purpose">The hash purpose (or null if unknown).</param>
/// <param name="requestedAlgorithm">The requested algorithm.</param>
/// <exception cref="CryptoComplianceException">
/// Thrown when StrictValidation is enabled and the algorithm is not compliant.
/// </exception>
public void ValidateAlgorithm(string? purpose, string requestedAlgorithm)
{
var opts = _options.CurrentValue;
opts.ApplyEnvironmentOverrides();
var profile = ComplianceProfiles.GetProfile(opts.ProfileId);
// If purpose is specified, check compliance
if (!string.IsNullOrWhiteSpace(purpose))
{
if (!profile.IsCompliant(purpose, requestedAlgorithm))
{
var expectedAlgorithm = profile.GetAlgorithmForPurpose(purpose);
var message = $"Algorithm '{requestedAlgorithm}' is not compliant for purpose '{purpose}' " +
$"in profile '{profile.ProfileId}'. Expected: '{expectedAlgorithm}'.";
if (opts.StrictValidation)
{
_logger.LogError(
"Compliance violation: {Message}",
message);
throw new CryptoComplianceException(message, profile.ProfileId, purpose, requestedAlgorithm, expectedAlgorithm);
}
if (opts.WarnOnNonCompliant)
{
_logger.LogWarning(
"Compliance warning: {Message}",
message);
}
}
}
}
/// <summary>
/// Checks if the given algorithm is compliant for any purpose in the active profile.
/// </summary>
/// <param name="algorithmId">The algorithm to check.</param>
/// <returns>True if the algorithm is used by any purpose in the profile.</returns>
public bool IsAlgorithmCompliant(string algorithmId)
{
var profile = ActiveProfile;
return HashPurpose.All.Any(purpose => profile.IsCompliant(purpose, algorithmId));
}
}
/// <summary>
/// Interface for compliance-aware cryptographic algorithm resolution.
/// </summary>
public interface ICryptoComplianceService
{
/// <summary>
/// Gets the currently active compliance profile.
/// </summary>
ComplianceProfile ActiveProfile { get; }
/// <summary>
/// Gets the algorithm for a given purpose based on the active profile.
/// </summary>
string GetAlgorithmForPurpose(string purpose);
/// <summary>
/// Gets the hash prefix for a given purpose.
/// </summary>
string GetHashPrefix(string purpose);
/// <summary>
/// Validates an algorithm request against the active compliance profile.
/// </summary>
void ValidateAlgorithm(string? purpose, string requestedAlgorithm);
/// <summary>
/// Checks if the given algorithm is compliant for any purpose in the active profile.
/// </summary>
bool IsAlgorithmCompliant(string algorithmId);
}