e7b485c0a2
#820: SqlServer + QuestDB now serve Part 13 DurationGood / DurationBad from the same Good / Bad region totals TimeWeightedAggregator already computes for PercentGood / PercentBad — reported in milliseconds (OPC UA Duration, the SDK's unit), Uncertain time in neither (Mantis 0006166), same BadNoData / status / Partial rules. AggregateFamilies.Served grows 17 -> 19, so i=11201 and the up-front refusal follow automatically; Gateway still refuses both (explicit served set, unchanged). Client.Shared AggregateType / mapper / CLI gain both. The #796 oracle answers DurationGood through the Good-only subclass as well. QualityMix conformance asserts both directly (Q and QP, hand values, ms, and = PercentGood x interval), replaces the "refused up front" test, and adds Duration* to the forward/reverse/truncated oracle comparisons. #821 (facts only, no decision): SdkAggregateParityTests pins an Uncertain-first late-start interval (QP over [0,20), both directions) against ours (Part 13 Total 163.96, TimeAverage 10.93), the frozen 1.5.378.182 calculators (188.96, 9.448), SDK 2.0.1's stock calculators (188.96, 9.448) and a Good-first control (all 163.96); LiveAggregateLateStartFactsTests pins the same through the booted server's runtime AggregateManager (live AggregateFilter) incl. DurationGood 15000 / PercentGood 75 there vs 8000 / 40 in HistoryRead (#809). QualityMix adds the reverse late-start variant (reverse TW pin + reverse oracle windows). Co-Authored-By: Claude <noreply@anthropic.com>
34 lines
1.8 KiB
C#
34 lines
1.8 KiB
C#
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.Tests;
|
|
|
|
/// <summary>The DB-free part of the former SQL Server integration <c>ProcessedReadTests</c>.</summary>
|
|
public sealed class ProcessedReadTests
|
|
{
|
|
[Fact]
|
|
public void Every_enum_member_is_either_served_or_refused()
|
|
{
|
|
// Nineteen served (#671 added TimeAverage, TimeAverage2, Interpolative and Total2, and moved Total to the
|
|
// time-weighted family; #680 moved PercentGood/PercentBad there too — they are duration-based; #820 added
|
|
// DurationGood/DurationBad, the same region time); anything appended to the enum later falls to the refusal
|
|
// (total default).
|
|
Enum.GetValues<HistoryAggregateType>().Count(a => AggregateFamilies.FamilyOf(a) is not null).ShouldBe(19);
|
|
Enum.GetValues<HistoryAggregateType>().Where(a => AggregateFamilies.FamilyOf(a) == AggregateFamily.TimeWeighted)
|
|
.ShouldBe([HistoryAggregateType.Total, HistoryAggregateType.Interpolative, HistoryAggregateType.TimeAverage,
|
|
HistoryAggregateType.DurationGood, HistoryAggregateType.DurationBad, HistoryAggregateType.PercentGood,
|
|
HistoryAggregateType.PercentBad, HistoryAggregateType.TimeAverage2, HistoryAggregateType.Total2],
|
|
ignoreOrder: true);
|
|
}
|
|
|
|
[Fact]
|
|
public void Served_is_exactly_the_members_with_a_family()
|
|
{
|
|
// #682: the advertised set and the dispatch are one definition — a member is served iff it has a family.
|
|
AggregateFamilies.Served.Count.ShouldBe(19);
|
|
foreach (var a in Enum.GetValues<HistoryAggregateType>())
|
|
AggregateFamilies.Served.Contains(a).ShouldBe(AggregateFamilies.FamilyOf(a) is not null, a.ToString());
|
|
}
|
|
}
|