// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using System.IO;
using GFramework.Core.SourceGenerators.Logging;
using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Logging;
///
/// 验证 在常见日志声明配置下的快照输出保持稳定。
///
[TestFixture]
public class LoggerGeneratorSnapshotTests
{
///
/// 验证默认配置下的类日志字段快照。
///
[Test]
public Task Snapshot_DefaultConfiguration_Class()
{
return RunScenarioAsync(
"DefaultConfiguration_Class",
"[Log]",
"public partial class MyService");
}
///
/// 验证自定义 logger 名称会反映到生成快照。
///
[Test]
public Task Snapshot_CustomName_Class()
{
return RunScenarioAsync(
"CustomName_Class",
"[Log(Name = \"CustomLogger\")]",
"public partial class MyService");
}
///
/// 验证自定义字段名会反映到生成快照。
///
[Test]
public Task Snapshot_CustomFieldName_Class()
{
return RunScenarioAsync(
"CustomFieldName_Class",
"[Log(FieldName = \"MyLogger\")]",
"public partial class MyService");
}
///
/// 验证实例字段模式会反映到生成快照。
///
[Test]
public Task Snapshot_InstanceField_Class()
{
return RunScenarioAsync(
"InstanceField_Class",
"[Log(IsStatic = false)]",
"public partial class MyService");
}
///
/// 验证公共字段可见性会反映到生成快照。
///
[Test]
public Task Snapshot_PublicField_Class()
{
return RunScenarioAsync(
"PublicField_Class",
"[Log(AccessModifier = \"public\")]",
"public partial class MyService");
}
///
/// 验证泛型类声明的日志字段快照。
///
[Test]
public Task Snapshot_GenericClass()
{
return RunScenarioAsync(
"GenericClass",
"[Log]",
"public partial class MyService");
}
///
/// 为给定场景组装最小测试源并执行快照校验。
///
/// 快照场景名称。
/// 目标类型上的 [Log(...)] 声明。
/// 目标 partial 类型声明。
/// 表示快照测试完成的异步任务。
private static Task RunScenarioAsync(string scenarioName, string logAttributeLine, string classDeclaration)
{
return GeneratorSnapshotTest.RunAsync(
CreateSource(logAttributeLine, classDeclaration),
GetSnapshotFolder(scenarioName));
}
///
/// 生成日志源生成器测试所需的最小宿主源代码。
///
/// 目标类型上的 [Log(...)] 声明。
/// 目标 partial 类型声明。
/// 可直接送入快照测试的完整源码字符串。
private static string CreateSource(string logAttributeLine, string classDeclaration)
{
return string.Join(
$"{Environment.NewLine}{Environment.NewLine}",
CreateLoggingAttributeSource(),
CreateLoggingContractsSource(),
CreateLoggingRuntimeSource(),
CreateTestAppSource(logAttributeLine, classDeclaration));
}
///
/// 生成日志测试使用的 attribute 定义源码。
///
/// 包含 LogAttribute 的源码片段。
private static string CreateLoggingAttributeSource()
{
return """
using System;
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
{
[AttributeUsage(AttributeTargets.Class)]
public sealed class LogAttribute : Attribute
{
public string Name { get; set; }
public string FieldName { get; set; }
public string AccessModifier { get; set; }
public bool IsStatic { get; set; } = true;
}
}
""";
}
///
/// 生成日志抽象契约源码,供测试编译图引用。
///
/// 包含 ILogger 的源码片段。
private static string CreateLoggingContractsSource()
{
return """
namespace GFramework.Core.Abstractions.Logging
{
public interface ILogger
{
void Info(string message);
void Error(string message);
void Warn(string message);
void Debug(string message);
void Trace(string message);
void Fatal(string message);
}
}
""";
}
///
/// 生成最小运行时宿主源码,供生成器解析 logger provider 依赖。
///
/// 包含 provider 与 mock logger 的源码片段。
private static string CreateLoggingRuntimeSource()
{
return """
namespace GFramework.Core.Logging
{
using GFramework.Core.Abstractions.Logging;
public static class LoggerFactoryResolver
{
public static ILoggerProvider Provider { get; set; }
public static ILoggerProvider CreateLogger(string name)
{
return Provider ?? new MockLoggerProvider();
}
}
public interface ILoggerProvider
{
ILogger CreateLogger(string name);
}
internal class MockLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string name)
{
return new MockLogger(name);
}
}
internal class MockLogger : ILogger
{
private readonly string _name;
public MockLogger(string name)
{
_name = name;
}
public void Info(string message) { }
public void Error(string message) { }
public void Warn(string message) { }
public void Debug(string message) { }
public void Trace(string message) { }
public void Fatal(string message) { }
}
}
""";
}
///
/// 生成实际承载 [Log] 声明的测试类型源码。
///
/// 目标类型上的 [Log(...)] 声明。
/// 目标 partial 类型声明。
/// 测试应用命名空间下的目标类型源码片段。
private static string CreateTestAppSource(string logAttributeLine, string classDeclaration)
{
return $$"""
namespace TestApp
{
using GFramework.Core.SourceGenerators.Abstractions.Logging;
{{logAttributeLine}}
{{classDeclaration}}
{
}
}
""";
}
///
/// 将运行时测试目录映射回仓库内已提交的日志生成器快照目录。
///
/// 快照场景名称。
/// 场景对应的绝对快照目录。
private static string GetSnapshotFolder(string scenarioName)
{
return Path.GetFullPath(
Path.Combine(
TestContext.CurrentContext.TestDirectory,
"..",
"..",
"..",
"Logging",
"snapshots",
"LoggerGenerator",
scenarioName));
}
}