fix(core): resolve Low code-review findings (Core-004,008,009,010,011,012)
- Core-004: add ConfigureAwait(false) to DriverHost.RegisterAsync / UnregisterAsync / DisposeAsync. - Core-008: rewrite the BuildAddressSpaceAsync XML doc to correctly name the caller (OpcUaApplicationHost.PopulateAddressSpaces) that owns the per-driver isolation. - Core-009: snapshot DriverResilienceOptions once per non-idempotent write in CapabilityInvoker.ExecuteWriteAsync. - Core-010: switch DriverResilienceOptions.Resolve to TryGetValue with a diagnostic error message when a tier table is missing a capability. - Core-011: add an optional diagnostic callback to PermissionTrieBuilder so production callers can surface scope-path mismatches. - Core-012: correct the stale WedgeDetector ctor summary and add the Reconnecting row to DriverHealthReport's state matrix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -67,4 +67,53 @@ public sealed class DriverHealthReportTests
|
||||
{
|
||||
DriverHealthReport.HttpStatus(verdict).ShouldBe(expected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core-012 regression: <see cref="DriverState.Reconnecting"/> must aggregate to
|
||||
/// <see cref="ReadinessVerdict.Degraded"/> — the doc remarks state matrix lists this
|
||||
/// mapping (after the Core-012 doc fix that added the Reconnecting row).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Any_Reconnecting_WithoutFaultedOrNotReady_IsDegraded()
|
||||
{
|
||||
var verdict = DriverHealthReport.Aggregate([
|
||||
new DriverHealthSnapshot("a", DriverState.Healthy),
|
||||
new DriverHealthSnapshot("b", DriverState.Reconnecting),
|
||||
]);
|
||||
verdict.ShouldBe(ReadinessVerdict.Degraded,
|
||||
"Reconnecting = driver alive but not serving live data → /readyz stays 200 while operators see the affected driver in the body");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core-012 regression: assert the XML <c><remarks></c> on
|
||||
/// <see cref="DriverHealthReport"/> names <see cref="DriverState.Reconnecting"/> in its
|
||||
/// state matrix. Catches a future doc-drift if someone re-aliases Reconnecting without
|
||||
/// updating the matrix.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Doc_State_Matrix_Includes_Reconnecting()
|
||||
{
|
||||
var xmlPath = Path.Combine(
|
||||
AppContext.BaseDirectory,
|
||||
"ZB.MOM.WW.OtOpcUa.Core.xml");
|
||||
File.Exists(xmlPath).ShouldBeTrue($"expected XML doc file at {xmlPath}");
|
||||
|
||||
var content = File.ReadAllText(xmlPath);
|
||||
var driverHealthReportRemarks = ExtractRemarksFor(content, "T:ZB.MOM.WW.OtOpcUa.Core.Observability.DriverHealthReport");
|
||||
|
||||
driverHealthReportRemarks.ShouldContain("Reconnecting");
|
||||
}
|
||||
|
||||
private static string ExtractRemarksFor(string xml, string member)
|
||||
{
|
||||
var memberStart = xml.IndexOf($"<member name=\"{member}\"", StringComparison.Ordinal);
|
||||
if (memberStart < 0) return string.Empty;
|
||||
var memberEnd = xml.IndexOf("</member>", memberStart, StringComparison.Ordinal);
|
||||
if (memberEnd < 0) return string.Empty;
|
||||
var slice = xml.Substring(memberStart, memberEnd - memberStart);
|
||||
var remarksStart = slice.IndexOf("<remarks>", StringComparison.Ordinal);
|
||||
if (remarksStart < 0) return string.Empty;
|
||||
var remarksEnd = slice.IndexOf("</remarks>", remarksStart, StringComparison.Ordinal);
|
||||
return remarksEnd < 0 ? string.Empty : slice.Substring(remarksStart, remarksEnd - remarksStart);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user