diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs index f2045ad3..86f01098 100644 --- a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs @@ -1133,6 +1133,26 @@ public class YamlConfigLoaderTests } } + /// + /// 验证热重载会在启动前拒绝负的防抖延迟,避免后台延迟任务才暴露参数错误。 + /// + [Test] + public void EnableHotReload_Should_Throw_When_Debounce_Delay_Is_Negative() + { + var loader = new YamlConfigLoader(_rootPath); + var registry = new ConfigRegistry(); + + var exception = Assert.Throws(() => + loader.EnableHotReload( + registry, + new YamlConfigHotReloadOptions + { + DebounceDelay = TimeSpan.FromMilliseconds(-1) + })); + + Assert.That(exception!.ParamName, Is.EqualTo("options")); + } + /// /// 验证热重载失败时会保留旧表状态,并通过失败回调暴露诊断信息。 /// diff --git a/GFramework.Game/Config/YamlConfigLoader.cs b/GFramework.Game/Config/YamlConfigLoader.cs index 491505fd..012caa32 100644 --- a/GFramework.Game/Config/YamlConfigLoader.cs +++ b/GFramework.Game/Config/YamlConfigLoader.cs @@ -97,6 +97,9 @@ public sealed class YamlConfigLoader : IConfigLoader /// 防抖延迟;为空时默认使用 200 毫秒。 /// 用于停止热重载监听的注销句柄。 /// 为空时抛出。 + /// + /// 当显式提供的 小于 时抛出。 + /// public IUnRegister EnableHotReload( IConfigRegistry registry, Action? onTableReloaded = null, @@ -122,12 +125,22 @@ public sealed class YamlConfigLoader : IConfigLoader /// 热重载配置选项;为空时使用默认选项。 /// 用于停止热重载监听的注销句柄。 /// 为空时抛出。 + /// + /// 当 小于 + /// 时抛出。 + /// public IUnRegister EnableHotReload( IConfigRegistry registry, YamlConfigHotReloadOptions? options) { ArgumentNullException.ThrowIfNull(registry); options ??= new YamlConfigHotReloadOptions(); + if (options.DebounceDelay < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException( + nameof(options), + "DebounceDelay must be greater than or equal to zero."); + } return new HotReloadSession( _rootPath, diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs index 9c777f4c..07b3b81c 100644 --- a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs @@ -95,8 +95,13 @@ public class SchemaConfigGeneratorTests /// /// 验证 schema 字段名无法映射为合法 C# 标识符时会直接给出诊断,而不是生成不可编译代码。 /// - [Test] - public void Run_Should_Report_Diagnostic_When_Schema_Key_Maps_To_Invalid_CSharp_Identifier() + /// 会映射为非法 C# 标识符的 schema key。 + /// 当前命名规范化逻辑生成出的非法标识符。 + [TestCase("drop$item", "Drop$item")] + [TestCase("1-phase", "1Phase")] + public void Run_Should_Report_Diagnostic_When_Schema_Key_Maps_To_Invalid_CSharp_Identifier( + string schemaKey, + string generatedIdentifier) { const string source = """ namespace TestApp @@ -107,16 +112,16 @@ public class SchemaConfigGeneratorTests } """; - const string schema = """ - { - "type": "object", - "required": ["id", "drop$item"], - "properties": { - "id": { "type": "integer" }, - "drop$item": { "type": "string" } - } - } - """; + var schema = $$""" + { + "type": "object", + "required": ["id", "{{schemaKey}}"], + "properties": { + "id": { "type": "integer" }, + "{{schemaKey}}": { "type": "string" } + } + } + """; var result = SchemaGeneratorTestDriver.Run( source, @@ -128,8 +133,8 @@ public class SchemaConfigGeneratorTests { Assert.That(diagnostic.Id, Is.EqualTo("GF_ConfigSchema_006")); Assert.That(diagnostic.Severity, Is.EqualTo(DiagnosticSeverity.Error)); - Assert.That(diagnostic.GetMessage(), Does.Contain("drop$item")); - Assert.That(diagnostic.GetMessage(), Does.Contain("Drop$item")); + Assert.That(diagnostic.GetMessage(), Does.Contain(schemaKey)); + Assert.That(diagnostic.GetMessage(), Does.Contain(generatedIdentifier)); }); }