Files
lmxopcua/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Observability/CapabilityInvokerEnrichmentTests.cs
T
Joseph Doherty bd6c0b4d3d docs: complete XML doc comments via fixdocs (2757 to 131 findings)
Add missing <returns>/<param>/<summary>/<typeparam> tags and clean up
misused inheritdoc across 481 files so the documented API surface is
complete. Documentation-only (zero code lines changed). The 131 remaining
findings are inheritdoc-style warnings deliberately left to preserve
hand-written implementation rationale (plan-decision notes, race-condition
explanations).
2026-06-03 12:34:34 -04:00

80 lines
3.0 KiB
C#

using Serilog;
using Serilog.Core;
using Serilog.Events;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Observability;
[Trait("Category", "Integration")]
public sealed class CapabilityInvokerEnrichmentTests
{
/// <summary>Verifies that InvokerExecute logs inside call site with structured properties.</summary>
/// <returns>A task that represents the asynchronous test.</returns>
[Fact]
public async Task InvokerExecute_LogsInsideCallSite_CarryStructuredProperties()
{
var sink = new InMemorySink();
var logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Sink(sink)
.CreateLogger();
var invoker = new CapabilityInvoker(
new DriverResiliencePipelineBuilder(),
driverInstanceId: "drv-live",
optionsAccessor: () => new DriverResilienceOptions { Tier = DriverTier.A },
driverType: "Modbus");
await invoker.ExecuteAsync(
DriverCapability.Read,
"plc-1",
ct =>
{
logger.Information("inside call site");
return ValueTask.FromResult(42);
},
CancellationToken.None);
var evt = sink.Events.ShouldHaveSingleItem();
evt.Properties["DriverInstanceId"].ToString().ShouldBe("\"drv-live\"");
evt.Properties["DriverType"].ToString().ShouldBe("\"Modbus\"");
evt.Properties["CapabilityName"].ToString().ShouldBe("\"Read\"");
evt.Properties.ShouldContainKey("CorrelationId");
}
/// <summary>Verifies that InvokerExecute does not leak context outside the call site.</summary>
/// <returns>A task that represents the asynchronous test.</returns>
[Fact]
public async Task InvokerExecute_DoesNotLeak_ContextOutsideCallSite()
{
var sink = new InMemorySink();
var logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Sink(sink)
.CreateLogger();
var invoker = new CapabilityInvoker(
new DriverResiliencePipelineBuilder(),
driverInstanceId: "drv-a",
optionsAccessor: () => new DriverResilienceOptions { Tier = DriverTier.A });
await invoker.ExecuteAsync(DriverCapability.Read, "host", _ => ValueTask.FromResult(1), CancellationToken.None);
logger.Information("outside");
var outside = sink.Events.ShouldHaveSingleItem();
outside.Properties.ContainsKey("DriverInstanceId").ShouldBeFalse();
}
private sealed class InMemorySink : ILogEventSink
{
/// <summary>Gets the list of captured log events.</summary>
public List<LogEvent> Events { get; } = [];
/// <summary>Emits a log event by adding it to the captured events list.</summary>
/// <param name="logEvent">The log event to emit.</param>
public void Emit(LogEvent logEvent) => Events.Add(logEvent);
}
}