using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer.Tests; public sealed class SqlServerHistorianProviderTests { private static SqlServerHistorianProvider Make() => new(new SqlServerHistorianOptions { ConnectionString = "Server=localhost;User Id=sa;Password=x;TrustServerCertificate=True", }); [Fact] public void Name_and_all_six_kinds() { var p = Make(); p.Name.ShouldBe("SqlServer"); p.SupportedKinds.ShouldBe(Enum.GetValues(), ignoreOrder: true); p.SupportedKinds.Count.ShouldBe(6); } [Fact] public void Creates_all_five_seams_without_touching_sql() { var sp = new NullSp(); var p = Make(); p.CreateDataSource(sp).ShouldBeOfType(); p.CreateValueWriter(sp).ShouldBeOfType(); p.CreateAlarmWriter(sp).ShouldBeOfType(); p.CreateProvisioning(sp).ShouldBeOfType(); p.CreateUpdater(sp).ShouldBeOfType(); } [Fact] public void Supported_kinds_are_a_frozen_set() => Make().SupportedKinds.ShouldBeAssignableTo>(); /// /// An invalid schema must not fail provider construction (the host resolves the provider even when no /// consumer is enabled); it surfaces only when a seam is actually built. /// [Fact] public void An_invalid_schema_fails_only_when_a_seam_is_built() { var p = new SqlServerHistorianProvider(new SqlServerHistorianOptions { ConnectionString = "x", Schema = "bad;schema" }); p.Name.ShouldBe("SqlServer"); Should.Throw(() => p.CreateDataSource(new NullSp())); } [Fact] public void Every_seam_shares_one_connection_bootstrapper_and_catalog() { var sp = new NullSp(); var p = Make(); var a = (SqlServerHistorianDataSource)p.CreateDataSource(sp); var b = (SqlServerHistorianDataSource)p.CreateDataSource(sp); Field(a, "_bootstrap").ShouldBeSameAs(Field(b, "_bootstrap")); Field(a, "_catalog").ShouldBeSameAs(Field(b, "_catalog")); } private static object? Field(object o, string name) => o.GetType().GetField(name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)!.GetValue(o); private sealed class NullSp : IServiceProvider { public object? GetService(Type serviceType) => null; } }