using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway; using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Recorder; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb; using ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer; using ZB.MOM.WW.OtOpcUa.Host.Configuration; using ZB.MOM.WW.OtOpcUa.Runtime.Historian; namespace ZB.MOM.WW.OtOpcUa.Host.Tests.Configuration; public sealed class HistorianBackendRegistryTests { private static readonly IConfiguration Cfg = new ConfigurationBuilder().Build(); private static ServerHistorianOptions Gateway(string backend = "Gateway") => new() { Backend = backend, Enabled = true, Endpoint = "http://localhost:5222", ApiKey = "histgw_id_secret", UseTls = false, }; [Fact] public void Default_backend_is_Gateway_and_resolves_the_gateway_provider() { new ServerHistorianOptions().Backend.ShouldBe("Gateway"); HistorianBackendRegistry.Resolve(new ServerHistorianOptions(), Cfg).ShouldBeOfType(); } [Theory] [InlineData("gateway")] [InlineData("GATEWAY")] [InlineData("Gateway")] public void Resolve_is_case_insensitive(string name) => HistorianBackendRegistry.Resolve(Gateway(name), Cfg).Name.ShouldBe("Gateway"); [Fact] public void Unknown_backend_throws_naming_the_value_and_the_allowed_names() { var ex = Should.Throw( () => HistorianBackendRegistry.Resolve(Gateway("Nope"), Cfg)); var msg = string.Join(" ", ex.Failures); msg.ShouldContain("Nope"); msg.ShouldContain("Gateway"); msg.ShouldContain("ServerHistorian:Backend"); } [Fact] public void KnownBackends_lists_Gateway() => HistorianBackendRegistry.KnownBackends.ShouldContain("Gateway"); [Fact] public void Gateway_provider_builds_the_same_concrete_seams_Program_used_to_build() { var sp = new ServiceCollection().BuildServiceProvider(); var p = HistorianBackendRegistry.Resolve(Gateway(), Cfg); p.CreateDataSource(sp).ShouldBeOfType(); p.CreateValueWriter(sp).ShouldBeOfType(); p.CreateAlarmWriter(sp).ShouldBeOfType(); p.CreateProvisioning(sp).ShouldBeOfType(); p.CreateUpdater(sp).ShouldBeNull(); } private static IConfiguration SqlCfg() => new ConfigurationBuilder().AddInMemoryCollection(new Dictionary { ["ServerHistorian:SqlServer:ConnectionString"] = "Server=localhost;User Id=sa;Password=x;TrustServerCertificate=True", }).Build(); [Fact] public void SqlServer_backend_resolves_and_builds_the_sql_seams() { var sp = new ServiceCollection().BuildServiceProvider(); var p = HistorianBackendRegistry.Resolve(new ServerHistorianOptions { Backend = "sqlserver", Enabled = true }, SqlCfg()); p.ShouldBeOfType(); HistorianBackendRegistry.KnownBackends.ShouldContain("SqlServer"); p.SupportedKinds.Count.ShouldBe(6); p.SupportedKinds.ShouldContain(HistorianValueKind.String); p.SupportedKinds.ShouldContain(HistorianValueKind.Empty); p.CreateDataSource(sp).ShouldBeOfType(); p.CreateValueWriter(sp).GetType().Name.ShouldBe("SqlServerHistorianValueWriter"); p.CreateAlarmWriter(sp).GetType().Name.ShouldBe("SqlServerAlarmHistorianWriter"); p.CreateProvisioning(sp).GetType().Name.ShouldBe("SqlServerTagProvisioner"); var holder = new HistorianUpdaterHolder(p.CreateUpdater(sp)); holder.Updater.ShouldNotBeNull(); holder.Updater!.GetType().Name.ShouldBe("SqlServerHistorianDataUpdater"); } private static IConfiguration QuestDbCfg() => new ConfigurationBuilder().AddInMemoryCollection(new Dictionary { ["ServerHistorian:QuestDb:ConnectionString"] = "Host=localhost;Port=18812;Username=admin;Password=quest;Database=qdb", ["ServerHistorian:QuestDb:TablePrefix"] = "rig_", }).Build(); [Theory] [InlineData("questdb")] [InlineData("QUESTDB")] [InlineData("QuestDb")] public void QuestDb_backend_resolves_case_insensitively(string name) => HistorianBackendRegistry.Resolve(new ServerHistorianOptions { Backend = name, Enabled = true }, QuestDbCfg()) .ShouldBeOfType().Name.ShouldBe("QuestDb"); [Fact] public void QuestDb_backend_resolves_and_builds_the_questdb_seams() { var sp = new ServiceCollection().BuildServiceProvider(); var p = HistorianBackendRegistry.Resolve(new ServerHistorianOptions { Backend = "questdb", Enabled = true }, QuestDbCfg()); p.ShouldBeOfType(); HistorianBackendRegistry.KnownBackends.ShouldContain("QuestDb"); p.SupportedKinds.Count.ShouldBe(6); p.SupportedKinds.ShouldContain(HistorianValueKind.String); p.SupportedKinds.ShouldContain(HistorianValueKind.Empty); p.CreateDataSource(sp).ShouldBeOfType(); p.CreateValueWriter(sp).GetType().Name.ShouldBe("QuestDbHistorianValueWriter"); p.CreateAlarmWriter(sp).GetType().Name.ShouldBe("QuestDbAlarmHistorianWriter"); p.CreateProvisioning(sp).GetType().Name.ShouldBe("QuestDbTagProvisioner"); var holder = new HistorianUpdaterHolder(p.CreateUpdater(sp)); holder.Updater.ShouldNotBeNull(); holder.Updater!.GetType().Name.ShouldBe("QuestDbHistorianDataUpdater"); } [Fact] public void BindQuestDb_reads_the_QuestDb_section() { var o = HistorianBackendRegistry.BindQuestDb(QuestDbCfg()); o.ConnectionString.ShouldContain("Port=18812"); o.TablePrefix.ShouldBe("rig_"); } }