using System.Text.Json; using GFramework.Core.Abstractions.logging; using GFramework.Core.logging.formatters; using NUnit.Framework; namespace GFramework.Core.Tests.logging; /// /// 测试 JsonLogFormatter 的功能和行为 /// [TestFixture] public class JsonLogFormatterTests { [SetUp] public void SetUp() { _formatter = new JsonLogFormatter(); } private JsonLogFormatter _formatter = null!; [Test] public void Format_WithBasicEntry_ShouldProduceValidJson() { var timestamp = new DateTime(2026, 2, 26, 10, 30, 45, 123, DateTimeKind.Utc); var entry = new LogEntry(timestamp, LogLevel.Info, "TestLogger", "Test message", null, null); var result = _formatter.Format(entry); Assert.That(() => JsonDocument.Parse(result), Throws.Nothing); var doc = JsonDocument.Parse(result); Assert.That(doc.RootElement.GetProperty("level").GetString(), Is.EqualTo("INFO")); Assert.That(doc.RootElement.GetProperty("logger").GetString(), Is.EqualTo("TestLogger")); Assert.That(doc.RootElement.GetProperty("message").GetString(), Is.EqualTo("Test message")); } [Test] public void Format_WithException_ShouldIncludeExceptionDetails() { var exception = new InvalidOperationException("Test exception"); var entry = new LogEntry(DateTime.Now, LogLevel.Error, "TestLogger", "Error occurred", exception, null); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); var exceptionObj = doc.RootElement.GetProperty("exception"); Assert.That(exceptionObj.GetProperty("type").GetString(), Does.Contain("InvalidOperationException")); Assert.That(exceptionObj.GetProperty("message").GetString(), Is.EqualTo("Test exception")); Assert.That(exceptionObj.TryGetProperty("stackTrace", out _), Is.True); } [Test] public void Format_WithProperties_ShouldIncludePropertiesObject() { var properties = new Dictionary { ["UserId"] = 12345, ["UserName"] = "TestUser", ["IsActive"] = true }; var entry = new LogEntry(DateTime.Now, LogLevel.Info, "TestLogger", "User action", null, properties); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); var propsObj = doc.RootElement.GetProperty("properties"); Assert.That(propsObj.GetProperty("userId").GetInt32(), Is.EqualTo(12345)); Assert.That(propsObj.GetProperty("userName").GetString(), Is.EqualTo("TestUser")); Assert.That(propsObj.GetProperty("isActive").GetBoolean(), Is.True); } [Test] public void Format_WithNullProperty_ShouldHandleNull() { var properties = new Dictionary { ["Key1"] = null }; var entry = new LogEntry(DateTime.Now, LogLevel.Info, "TestLogger", "Test message", null, properties); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); var propsObj = doc.RootElement.GetProperty("properties"); Assert.That(propsObj.GetProperty("key1").ValueKind, Is.EqualTo(JsonValueKind.Null)); } [Test] public void Format_WithAllLogLevels_ShouldFormatCorrectly() { var levels = new[] { LogLevel.Trace, LogLevel.Debug, LogLevel.Info, LogLevel.Warning, LogLevel.Error, LogLevel.Fatal }; var expectedStrings = new[] { "TRACE", "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; for (int i = 0; i < levels.Length; i++) { var entry = new LogEntry(DateTime.Now, levels[i], "TestLogger", "Test", null, null); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); Assert.That(doc.RootElement.GetProperty("level").GetString(), Is.EqualTo(expectedStrings[i])); } } [Test] public void Format_WithSpecialCharacters_ShouldEscapeCorrectly() { var message = "Test \"quoted\" and \n newline"; var entry = new LogEntry(DateTime.Now, LogLevel.Info, "TestLogger", message, null, null); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); Assert.That(doc.RootElement.GetProperty("message").GetString(), Is.EqualTo(message)); } [Test] public void Format_ShouldUseIso8601Timestamp() { var timestamp = new DateTime(2026, 2, 26, 10, 30, 45, 123, DateTimeKind.Utc); var entry = new LogEntry(timestamp, LogLevel.Info, "TestLogger", "Test", null, null); var result = _formatter.Format(entry); var doc = JsonDocument.Parse(result); var timestampStr = doc.RootElement.GetProperty("timestamp").GetString(); Assert.That(timestampStr, Does.Contain("2026-02-26")); Assert.That(timestampStr, Does.Contain("T")); } [Test] public void Format_WithComplexProperties_ShouldSerializeCorrectly() { var properties = new Dictionary { ["Number"] = 123, ["String"] = "test", ["Boolean"] = true, ["Null"] = null, ["Array"] = new[] { 1, 2, 3 } }; var entry = new LogEntry(DateTime.Now, LogLevel.Info, "TestLogger", "Test", null, properties); var result = _formatter.Format(entry); Assert.That(() => JsonDocument.Parse(result), Throws.Nothing); } }