From 58ba6c011e005a6ed2e83c7ec6c65b6290d60802 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:39:32 +0800 Subject: [PATCH] =?UTF-8?q?test(cqrs-tests):=20=E6=94=B6=E6=95=9B=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=99=A8=E6=B3=A8=E5=86=8C=E7=BC=93=E5=AD=98=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 CqrsHandlerRegistrarTests 的缓存元数据用例,拆分装配、断言与 verify helper - 更新 analyzer warning reduction 的 active tracking 与 trace,记录并行 subagent 批次和 645 条根构建基线 --- .../Cqrs/CqrsHandlerRegistrarTests.cs | 148 +++++++++++------- .../analyzer-warning-reduction-tracking.md | 37 +++-- .../analyzer-warning-reduction-trace.md | 36 +++++ 3 files changed, 150 insertions(+), 71 deletions(-) diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs index 8bcdeff3..dcbfbd2a 100644 --- a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs +++ b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs @@ -327,27 +327,7 @@ internal sealed class CqrsHandlerRegistrarTests [Test] public void RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers() { - var generatedAssembly = new Mock(); - generatedAssembly - .SetupGet(static assembly => assembly.FullName) - .Returns("GFramework.Core.Tests.Cqrs.CachedMetadataAssembly, Version=1.0.0.0"); - generatedAssembly - .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false)) - .Returns([new CqrsHandlerRegistryAttribute(typeof(PartialGeneratedNotificationHandlerRegistry))]); - generatedAssembly - .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false)) - .Returns( - [ - new CqrsReflectionFallbackAttribute( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!) - ]); - generatedAssembly - .Setup(static assembly => assembly.GetType( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, - false, - false)) - .Returns(ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType); - + var generatedAssembly = CreateCachedMetadataAssembly(); var firstContainer = new MicrosoftDiContainer(); var secondContainer = new MicrosoftDiContainer(); @@ -356,43 +336,8 @@ internal sealed class CqrsHandlerRegistrarTests firstContainer.Freeze(); secondContainer.Freeze(); - var firstRegistrations = firstContainer.GetAll>() - .Select(static handler => handler.GetType()) - .ToArray(); - var secondRegistrations = secondContainer.GetAll>() - .Select(static handler => handler.GetType()) - .ToArray(); - - Assert.Multiple(() => - { - Assert.That( - firstRegistrations, - Is.EqualTo( - [ - typeof(GeneratedRegistryNotificationHandler), - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType - ])); - Assert.That( - secondRegistrations, - Is.EqualTo( - [ - typeof(GeneratedRegistryNotificationHandler), - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType - ])); - }); - - generatedAssembly.Verify( - static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false), - Times.Once); - generatedAssembly.Verify( - static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false), - Times.Once); - generatedAssembly.Verify( - static assembly => assembly.GetType( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, - false, - false), - Times.Once); + AssertGeneratedRegistryNotificationHandlers(firstContainer, secondContainer); + VerifyCachedMetadataAssemblyLookups(generatedAssembly); } /// @@ -526,6 +471,93 @@ internal sealed class CqrsHandlerRegistrarTests ClearCache(GetRegistrarCacheField("SupportedHandlerInterfacesCache")); } + /// + /// 创建一个携带 generated registry 与 reflection fallback 元数据的程序集替身, + /// 用于验证 registrar 是否会跨容器复用程序集级元数据。 + /// + private static Mock CreateCachedMetadataAssembly() + { + var generatedAssembly = new Mock(); + generatedAssembly + .SetupGet(static assembly => assembly.FullName) + .Returns("GFramework.Core.Tests.Cqrs.CachedMetadataAssembly, Version=1.0.0.0"); + generatedAssembly + .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false)) + .Returns([new CqrsHandlerRegistryAttribute(typeof(PartialGeneratedNotificationHandlerRegistry))]); + generatedAssembly + .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false)) + .Returns( + [ + new CqrsReflectionFallbackAttribute( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!) + ]); + generatedAssembly + .Setup(static assembly => assembly.GetType( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, + false, + false)) + .Returns(ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType); + return generatedAssembly; + } + + /// + /// 断言两个容器都获得了相同的 generated-registry 与 reflection-fallback 处理器集合。 + /// + private static void AssertGeneratedRegistryNotificationHandlers( + MicrosoftDiContainer firstContainer, + MicrosoftDiContainer secondContainer) + { + var firstRegistrations = GetGeneratedRegistryNotificationHandlerTypes(firstContainer); + var secondRegistrations = GetGeneratedRegistryNotificationHandlerTypes(secondContainer); + + Assert.Multiple(() => + { + Assert.That(firstRegistrations, Is.EqualTo(GetExpectedGeneratedRegistryNotificationHandlerTypes())); + Assert.That(secondRegistrations, Is.EqualTo(GetExpectedGeneratedRegistryNotificationHandlerTypes())); + }); + } + + /// + /// 读取容器中针对 generated notification 的 handler 运行时类型列表。 + /// + private static Type[] GetGeneratedRegistryNotificationHandlerTypes(MicrosoftDiContainer container) + { + return container.GetAll>() + .Select(static handler => handler.GetType()) + .ToArray(); + } + + /// + /// 获取 generated registry 与 reflection fallback 共同组成的预期 handler 顺序。 + /// + private static Type[] GetExpectedGeneratedRegistryNotificationHandlerTypes() + { + return + [ + typeof(GeneratedRegistryNotificationHandler), + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType + ]; + } + + /// + /// 断言程序集级 generated registry / fallback 元数据只会被读取一次。 + /// + private static void VerifyCachedMetadataAssemblyLookups(Mock generatedAssembly) + { + generatedAssembly.Verify( + static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false), + Times.Once); + generatedAssembly.Verify( + static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false), + Times.Once); + generatedAssembly.Verify( + static assembly => assembly.GetType( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, + false, + false), + Times.Once); + } + /// /// 通过反射读取 registrar 的静态缓存对象。 /// diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md index c3bee7f0..2d1d182f 100644 --- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -6,14 +6,14 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-067` -- 当前阶段:`Phase 67` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-068` +- 当前阶段:`Phase 68` - 当前焦点: - - `2026-04-25` 已连续提交 `6a704f3` `fix(analyzer): 固化沙箱外验证并清理测试噪音` 与 `be26640` `test(game-tests): 收敛热重载长方法 warning` - - 当前单文件批次聚焦 `GFramework.Game/Internal/VersionedMigrationRunner.cs`,通过拆分迁移主循环中的职责收敛根构建直接确认的 `MA0051` - - 提权后的直接仓库根基线已从 `652 Warning(s)` 降至 `649 Warning(s)`,说明本轮 runtime 单文件批次继续有效 - - `GFramework.Game` 的直接受影响 `Release` build 当前为 `0 Warning(s)`、`0 Error(s)` - - 本轮只新增 1 个源码唯一文件,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 + - `2026-04-25` 主线程已提交 `1b85b53` `refactor(game): 收敛版本化迁移运行器长方法 warning` + - 并行 subagent 批次已提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` 与 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` + - 当前主线程单文件批次聚焦 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs`,通过拆分缓存元数据测试的装配、断言与 verify helper 收敛根构建直接确认的 `MA0051` + - 提权后的直接仓库根基线已从 `649 Warning(s)` 降至 `645 Warning(s)`,说明本轮 3 文件并行批次继续有效 + - `GFramework.Cqrs.Tests` 与 `GFramework.Core.Tests` 的直接受影响 `Release` build 当前均已通过,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 ## 当前活跃事实 @@ -22,9 +22,12 @@ - `dotnet clean` - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - - 最新结果:成功;`649 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`645 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` + - `GFramework.Core.Tests/Logging/LogContextTests.cs` + - `GFramework.Core.Tests/Logging/LoggerTests.cs` + - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` @@ -34,7 +37,11 @@ - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - 当前批次验证结果: - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 最新主线程结果:成功;`155 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 最新主线程结果:成功;`Passed 1/1` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 @@ -63,12 +70,16 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`649 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 当前结果:成功;`645 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 当前结果:成功;`155 Warning(s)`、`0 Error(s)` +- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 当前结果:成功;`Passed 1/1` +- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` ## 下一步建议 -1. 以当前 `649 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 -2. 下一轮优先从 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051`、`MA0016` 或测试噪音切片,避免过早推高 review 范围。 +1. 以当前 `645 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +2. 下一轮优先从 `GFramework.Cqrs.Tests`、`GFramework.Core.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051`、`MA0016` 或测试噪音切片,避免过早推高 review 范围。 3. 后续凡是沙箱内 `.NET` 验证再次出现无诊断失败、pipe/socket 权限问题或与普通 shell 不一致的结果,直接申请沙箱外重跑同一命令,不再扩散 workaround 型命令噪音。 diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md index 58cc8941..6316d76e 100644 --- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -1,5 +1,41 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-068 + +### 阶段:吸收并行 subagent 小批次,并继续压低仓库根 warning 基线 + +- 触发背景: + - `RP-067` 收尾后,当前分支的仓库根基线已降到 `649 Warning(s)`,branch diff 仅 `9 files` + - 用户明确允许主线程与 subagent 在不冲突的写集上并行推进,因此本轮继续按 `$gframework-batch-boot 50` 规则拆成 3 个单文件切片 +- 接受的委派范围: + - worker `Averroes` + - 文件:`GFramework.Core.Tests/Logging/LogContextTests.cs` + - 目标:收敛 `Push_InAsyncContext_ShouldIsolateAcrossThreads()` 内的 `MA0004` + - 结果:提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` + - worker `Laplace` + - 文件:`GFramework.Core.Tests/Logging/LoggerTests.cs` + - 目标:把 `TestLogger.Logs` 从 `List` 收口为集合抽象以修复 `MA0016` + - 结果:提交 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` +- 主线程实施: + - 本地重构 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` + - 将 `RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers()` 中的 mock 装配、handler 类型读取、预期集合断言与 metadata lookup verify 拆分为具名 helper + - 在吸收两个 worker 提交后,主线程重新执行直接受影响模块与仓库根验证,确保并行切片合并后的真值一致 +- 验证里程碑: + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`155 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 结果:成功;`Passed 1/1` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`645 Warning(s)`、`0 Error(s)`,相较 `RP-067` 的 `649` 再下降 `4` +- 当前结论: + - 并行 3 文件批次已确认有效,且主线程已把 subagent 的负责范围和验证结果收口进 active trace + - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有充足空间,可以继续用“主线程验证 + subagent 并行单文件切片”的节奏推进 + - 下一轮可优先回到 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 的单文件 `MA0051` / `MA0016` 热点 + ## 2026-04-25 — RP-067 ### 阶段:收口 Game runtime 单文件长方法切片,并继续压低根构建 warning 基线