Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/Runtime/GatewayGalaxyAlarmFeedLiveTests.cs
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

85 lines
4.3 KiB
C#

using ZB.MOM.WW.MxGateway.Client;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Runtime;
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests.Runtime;
/// <summary>
/// D.1 smoke (alarm-source leg): drives the REAL gateway <c>StreamAlarms</c> feed through the
/// production lmxopcua consumer (<see cref="GatewayGalaxyAlarmFeed"/>) and asserts native alarm
/// transitions — with operator comment, category, original raise time, and the mapped OPC UA
/// severity bucket preserved — reach the driver-side boundary that feeds
/// <c>IAlarmSource.OnAlarmEvent</c>.
/// <para>
/// Skip-gated: runs only when <c>MXGW_ENDPOINT</c> + <c>GALAXY_MXGW_API_KEY</c> are set to a
/// reachable gateway. Captured 2026-05-29 against <c>10.100.0.48:5120</c> — see
/// <c>docs/plans/alarms-d1-smoke-artifact.md</c>. Set <c>D1_SMOKE_OUT</c> to dump the observed
/// transitions to a file for artifact capture.
/// </para>
/// </summary>
[Trait("Category", "Integration")]
public sealed class GatewayGalaxyAlarmFeedLiveTests
{
/// <summary>Verifies that the live gateway delivers native alarm transitions through the consumer.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task Live_gateway_delivers_native_alarm_transitions_through_the_consumer()
{
var endpoint = Environment.GetEnvironmentVariable("MXGW_ENDPOINT");
var apiKey = Environment.GetEnvironmentVariable("GALAXY_MXGW_API_KEY");
if (string.IsNullOrWhiteSpace(endpoint) || string.IsNullOrWhiteSpace(apiKey))
Assert.Skip("Set MXGW_ENDPOINT + GALAXY_MXGW_API_KEY to run the live gateway alarm-feed smoke.");
var client = MxGatewayClient.Create(new MxGatewayClientOptions
{
Endpoint = new Uri(endpoint!, UriKind.Absolute),
ApiKey = apiKey!,
UseTls = false,
ConnectTimeout = TimeSpan.FromSeconds(10),
DefaultCallTimeout = TimeSpan.FromSeconds(30),
StreamTimeout = TimeSpan.FromSeconds(30),
});
var observed = new List<GalaxyAlarmTransition>();
var gotOne = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
// Wire the live client's StreamAlarms method group into the production consumer seam.
await using var feed = new GatewayGalaxyAlarmFeed(client.StreamAlarmsAsync, clientName: "D1Smoke");
feed.OnAlarmTransition += (_, t) =>
{
lock (observed) { observed.Add(t); }
gotOne.TrySetResult(true);
};
feed.Start();
// The stream opens with the active-alarm snapshot, so we expect ≥1 transition promptly.
await Task.WhenAny(gotOne.Task, Task.Delay(TimeSpan.FromSeconds(20), TestContext.Current.CancellationToken));
List<GalaxyAlarmTransition> snapshot;
lock (observed) snapshot = observed.ToList();
snapshot.ShouldNotBeEmpty(
"Live gateway should deliver at least the active-alarm snapshot through the lmxopcua consumer.");
var first = snapshot[0];
first.AlarmFullReference.ShouldNotBeNullOrWhiteSpace();
first.OpcUaSeverity.ShouldBeGreaterThan(0); // severity bucket mapping applied by the consumer
foreach (var t in snapshot.Take(8))
TestContext.Current.SendDiagnosticMessage(
$"{t.TransitionKind,-11} {t.AlarmFullReference} sev={t.OpcUaSeverity}({t.SeverityBucket}) cat={t.Category} comment='{t.OperatorComment}'");
TestContext.Current.SendDiagnosticMessage($"TOTAL consumer transitions observed: {snapshot.Count}");
// Deterministic artifact capture (only when D1_SMOKE_OUT is set).
var outPath = Environment.GetEnvironmentVariable("D1_SMOKE_OUT");
if (!string.IsNullOrWhiteSpace(outPath))
{
var lines = snapshot.Take(50).Select(t =>
$"{t.TransitionKind,-11} {t.AlarmFullReference} | sev={t.OpcUaSeverity}({t.SeverityBucket}) raw={t.RawMxAccessSeverity} | cat={t.Category} | comment='{t.OperatorComment}' | xitionUtc={t.TransitionTimestampUtc:o}");
await File.WriteAllLinesAsync(outPath!,
new[] { $"# consumer transitions observed: {snapshot.Count}" }.Concat(lines),
TestContext.Current.CancellationToken);
}
}
}