544a6ddb77
Resolves the 35 findings from the 2026-06-01 baseline (commit 26ba1c7),
test-first for every behavioral change. +51 tests (331 -> 382 passing, 0 failed).
- Telemetry-001 (HIGH): RedactionEnricher now honours property removal, so a
redactor that drops a key actually scrubs the secret from the event.
- Auth: LDAP validator ValidateOnStart; API-key verify no longer fails on a
best-effort MarkUsed write or a corrupt scopes column (fail-closed); LDAP cert
validation hook; KeyPrefix persistence aligned; README algorithm corrected.
- Health: Akka checks return Degraded (not throw) when the cluster isn't up yet;
GrpcDependencyHealthCheck catch-all; null 'description' rendered; composite
endpoint builder; XML docs shipped.
- Audit: CompositeAuditWriter no longer re-throws OperationCanceledException;
TruncatingAuditRedactor over-redact scrubs Target + safe negative max; options
record; XML docs shipped.
- Configuration: TryAddEnumerable idempotent registration; consistent port
quoting; strict invariant port parsing; XML docs + README packaged.
- Theme: mobile toggle is now CSS-only (no Bootstrap JS); token/CSS hygiene;
XML docs on the public parameter surface.
Shared-contract/spec docs updated where the code was the source of truth
(observability service.instance.id, MapZbMetrics, redactor reach). All changes
additive/back-compatible at v0.1.0. code-reviews bookkeeping follows separately.
93 lines
3.0 KiB
C#
93 lines
3.0 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using ZB.MOM.WW.Configuration;
|
|
|
|
namespace ZB.MOM.WW.Configuration.Tests;
|
|
|
|
/// <summary>
|
|
/// Pins the exact failure-message wording produced by the shared <c>Checks</c> seam through its
|
|
/// public front-ends (<see cref="ConfigPreflight"/> for raw port values, <see cref="ValidationBuilder"/>
|
|
/// for host:port endpoints). Covers Configuration-002 (consistent quoting) and Configuration-003
|
|
/// (strict, culture-invariant port parsing).
|
|
/// </summary>
|
|
public sealed class ChecksWordingTests
|
|
{
|
|
private static IConfiguration Config(string key, string? value) =>
|
|
new ConfigurationBuilder()
|
|
.AddInMemoryCollection(new Dictionary<string, string?> { [key] = value })
|
|
.Build();
|
|
|
|
private static string PortFailure(string? rawValue)
|
|
{
|
|
var pf = ConfigPreflight.For(Config("X:Port", rawValue)).RequirePort("X:Port");
|
|
return Assert.Single(pf.Failures);
|
|
}
|
|
|
|
// Configuration-002: range failure and parse failure must quote the offending value the same way.
|
|
|
|
[Fact]
|
|
public void PortValue_range_failure_quotes_the_value()
|
|
{
|
|
Assert.Equal("X:Port must be between 1 and 65535 (was '0')", PortFailure("0"));
|
|
}
|
|
|
|
[Fact]
|
|
public void PortValue_high_range_failure_quotes_the_value()
|
|
{
|
|
Assert.Equal("X:Port must be between 1 and 65535 (was '70000')", PortFailure("70000"));
|
|
}
|
|
|
|
[Fact]
|
|
public void PortValue_parse_failure_quotes_the_value()
|
|
{
|
|
Assert.Equal("X:Port must be between 1 and 65535 (was 'notaport')", PortFailure("notaport"));
|
|
}
|
|
|
|
[Fact]
|
|
public void PortValue_null_failure_renders_null()
|
|
{
|
|
Assert.Equal("X:Port must be between 1 and 65535 (was 'null')", PortFailure(null));
|
|
}
|
|
|
|
// Configuration-003: strict, culture-invariant parsing rejects sign and surrounding whitespace.
|
|
|
|
[Theory]
|
|
[InlineData("+5000")]
|
|
[InlineData(" 5000")]
|
|
[InlineData("5000 ")]
|
|
[InlineData(" 5000 ")]
|
|
[InlineData("-1")]
|
|
public void PortValue_rejects_loose_inputs(string raw)
|
|
{
|
|
var pf = ConfigPreflight.For(Config("X:Port", raw)).RequirePort("X:Port");
|
|
Assert.False(pf.IsValid);
|
|
Assert.Equal($"X:Port must be between 1 and 65535 (was '{raw}')", Assert.Single(pf.Failures));
|
|
}
|
|
|
|
[Fact]
|
|
public void PortValue_accepts_plain_in_range_port()
|
|
{
|
|
var pf = ConfigPreflight.For(Config("X:Port", "5000")).RequirePort("X:Port");
|
|
Assert.True(pf.IsValid);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("host:+5000")]
|
|
[InlineData("host: 5000")]
|
|
[InlineData("host:5000 ")]
|
|
public void HostPort_rejects_loose_port_inputs(string value)
|
|
{
|
|
var b = new ValidationBuilder();
|
|
b.HostPort(value, "X:Endpoint");
|
|
Assert.False(b.IsValid);
|
|
Assert.Equal($"X:Endpoint must be 'host:port' with port 1-65535 (was '{value}')", Assert.Single(b.Failures));
|
|
}
|
|
|
|
[Fact]
|
|
public void HostPort_accepts_plain_endpoint()
|
|
{
|
|
var b = new ValidationBuilder();
|
|
b.HostPort("host:5000", "X:Endpoint");
|
|
Assert.True(b.IsValid);
|
|
}
|
|
}
|