server(alarms): AlarmFallbackOptions + ForceSubtag/threshold validation (Task 10)
This commit is contained in:
@@ -118,4 +118,181 @@ public sealed class GatewayOptionsValidatorTests
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// AlarmFallbackOptions validation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static AlarmsOptions EnabledAlarmsWithFallback(AlarmFallbackOptions fallback) => new()
|
||||
{
|
||||
Enabled = true,
|
||||
DefaultArea = "Galaxy",
|
||||
Fallback = fallback,
|
||||
};
|
||||
|
||||
private static GatewayOptions CloneWithAlarms(GatewayOptions source, AlarmsOptions alarms)
|
||||
=> new()
|
||||
{
|
||||
Authentication = source.Authentication,
|
||||
Ldap = source.Ldap,
|
||||
Worker = source.Worker,
|
||||
Sessions = source.Sessions,
|
||||
Events = source.Events,
|
||||
Dashboard = source.Dashboard,
|
||||
Protocol = source.Protocol,
|
||||
Alarms = alarms,
|
||||
Tls = source.Tls,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void Validate_Succeeds_WhenAlarmsDisabled_FallbackNotValidated()
|
||||
{
|
||||
// Even an invalid Mode is acceptable when Enabled = false.
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
new AlarmsOptions
|
||||
{
|
||||
Enabled = false,
|
||||
Fallback = new AlarmFallbackOptions { Mode = "InvalidMode" },
|
||||
});
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Succeeds_WhenAlarmsEnabled_DefaultAutoConfig()
|
||||
{
|
||||
// Default AlarmFallbackOptions (Mode="Auto") must pass validation when alarms are enabled.
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions()));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Auto")]
|
||||
[InlineData("ForceAlarmManager")]
|
||||
[InlineData("ForceSubtag")]
|
||||
[InlineData("auto")]
|
||||
[InlineData("FORCESUBTAG")]
|
||||
public void Validate_Succeeds_WhenAlarmsEnabled_RecognisedMode(string mode)
|
||||
{
|
||||
AlarmsOptions alarms = mode.Equals("ForceSubtag", StringComparison.OrdinalIgnoreCase)
|
||||
// ForceSubtag needs either UseGalaxyRepository=true (default) or IncludeAttributes.
|
||||
? EnabledAlarmsWithFallback(new AlarmFallbackOptions { Mode = mode })
|
||||
: EnabledAlarmsWithFallback(new AlarmFallbackOptions { Mode = mode });
|
||||
GatewayOptions options = CloneWithAlarms(ValidOptions(), alarms);
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Fails_WhenAlarmsEnabled_InvalidMode()
|
||||
{
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions { Mode = "InvalidMode" }));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(result.Failures!, f => f.Contains("MxGateway:Alarms:Fallback") && f.Contains("Mode"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Fails_WhenForceSubtag_NoGalaxyRepository_NoIncludes()
|
||||
{
|
||||
// ForceSubtag without galaxy repository and without IncludeAttributes must fail.
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions
|
||||
{
|
||||
Mode = "ForceSubtag",
|
||||
Discovery = new AlarmDiscoveryOptions
|
||||
{
|
||||
UseGalaxyRepository = false,
|
||||
IncludeAttributes = [],
|
||||
},
|
||||
}));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(
|
||||
result.Failures!,
|
||||
f => f.Contains("ForceSubtag") && f.Contains("Discovery"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Succeeds_WhenForceSubtag_NoGalaxyRepository_WithIncludes()
|
||||
{
|
||||
// ForceSubtag without galaxy repository is allowed when IncludeAttributes is non-empty.
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions
|
||||
{
|
||||
Mode = "ForceSubtag",
|
||||
Discovery = new AlarmDiscoveryOptions
|
||||
{
|
||||
UseGalaxyRepository = false,
|
||||
IncludeAttributes = ["attr1"],
|
||||
},
|
||||
}));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Succeeds_WhenForceSubtag_WithGalaxyRepository()
|
||||
{
|
||||
// ForceSubtag + UseGalaxyRepository=true (default) must pass even without IncludeAttributes.
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions
|
||||
{
|
||||
Mode = "ForceSubtag",
|
||||
Discovery = new AlarmDiscoveryOptions { UseGalaxyRepository = true },
|
||||
}));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, nameof(AlarmFallbackOptions.ConsecutiveFailureThreshold))]
|
||||
[InlineData(-1, nameof(AlarmFallbackOptions.ConsecutiveFailureThreshold))]
|
||||
public void Validate_Fails_WhenConsecutiveFailureThresholdBelowOne(int value, string keyPart)
|
||||
{
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions { ConsecutiveFailureThreshold = value }));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(result.Failures!, f => f.Contains(keyPart));
|
||||
_ = keyPart; // suppress unused-param warning
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, nameof(AlarmFallbackOptions.FailbackProbeIntervalSeconds))]
|
||||
[InlineData(-5, nameof(AlarmFallbackOptions.FailbackProbeIntervalSeconds))]
|
||||
public void Validate_Fails_WhenFailbackProbeIntervalSecondsBelowOne(int value, string keyPart)
|
||||
{
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions { FailbackProbeIntervalSeconds = value }));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(result.Failures!, f => f.Contains(keyPart));
|
||||
_ = keyPart;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, nameof(AlarmFallbackOptions.FailbackStableProbes))]
|
||||
[InlineData(-1, nameof(AlarmFallbackOptions.FailbackStableProbes))]
|
||||
public void Validate_Fails_WhenFailbackStableProbesBelowOne(int value, string keyPart)
|
||||
{
|
||||
GatewayOptions options = CloneWithAlarms(
|
||||
ValidOptions(),
|
||||
EnabledAlarmsWithFallback(new AlarmFallbackOptions { FailbackStableProbes = value }));
|
||||
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
|
||||
Assert.True(result.Failed);
|
||||
Assert.Contains(result.Failures!, f => f.Contains(keyPart));
|
||||
_ = keyPart;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user