From 082e808d0dd0bb49f172bfff13f58b58470e630f Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 11 Oct 2026 01:42:22 -0400 Subject: [PATCH] test(historian): pin Uncertain-input degradation (T1 review) Two Sql.Common tests close review finding I-1: an Uncertain NEXT neighbour makes an AtTime interpolation Uncertain, and an Uncertain (non-Bad) sample in a bucket makes the aggregate Uncertain. Each falsified with the reviewer's surviving mutation. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe --- .../AggregateEvaluatorTests.cs | 10 ++++++++++ .../AtTimeEvaluatorTests.cs | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AggregateEvaluatorTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AggregateEvaluatorTests.cs index 4e9270e5..72a4a54b 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AggregateEvaluatorTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AggregateEvaluatorTests.cs @@ -119,4 +119,14 @@ public sealed class AggregateEvaluatorTests AggregateEvaluator.Evaluate(HistoryAggregateType.TimeAverage, RowsA()[0], At(0), Now)); ex.Aggregate.ShouldBe(HistoryAggregateType.TimeAverage); } + + [Fact] + public void An_uncertain_sample_in_a_bucket_degrades_the_aggregate_to_uncertain() + { + // Two usable samples, one Good and one Uncertain, no Bad: the value is computed, the status is Uncertain. + var row = new BucketRow { Total = 2, Usable = 2, Good = 1, Bad = 0, Avg = 15, Min = 10, Max = 20, Sum = 30 }; + var avg = AggregateEvaluator.Evaluate(HistoryAggregateType.Average, row, At(0), Now); + avg.Value.ShouldBe(15d); + avg.StatusCode.ShouldBe(UncertainCalc); + } } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AtTimeEvaluatorTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AtTimeEvaluatorTests.cs index 5ab37704..70dc5a96 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AtTimeEvaluatorTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests/AtTimeEvaluatorTests.cs @@ -106,4 +106,13 @@ public sealed class AtTimeEvaluatorTests r.Value.ShouldBe("a"); r.StatusCode.ShouldBe(Uncertain | 0x402u); } + + [Fact] + public void An_uncertain_next_neighbour_makes_the_interpolation_uncertain() + { + var r = AtTimeEvaluator.Evaluate(At(5), S(0, HistorianValue.FromDouble(10), Good), + S(10, HistorianValue.FromDouble(20), Uncertain), Now, Now); + r.Value.ShouldBe(15d); + r.StatusCode.ShouldBe(UncertainInterpolated); + } }