You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.9 KiB
195 lines
5.9 KiB
using System.Net; |
|
using System.Net.Sockets; |
|
using System.Text; |
|
using Bit.Core.Utilities; |
|
using Microsoft.AspNetCore.Hosting; |
|
using Microsoft.Extensions.Configuration; |
|
using Microsoft.Extensions.DependencyInjection; |
|
using Microsoft.Extensions.Logging; |
|
using NSubstitute; |
|
using Serilog; |
|
using Serilog.Extensions.Logging; |
|
using Xunit; |
|
|
|
namespace Bit.Core.Test.Utilities; |
|
|
|
public class LoggerFactoryExtensionsTests |
|
{ |
|
[Fact] |
|
public void AddSerilog_IsDevelopment_AddsNoProviders() |
|
{ |
|
var providers = GetProviders([], "Development"); |
|
|
|
Assert.Empty(providers); |
|
} |
|
|
|
[Fact] |
|
public void AddSerilog_IsDevelopment_DevLoggingEnabled_AddsSerilog() |
|
{ |
|
var providers = GetProviders(new Dictionary<string, string?> |
|
{ |
|
{ "GlobalSettings:EnableDevLogging", "true" }, |
|
}, "Development"); |
|
|
|
var provider = Assert.Single(providers); |
|
Assert.IsAssignableFrom<SerilogLoggerProvider>(provider); |
|
} |
|
|
|
[Fact] |
|
public void AddSerilog_IsProduction_AddsSerilog() |
|
{ |
|
var providers = GetProviders([]); |
|
|
|
var provider = Assert.Single(providers); |
|
Assert.IsAssignableFrom<SerilogLoggerProvider>(provider); |
|
} |
|
|
|
[Fact] |
|
public async Task AddSerilog_FileLogging_Old_Works() |
|
{ |
|
var tempDir = Directory.CreateTempSubdirectory(); |
|
|
|
var providers = GetProviders(new Dictionary<string, string?> |
|
{ |
|
{ "GlobalSettings:ProjectName", "Test" }, |
|
{ "GlobalSetting:LogDirectoryByProject", "true" }, |
|
{ "GlobalSettings:LogDirectory", tempDir.FullName }, |
|
}); |
|
|
|
var provider = Assert.Single(providers); |
|
Assert.IsAssignableFrom<SerilogLoggerProvider>(provider); |
|
|
|
var logger = provider.CreateLogger("Test"); |
|
logger.LogWarning("This is a test"); |
|
|
|
var logFile = Assert.Single(tempDir.EnumerateFiles("Test/*.txt")); |
|
|
|
var logFileContents = await File.ReadAllTextAsync(logFile.FullName); |
|
|
|
Assert.Contains( |
|
"This is a test", |
|
logFileContents |
|
); |
|
} |
|
|
|
[Fact] |
|
public async Task AddSerilog_FileLogging_New_Works() |
|
{ |
|
var tempDir = Directory.CreateTempSubdirectory(); |
|
|
|
var provider = GetServiceProvider(new Dictionary<string, string?> |
|
{ |
|
{ "Logging:PathFormat", $"{tempDir}/Logs/log-{{Date}}.log" }, |
|
}, "Production"); |
|
|
|
var logger = provider |
|
.GetRequiredService<ILoggerFactory>() |
|
.CreateLogger("Test"); |
|
|
|
logger.LogWarning("This is a test"); |
|
|
|
// Writing to the file is buffered, give it a little time to flush |
|
await Task.Delay(5); |
|
|
|
var logFile = Assert.Single(tempDir.EnumerateFiles("Logs/*.log")); |
|
|
|
var logFileContents = await File.ReadAllTextAsync(logFile.FullName); |
|
|
|
Assert.DoesNotContain( |
|
"This configuration location for file logging has been deprecated.", |
|
logFileContents |
|
); |
|
Assert.Contains( |
|
"This is a test", |
|
logFileContents |
|
); |
|
} |
|
|
|
[Fact(Skip = "Only for local development.")] |
|
public async Task AddSerilog_SyslogConfigured_Warns() |
|
{ |
|
// Setup a fake syslog server |
|
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)); |
|
using var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 25000); |
|
listener.Start(); |
|
|
|
var provider = GetServiceProvider(new Dictionary<string, string?> |
|
{ |
|
{ "GlobalSettings:SysLog:Destination", "tcp://127.0.0.1:25000" }, |
|
{ "GlobalSettings:SiteName", "TestSite" }, |
|
{ "GlobalSettings:ProjectName", "TestProject" }, |
|
}, "Production"); |
|
|
|
var loggerFactory = provider.GetRequiredService<ILoggerFactory>(); |
|
var logger = loggerFactory.CreateLogger("Test"); |
|
|
|
logger.LogWarning("This is a test"); |
|
|
|
// Look in syslog for data |
|
using var socket = await listener.AcceptSocketAsync(cts.Token); |
|
|
|
// This is rather lazy as opposed to implementing smarter syslog message |
|
// reading but thats not what this test about, so instead just give |
|
// the sink time to finish its work in the background |
|
|
|
List<string> messages = []; |
|
|
|
while (true) |
|
{ |
|
var buffer = new byte[1024]; |
|
var received = await socket.ReceiveAsync(buffer, SocketFlags.None, cts.Token); |
|
|
|
if (received == 0) |
|
{ |
|
break; |
|
} |
|
|
|
var response = Encoding.ASCII.GetString(buffer, 0, received); |
|
messages.Add(response); |
|
|
|
if (messages.Count == 2) |
|
{ |
|
break; |
|
} |
|
} |
|
|
|
Assert.Collection( |
|
messages, |
|
(firstMessage) => Assert.Contains("Syslog for logging has been deprecated", firstMessage), |
|
(secondMessage) => Assert.Contains("This is a test", secondMessage) |
|
); |
|
} |
|
|
|
private static IEnumerable<ILoggerProvider> GetProviders(Dictionary<string, string?> initialData, string environment = "Production") |
|
{ |
|
var provider = GetServiceProvider(initialData, environment); |
|
return provider.GetServices<ILoggerProvider>(); |
|
} |
|
|
|
private static IServiceProvider GetServiceProvider(Dictionary<string, string?> initialData, string environment) |
|
{ |
|
var config = new ConfigurationBuilder() |
|
.AddInMemoryCollection(initialData) |
|
.Build(); |
|
|
|
var hostingEnvironment = Substitute.For<IWebHostEnvironment>(); |
|
|
|
hostingEnvironment |
|
.EnvironmentName |
|
.Returns(environment); |
|
|
|
var context = new WebHostBuilderContext |
|
{ |
|
HostingEnvironment = hostingEnvironment, |
|
Configuration = config, |
|
}; |
|
|
|
var services = new ServiceCollection(); |
|
services.AddLogging(builder => |
|
{ |
|
builder.AddSerilog(context); |
|
}); |
|
|
|
return services.BuildServiceProvider(); |
|
} |
|
}
|
|
|