using Microsoft.Extensions.Configuration; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Scripting; using ZB.MOM.WW.OtOpcUa.Host.Configuration; namespace ZB.MOM.WW.OtOpcUa.Host.Tests.Configuration; /// /// Review m-1: the Scripting section binds by the documented key names and is clamped at bind. Each /// configured value differs from the compiled default, so a misspelled key (which the binder would silently /// ignore, falling back to the default) goes red. /// public sealed class ScriptingOptionsBindingTests { private static IConfiguration Config(Dictionary values) => new ConfigurationBuilder().AddInMemoryCollection(values).Build(); [Fact] public void Every_documented_key_binds_to_its_property() { var bound = ScriptingOptionsBinding.Bind(Config(new() { ["Scripting:MaxAllocBytesPerRun"] = "8388608", ["Scripting:QuarantineAfterConsecutiveTimeouts"] = "7", ["Scripting:StuckOrphanQuarantineFactor"] = "4.5", // Sibling keys owned by the script-log pipeline must not disturb the bind. ["Scripting:LogFilePath"] = "logs/x-.log", ["Scripting:LogTopicMinLevel"] = "Warning", }), out var adjustments); adjustments.ShouldBeEmpty(); bound.MaxAllocBytesPerRun.ShouldBe(8L * 1024 * 1024); bound.QuarantineAfterConsecutiveTimeouts.ShouldBe(7); bound.StuckOrphanQuarantineFactor.ShouldBe(4.5); } [Fact] public void Out_of_range_values_are_clamped_at_bind_and_reported() { var bound = ScriptingOptionsBinding.Bind(Config(new() { ["Scripting:StuckOrphanQuarantineFactor"] = "1e300", ["Scripting:MaxAllocBytesPerRun"] = "1024", ["Scripting:QuarantineAfterConsecutiveTimeouts"] = "0", }), out var adjustments); bound.StuckOrphanQuarantineFactor.ShouldBe(ScriptingOptions.MaxStuckOrphanQuarantineFactor); bound.MaxAllocBytesPerRun.ShouldBe(ScriptingOptions.MinMaxAllocBytesPerRun); bound.QuarantineAfterConsecutiveTimeouts.ShouldBe(1); adjustments.Count.ShouldBe(3); } [Fact] public void An_absent_section_yields_the_compiled_defaults() { var bound = ScriptingOptionsBinding.Bind(Config(new()), out var adjustments); adjustments.ShouldBeEmpty(); bound.MaxAllocBytesPerRun.ShouldBe(ScriptingOptions.DefaultMaxAllocBytesPerRun); bound.QuarantineAfterConsecutiveTimeouts.ShouldBe(ScriptingOptions.DefaultQuarantineAfterConsecutiveTimeouts); bound.StuckOrphanQuarantineFactor.ShouldBe(ScriptingOptions.DefaultStuckOrphanQuarantineFactor); } }