using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; // HistoryAggregateType using ZB.MOM.WW.HistorianGateway.Contracts.Grpc; // RetrievalMode using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping; namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests.Mapping; public sealed class AggregateModeMapperTests { [Theory] [InlineData(HistoryAggregateType.TimeAverage, RetrievalMode.TimeWeightedAverage)] [InlineData(HistoryAggregateType.Total, RetrievalMode.Integral)] public void Maps_each_aggregate(HistoryAggregateType a, RetrievalMode expected) => Assert.Equal(expected, AggregateModeMapper.ToRetrievalMode(a)); [Fact] // matrix guard: every member is either mapped or explicitly reported as not supported public void Every_aggregate_member_is_mapped_or_reports_not_supported() { var original = new[] { HistoryAggregateType.Total, HistoryAggregateType.TimeAverage }; Assert.Equal(original.OrderBy(a => a), AggregateModeMapper.NativeAggregates.OrderBy(a => a)); foreach (var a in Enum.GetValues()) { if (original.Contains(a)) _ = AggregateModeMapper.ToRetrievalMode(a); else Assert.Throws(() => AggregateModeMapper.ToRetrievalMode(a)); } } [Theory] // #679: AVEVA has no arithmetic mean and no sample count; #681: the per-sample aggregates are raw-evaluated, not native [InlineData(HistoryAggregateType.Average)] [InlineData(HistoryAggregateType.Count)] [InlineData(HistoryAggregateType.Minimum)] [InlineData(HistoryAggregateType.Maximum)] public void Per_sample_aggregates_have_no_native_mode(HistoryAggregateType a) => Assert.Throws(() => AggregateModeMapper.ToRetrievalMode(a)); [Fact] // #682/#681: the served (= advertised) set is the native members plus the raw-evaluated per-sample families, // and the data source returns exactly that static public void Served_is_exactly_the_mapped_members_and_the_data_source_declares_it() { foreach (var a in Enum.GetValues()) { var native = AggregateModeMapper.NativeAggregates.Contains(a); var perSample = ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.AggregateFamilies.FamilyOf(a) is ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.AggregateFamily.Simple or ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.AggregateFamily.StartEnd or ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common.AggregateFamily.ActualTime; Assert.Equal(native || perSample, GatewayHistorianDataSource.ServedAggregates.Contains(a)); if (!native) Assert.Throws(() => AggregateModeMapper.ToRetrievalMode(a)); } Assert.Equal(12, GatewayHistorianDataSource.ServedAggregates.Count); var source = new GatewayHistorianDataSource( new FakeHistorianGatewayClient(), Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance); Assert.Same(GatewayHistorianDataSource.ServedAggregates, source.SupportedAggregates); } [Fact] public void Undefined_value_is_a_programming_error_not_a_not_supported() => Assert.Throws(() => AggregateModeMapper.ToRetrievalMode((HistoryAggregateType)9999)); }