fix(historian): respect gateway ceilings and history value contracts
This commit is contained in:
+9
-5
@@ -295,12 +295,14 @@ public sealed class NodeManagerHistoryReadEventsTests : IDisposable
|
||||
/// HistoryRead call. The fake source MUST be invoked (proving we reached the bridge) and threw;
|
||||
/// the production catch now sets BOTH errors and results explicitly, so both are asserted here
|
||||
/// rather than relying on the SDK base pre-seeding results[i].</summary>
|
||||
[Fact]
|
||||
public async Task Events_backend_throw_yields_bad_status_and_does_not_escape()
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async Task Events_backend_throw_yields_bad_status_and_does_not_escape(bool communication)
|
||||
{
|
||||
var (host, server) = await BootAsync();
|
||||
var nm = server.NodeManager!;
|
||||
var fake = new RecordingHistorianDataSource { ThrowOnRead = true };
|
||||
var fake = new RecordingHistorianDataSource { ThrowOnRead = !communication, ReadException = communication ? new System.IO.IOException("lost connection") : null };
|
||||
nm.HistorianDataSource = fake;
|
||||
|
||||
const string equipmentId = "eq-boom";
|
||||
@@ -321,10 +323,10 @@ public sealed class NodeManagerHistoryReadEventsTests : IDisposable
|
||||
|
||||
// Authoritative per-node signal: errors[0] must be Bad.
|
||||
ServiceResult.IsBad(errors[0]).ShouldBeTrue();
|
||||
errors[0].StatusCode.Code.ShouldBe(StatusCodes.BadHistoryOperationUnsupported);
|
||||
errors[0].StatusCode.Code.ShouldBe(communication ? StatusCodes.BadNoCommunication : StatusCodes.BadHistoryOperationUnsupported);
|
||||
// The production catch now sets results[0] explicitly — assert it directly (not relying on base seeding).
|
||||
results[0].ShouldNotBeNull();
|
||||
results[0].StatusCode.Code.ShouldBe(StatusCodes.BadHistoryOperationUnsupported);
|
||||
results[0].StatusCode.Code.ShouldBe(communication ? StatusCodes.BadNoCommunication : StatusCodes.BadHistoryOperationUnsupported);
|
||||
// The source WAS entered (proving the override reached the bridge and the throw was swallowed).
|
||||
fake.EventsEntered.ShouldBeTrue();
|
||||
// ThrowOnRead fires before EventsCalled/LastSourceName are set — that's the throw path.
|
||||
@@ -380,6 +382,7 @@ public sealed class NodeManagerHistoryReadEventsTests : IDisposable
|
||||
private sealed class RecordingHistorianDataSource : IHistorianDataSource
|
||||
{
|
||||
public bool ThrowOnRead { get; init; }
|
||||
public Exception? ReadException { get; init; }
|
||||
public HistoricalEventsResult EventsResult { get; set; } =
|
||||
new(Array.Empty<HistoricalEvent>(), null);
|
||||
|
||||
@@ -411,6 +414,7 @@ public sealed class NodeManagerHistoryReadEventsTests : IDisposable
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
EventsEntered = true;
|
||||
if (ReadException is not null) throw ReadException;
|
||||
if (ThrowOnRead) throw new InvalidOperationException("backend boom for events");
|
||||
EventsCalled = true;
|
||||
LastSourceName = sourceName;
|
||||
|
||||
Reference in New Issue
Block a user