// // XUnitLogger.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Text; using Microsoft.Extensions.Logging; using Xunit.Abstractions; namespace NosSmooth.Game.Tests.Helpers; /// /// X unit logger. /// internal class XUnitLogger : ILogger { private readonly ITestOutputHelper _testOutputHelper; private readonly string _categoryName; private readonly LoggerExternalScopeProvider _scopeProvider; /// /// Creates a logger for the given test output. /// /// The test output helper. /// A logger. public static ILogger CreateLogger(ITestOutputHelper testOutputHelper) => new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider(), string.Empty); /// /// Creates a logger for the given test output. /// /// The test output helper. /// The type to create logger for. /// A logger. public static ILogger CreateLogger(ITestOutputHelper testOutputHelper) => new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider()); /// /// Initializes a new instance of the class. /// /// The test output helper. /// The scope provider. /// The category name. public XUnitLogger (ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider, string categoryName) { _testOutputHelper = testOutputHelper; _scopeProvider = scopeProvider; _categoryName = categoryName; } /// public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; /// public IDisposable? BeginScope(TState state) where TState : notnull { return _scopeProvider.Push(state); } /// public void Log ( LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter ) { var sb = new StringBuilder(); sb.Append(GetLogLevelString(logLevel)) .Append(" [").Append(_categoryName).Append("] ") .Append(formatter(state, exception)); if (exception != null) { sb.Append('\n').Append(exception); } // Append scopes _scopeProvider.ForEachScope ( (scope, state) => { state.Append("\n => "); state.Append(scope); }, sb ); _testOutputHelper.WriteLine(sb.ToString()); } private static string GetLogLevelString(LogLevel logLevel) { return logLevel switch { LogLevel.Trace => "trce", LogLevel.Debug => "dbug", LogLevel.Information => "info", LogLevel.Warning => "warn", LogLevel.Error => "fail", LogLevel.Critical => "crit", _ => throw new ArgumentOutOfRangeException(nameof(logLevel)) }; } } /// /// A xunit logger for specific type. /// /// The type the xunit logger is for. internal sealed class XUnitLogger : XUnitLogger, ILogger { /// /// Initializes a new instance of the class. /// /// The test output helper. /// The scope provider. public XUnitLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider) : base(testOutputHelper, scopeProvider, typeof(T).FullName!) { } } /// /// A provider. /// internal sealed class XUnitLoggerProvider : ILoggerProvider { private readonly ITestOutputHelper _testOutputHelper; private readonly LoggerExternalScopeProvider _scopeProvider = new LoggerExternalScopeProvider(); /// /// Initializes a new instance of the class. /// /// The test output helper. public XUnitLoggerProvider(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; } /// public ILogger CreateLogger(string categoryName) { return new XUnitLogger(_testOutputHelper, _scopeProvider, categoryName); } /// public void Dispose() { } }