//
// 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()
{
}
}