Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Protos/AuditEventProtoTests.cs
T
Joseph Doherty 513fa1aa16 docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)
Comment/XML-doc changes only:
- add summaries to ~10k test methods, fixtures, fakes and helpers
  (+ <param> on theories, <returns> on async Task methods,
  <inheritdoc/> on interface implementations the checker can resolve)
- strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N,
  #NN, Component-0NN) from comments, keeping the explanatory text;
  reword false positives in comments only
- real docs on fakes implementing BCL/library interfaces
  (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime)
- reword the last 5 src/ false positives (CWE-1236, failures-1,
  year-0001, M365)

Only non-comment edits: four one-line nested classes split across lines
so members can carry docs. Build 0 errors / 0 warnings.
2026-10-07 15:05:49 -04:00

130 lines
5.3 KiB
C#

using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ZB.MOM.WW.ScadaBridge.Communication.Grpc;
namespace ZB.MOM.WW.ScadaBridge.Communication.Tests.Protos;
/// <summary>
/// Wire-format round-trip tests for the Audit Log telemetry proto messages
/// (<see cref="AuditEventDto"/>, <see cref="AuditEventBatch"/>, <see cref="IngestAck"/>).
/// Locks the additive contract the site → central audit pipeline depends on.
/// </summary>
public class AuditEventProtoTests
{
/// <summary>Verifies that an <c>AuditEventDto</c> round trip preserves all fields.</summary>
[Fact]
public void AuditEventDto_RoundTrip_PreservesAllFields()
{
var occurredAt = Timestamp.FromDateTimeOffset(
new DateTimeOffset(2026, 5, 20, 10, 15, 30, 123, TimeSpan.Zero));
var original = new AuditEventDto
{
EventId = Guid.NewGuid().ToString(),
OccurredAtUtc = occurredAt,
Channel = "ApiOutbound",
Kind = "ApiCall",
CorrelationId = Guid.NewGuid().ToString(),
SourceSiteId = "site-1",
SourceNode = "node-a",
SourceInstanceId = "Pump01",
SourceScript = "OnDemand",
Actor = "design-key",
Target = "weather-api",
Status = "Delivered",
HttpStatus = 200,
DurationMs = 42,
ErrorMessage = "no error",
ErrorDetail = "stack",
RequestSummary = "GET /weather?city=brisbane",
ResponseSummary = "{ \"temp\": 22.5 }",
PayloadTruncated = true,
Extra = "{ \"retryCount\": 0 }"
};
var bytes = original.ToByteArray();
var deserialized = AuditEventDto.Parser.ParseFrom(bytes);
Assert.Equal(original.EventId, deserialized.EventId);
Assert.Equal(original.OccurredAtUtc, deserialized.OccurredAtUtc);
Assert.Equal(original.Channel, deserialized.Channel);
Assert.Equal(original.Kind, deserialized.Kind);
Assert.Equal(original.CorrelationId, deserialized.CorrelationId);
Assert.Equal(original.SourceSiteId, deserialized.SourceSiteId);
Assert.Equal(original.SourceNode, deserialized.SourceNode);
Assert.Equal(original.SourceInstanceId, deserialized.SourceInstanceId);
Assert.Equal(original.SourceScript, deserialized.SourceScript);
Assert.Equal(original.Actor, deserialized.Actor);
Assert.Equal(original.Target, deserialized.Target);
Assert.Equal(original.Status, deserialized.Status);
Assert.Equal(original.HttpStatus, deserialized.HttpStatus);
Assert.Equal(original.DurationMs, deserialized.DurationMs);
Assert.Equal(original.ErrorMessage, deserialized.ErrorMessage);
Assert.Equal(original.ErrorDetail, deserialized.ErrorDetail);
Assert.Equal(original.RequestSummary, deserialized.RequestSummary);
Assert.Equal(original.ResponseSummary, deserialized.ResponseSummary);
Assert.Equal(original.PayloadTruncated, deserialized.PayloadTruncated);
Assert.Equal(original.Extra, deserialized.Extra);
}
/// <summary>Verifies that an unset nullable integer is absent from the wire encoding.</summary>
[Fact]
public void AuditEventDto_NullableInt_AbsentByDefault_NotIncludedInWire()
{
// Int32Value fields (http_status, duration_ms) are wrapper-typed in proto;
// when unset, the wrapper is absent, not serialized, and deserializes back to null.
var original = new AuditEventDto
{
EventId = Guid.NewGuid().ToString(),
OccurredAtUtc = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
Channel = "Notification",
Kind = "NotifySend",
Status = "Submitted"
};
Assert.Null(original.HttpStatus);
Assert.Null(original.DurationMs);
var bytes = original.ToByteArray();
var deserialized = AuditEventDto.Parser.ParseFrom(bytes);
Assert.Null(deserialized.HttpStatus);
Assert.Null(deserialized.DurationMs);
}
/// <summary>Verifies that an empty <c>AuditEventBatch</c> round-trips to an empty event list.</summary>
[Fact]
public void AuditEventBatch_Empty_RoundTrip_Yields_EmptyEvents()
{
var original = new AuditEventBatch();
Assert.Empty(original.Events);
var bytes = original.ToByteArray();
var deserialized = AuditEventBatch.Parser.ParseFrom(bytes);
Assert.Empty(deserialized.Events);
}
/// <summary>Verifies that an <c>IngestAck</c> preserves its accepted event ids.</summary>
[Fact]
public void IngestAck_PreservesAcceptedEventIds()
{
var id1 = Guid.NewGuid().ToString();
var id2 = Guid.NewGuid().ToString();
var id3 = Guid.NewGuid().ToString();
var original = new IngestAck();
original.AcceptedEventIds.Add(id1);
original.AcceptedEventIds.Add(id2);
original.AcceptedEventIds.Add(id3);
var bytes = original.ToByteArray();
var deserialized = IngestAck.Parser.ParseFrom(bytes);
Assert.Equal(3, deserialized.AcceptedEventIds.Count);
Assert.Equal(id1, deserialized.AcceptedEventIds[0]);
Assert.Equal(id2, deserialized.AcceptedEventIds[1]);
Assert.Equal(id3, deserialized.AcceptedEventIds[2]);
}
}