using System.Text.Json; using Serilog.Events; using YZWater.Core.Models; using YZWater.Core.Services; namespace YZWater.Core.Tests.Services; /// /// 日志级别运行时开关的回归测试。 /// 背景:轮询诊断降到 Debug 之后,如果级别不可调,现场遇到"某个值不对"就没有任何手段 /// 把它临时开回来取证,只能停下来重新发布 —— 降级就变成了丢能力。 /// // 本类会改 LogService.MinimumLevel(静态),必须与同样改它的测试类串行,否则默认值断言偶发失败 [Collection("Serilog minimum level")] public class LogLevelSwitchTests : IDisposable { private readonly LogEventLevel _original = LogService.MinimumLevel; [Fact] public void Default_MinimumLevel_IsInformation() { Assert.Equal(LogEventLevel.Information, _original); } [Fact] public void ApplyMinimumLevel_Debug_TakesEffect() { LogService.ApplyMinimumLevel("Debug"); Assert.Equal(LogEventLevel.Debug, LogService.MinimumLevel); } [Fact] public void ApplyMinimumLevel_IsCaseInsensitive() { LogService.ApplyMinimumLevel("warning"); Assert.Equal(LogEventLevel.Warning, LogService.MinimumLevel); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] [InlineData("banana")] [InlineData("Infos")] public void ApplyMinimumLevel_InvalidValue_KeepsCurrentLevel(string? level) { LogService.ApplyMinimumLevel("Debug"); var before = LogService.MinimumLevel; LogService.ApplyMinimumLevel(level); Assert.Equal(before, LogService.MinimumLevel); } [Theory] [InlineData("Debug", true)] [InlineData("debug", true)] [InlineData("Information", true)] [InlineData("Verbose", true)] [InlineData("Fatal", true)] [InlineData("Trace", false)] // 手改配置文件容易多敲空格,Enum.TryParse 本身容忍首尾空白 —— 这里把它钉住 [InlineData("Debug ", true)] [InlineData(" Debug", true)] public void TryParseLevel_MatchesSerilogVocabulary(string level, bool expected) { Assert.Equal(expected, LogService.TryParseLevel(level, out _)); } [Fact] public void SystemConfig_LogKnobs_DefaultToProductionValues() { var config = new SystemConfig(); Assert.Equal("Information", config.MinimumLogLevel); Assert.Equal(60, config.LogSnapshotIntervalSeconds); } [Fact] public void SystemConfig_LogKnobs_RoundTripThroughJson() { // 现场排障就是改这两行文本,键名必须能被反序列化认出来 const string json = """{"MinimumLogLevel":"Debug","LogSnapshotIntervalSeconds":10}"""; var config = JsonSerializer.Deserialize(json); Assert.Equal("Debug", config?.MinimumLogLevel); Assert.Equal(10, config?.LogSnapshotIntervalSeconds); } [Fact] public void PlcPollingService_SnapshotInterval_DefaultsTo60Seconds() { // 0 会让快照静默关闭,默认值必须是有证据的那一档 Assert.Equal(60, PlcPollingService.Instance.LogSnapshotIntervalSeconds); } public void Dispose() => LogService.ApplyMinimumLevel(_original.ToString()); }