fix(health-monitoring): resolve HealthMonitoring-013,014,016 — shorter-timeout cadence, options validation, injected TimeProvider; HealthMonitoring-015 left open (cross-module design decision)
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ScadaLink.HealthMonitoring.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// HealthMonitoring-014 regression: <see cref="HealthMonitoringOptions"/> intervals
|
||||
/// are fed straight into <c>new PeriodicTimer(...)</c>, which throws
|
||||
/// <see cref="ArgumentOutOfRangeException"/> for a zero/negative period. A
|
||||
/// misconfigured <c>appsettings.json</c> must be rejected by an
|
||||
/// <see cref="IValidateOptions{TOptions}"/> with a clear, key-naming message
|
||||
/// rather than crashing the hosted service with an opaque exception.
|
||||
/// </summary>
|
||||
public class HealthMonitoringOptionsValidatorTests
|
||||
{
|
||||
private static ValidateOptionsResult Validate(HealthMonitoringOptions options) =>
|
||||
new HealthMonitoringOptionsValidator().Validate(Options.DefaultName, options);
|
||||
|
||||
[Fact]
|
||||
public void DefaultOptions_AreValid()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions());
|
||||
Assert.True(result.Succeeded, result.FailureMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ZeroReportInterval_IsRejected()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions { ReportInterval = TimeSpan.Zero });
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains("ReportInterval", result.FailureMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NegativeReportInterval_IsRejected()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions { ReportInterval = TimeSpan.FromSeconds(-1) });
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains("ReportInterval", result.FailureMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ZeroOfflineTimeout_IsRejected()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions { OfflineTimeout = TimeSpan.Zero });
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains("OfflineTimeout", result.FailureMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ZeroCentralOfflineTimeout_IsRejected()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions { CentralOfflineTimeout = TimeSpan.Zero });
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains("CentralOfflineTimeout", result.FailureMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CentralOfflineTimeout_ShorterThanOfflineTimeout_IsRejected()
|
||||
{
|
||||
var result = Validate(new HealthMonitoringOptions
|
||||
{
|
||||
OfflineTimeout = TimeSpan.FromSeconds(60),
|
||||
CentralOfflineTimeout = TimeSpan.FromSeconds(30)
|
||||
});
|
||||
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains("CentralOfflineTimeout", result.FailureMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user