From 3a049a13a40a77f88c5c265aa58292f0bcbfa0d1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 13 Jul 2026 09:51:31 -0400 Subject: [PATCH] =?UTF-8?q?fix(r2-06):=20RED=20repro=20=E2=80=94=20misconf?= =?UTF-8?q?igured=20ServerHistorian:Endpoint=20should=20fail=20with=20a=20?= =?UTF-8?q?named=20error,=20not=20UriFormatException=20(06/S-11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...erverhistorian-failfast-plan.md.tasks.json | 2 +- .../HistorianGatewayClientAdapterTests.cs | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json b/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json index b50deccb..eb478c82 100644 --- a/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json +++ b/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json @@ -5,7 +5,7 @@ { "id": "T1", "subject": "RED: misconfig repro test — HistorianGatewayClientAdapter.Create with empty/malformed Endpoint must throw a named InvalidOperationException (currently UriFormatException; test MUST fail on current code)", - "status": "pending", + "status": "completed", "blockedBy": [] }, { diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs index 08dcc002..1a86a92e 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; +using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Runtime.Historian; @@ -21,6 +22,38 @@ public sealed class HistorianGatewayClientAdapterTests Assert.NotNull(adapter); } + /// + /// archreview 06/S-11 — an enabled historian with an empty Endpoint must fail with a + /// named, config-key-carrying (defense-in-depth for any + /// caller that bypasses the Host's ServerHistorianOptionsValidator), not the raw + /// that new Uri("") throws deep in the factory. Current + /// code throws → this is the failing-first (RED) repro. + /// + [Fact] + public void Create_with_empty_endpoint_throws_named_config_error() + { + var opts = new ServerHistorianOptions { Enabled = true, Endpoint = "", ApiKey = "histgw_x_y" }; + + var ex = Should.Throw( + () => HistorianGatewayClientAdapter.Create(opts, NullLoggerFactory.Instance)); + ex.Message.ShouldContain("ServerHistorian:Endpoint"); + } + + /// + /// archreview 06/S-11 companion — a non-empty but unparseable / non-absolute Endpoint must + /// also fail with the same named , not a raw + /// . RED on current code. + /// + [Fact] + public void Create_with_malformed_endpoint_throws_named_config_error() + { + var opts = new ServerHistorianOptions { Enabled = true, Endpoint = "not a uri", ApiKey = "histgw_x_y" }; + + var ex = Should.Throw( + () => HistorianGatewayClientAdapter.Create(opts, NullLoggerFactory.Instance)); + ex.Message.ShouldContain("ServerHistorian:Endpoint"); + } + [Fact] public void Factory_builds_GatewayHistorianDataSource() {