using System.Reflection; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Logging; using GFramework.Core.Logging.Appenders; namespace GFramework.Core.Tests.Logging; /// /// 验证可配置 Logger 工厂在配置归一化、级别合并与释放路径上的行为契约。 /// [TestFixture] public sealed class ConfigurableLoggerFactoryTests { /// /// 验证当反序列化结果把集合字段写成 时,工厂会将其归一化为空集合而不是抛出空引用异常。 /// [Test] public void CreateFactory_ShouldNormalizeNullCollectionsFromConfiguration() { var config = LoggingConfigurationLoader.LoadFromJsonString( """ { "minLevel": "Warning", "appenders": null, "loggerLevels": null } """); var factory = LoggingConfigurationLoader.CreateFactory(config); var logger = factory.GetLogger("TestLogger"); Assert.Multiple(() => { Assert.That(config.Appenders, Is.Not.Null); Assert.That(config.LoggerLevels, Is.Not.Null); Assert.That(logger.IsInfoEnabled(), Is.False); Assert.That(logger.IsWarnEnabled(), Is.True); }); } /// /// 验证调用方传入的默认最小级别会作为配置级别的下限参与最终 logger 级别计算。 /// [Test] public void GetLogger_ShouldHonorStricterCallerMinLevelWhenNoOverrideMatches() { var config = LoggingConfigurationLoader.LoadFromJsonString( """ { "minLevel": "Info", "appenders": [ { "type": "Console", "formatter": "Default", "useColors": false } ] } """); var factory = LoggingConfigurationLoader.CreateFactory(config); var logger = factory.GetLogger("TestLogger", LogLevel.Warning); Assert.Multiple(() => { Assert.That(logger.IsInfoEnabled(), Is.False); Assert.That(logger.IsWarnEnabled(), Is.True); }); } /// /// 验证工厂释放时会兼容释放未实现 。 /// [Test] public void Dispose_ShouldDisposeAsyncLogAppenderCreatedFromConfiguration() { var config = LoggingConfigurationLoader.LoadFromJsonString( """ { "appenders": [ { "type": "Async", "bufferSize": 8, "innerAppender": { "type": "Console", "formatter": "Default", "useColors": false } } ] } """); var factory = LoggingConfigurationLoader.CreateFactory(config); var logger = factory.GetLogger("AsyncLogger"); var asyncAppender = GetSingleAsyncAppender(factory); logger.Info("dispose-path"); ((IDisposable)factory).Dispose(); Assert.That(asyncAppender.IsCompleted, Is.True); } private static AsyncLogAppender GetSingleAsyncAppender(ILoggerFactory factory) { var appendersField = factory.GetType().GetField("_appenders", BindingFlags.Instance | BindingFlags.NonPublic); Assert.That(appendersField, Is.Not.Null); var appenders = appendersField!.GetValue(factory) as ILogAppender[]; Assert.That(appenders, Is.Not.Null); Assert.That(appenders, Has.Length.EqualTo(1)); Assert.That(appenders![0], Is.TypeOf()); return (AsyncLogAppender)appenders[0]; } }