mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 08:44:29 +08:00
- 在 EnumExtensionsGeneratorSnapshotTests.cs 中补充 snapshotFileNameSelector 的 null 分支覆盖,新增默认快照文件名选择器用例及对应快照资产 - 强化 GeneratorSnapshotTest.cs 的快照路径校验,拒绝空白文件名、绝对路径和目录遍历攻击;将辅助器改为通过 Roslyn GeneratorDriver 读取真实生成结果并验证编译,消除仅依赖 TestState.GeneratedSources 导致的空跑风险 - 新增 GeneratorSnapshotTestSecurityTests.cs 安全回归测试,覆盖绝对路径拒绝和目录逃逸防护两个分支 - 将 Priority、Logger、ContextAware 三组生成器测试统一指向仓库内快照目录,并补齐缺失的快照资产以支持现在强制执行的生成验证
581 lines
26 KiB
C#
581 lines
26 KiB
C#
using System.IO;
|
|
using GFramework.Core.SourceGenerators.Logging;
|
|
using GFramework.SourceGenerators.Tests.Core;
|
|
|
|
namespace GFramework.SourceGenerators.Tests.Logging;
|
|
|
|
[TestFixture]
|
|
public class LoggerGeneratorSnapshotTests
|
|
{
|
|
[Test]
|
|
public async Task Snapshot_DefaultConfiguration_Class()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log]
|
|
public partial class MyService
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("DefaultConfiguration_Class"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Snapshot_CustomName_Class()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log(Name = "CustomLogger")]
|
|
public partial class MyService
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("CustomName_Class"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Snapshot_CustomFieldName_Class()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log(FieldName = "MyLogger")]
|
|
public partial class MyService
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("CustomFieldName_Class"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Snapshot_InstanceField_Class()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log(IsStatic = false)]
|
|
public partial class MyService
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("InstanceField_Class"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Snapshot_PublicField_Class()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log(AccessModifier = "public")]
|
|
public partial class MyService
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("PublicField_Class"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Snapshot_GenericClass()
|
|
{
|
|
const string source = """
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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) { }
|
|
}
|
|
}
|
|
|
|
namespace TestApp
|
|
{
|
|
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
|
|
|
[Log]
|
|
public partial class MyService<T>
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
|
source,
|
|
GetSnapshotFolder("GenericClass"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将运行时测试目录映射回仓库内已提交的日志生成器快照目录。
|
|
/// </summary>
|
|
/// <param name="scenarioName">快照场景名称。</param>
|
|
/// <returns>场景对应的绝对快照目录。</returns>
|
|
private static string GetSnapshotFolder(string scenarioName)
|
|
{
|
|
return Path.GetFullPath(
|
|
Path.Combine(
|
|
TestContext.CurrentContext.TestDirectory,
|
|
"..",
|
|
"..",
|
|
"..",
|
|
"Logging",
|
|
"snapshots",
|
|
"LoggerGenerator",
|
|
scenarioName));
|
|
}
|
|
}
|