mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
test(cqrs): 补齐 fallback 元数据回归
- 新增 mixed fallback 禁用多实例 attribute 时的字符串回退覆盖 - 补充 runtime AttributeUsage 变体测试辅助方法 - 更新 CQRS 恢复文档与本轮验证记录
This commit is contained in:
parent
0ac53a4cee
commit
857ce08edb
@ -2870,6 +2870,50 @@ public class CqrsHandlerRegistryGeneratorTests
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当 runtime 同时支持直接 <see cref="Type" /> 与字符串 fallback 元数据、但不允许多个 fallback 特性实例时,
|
||||
/// mixed 场景会整体回退到单个字符串特性,避免生成会违反 runtime attribute usage 的多实例元数据。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void
|
||||
Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes()
|
||||
{
|
||||
var source = ReplaceAttributeUsageForType(
|
||||
AssemblyLevelMixedFallbackMetadataSource,
|
||||
"CqrsReflectionFallbackAttribute",
|
||||
"[AttributeUsage(AttributeTargets.Assembly)]");
|
||||
var execution = ExecuteGenerator(
|
||||
source,
|
||||
allowUnsafe: true);
|
||||
var inputCompilationErrors = execution.InputCompilationDiagnostics
|
||||
.Where(static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||
.ToArray();
|
||||
var generatedCompilationErrors = execution.GeneratedCompilationDiagnostics
|
||||
.Where(static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||
.ToArray();
|
||||
var generatorErrors = execution.GeneratorDiagnostics
|
||||
.Where(static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||
.ToArray();
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(inputCompilationErrors.Select(static diagnostic => diagnostic.Id), Does.Contain("CS0306"));
|
||||
Assert.That(generatedCompilationErrors, Is.Empty);
|
||||
Assert.That(generatorErrors, Is.Empty);
|
||||
Assert.That(execution.GeneratedSources, Has.Length.EqualTo(1));
|
||||
var generatedSource = execution.GeneratedSources[0].content;
|
||||
Assert.That(
|
||||
generatedSource,
|
||||
Does.Contain(
|
||||
"[assembly: global::GFramework.Cqrs.CqrsReflectionFallbackAttribute(\"TestApp.Container+AlphaHandler\", \"TestApp.Container+BetaHandler\")]"));
|
||||
Assert.That(generatedSource, Does.Not.Contain("CqrsReflectionFallbackAttribute(typeof("));
|
||||
Assert.That(
|
||||
CountOccurrences(
|
||||
generatedSource,
|
||||
"[assembly: global::GFramework.Cqrs.CqrsReflectionFallbackAttribute"),
|
||||
Is.EqualTo(1));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当 runtime 暴露 request invoker provider 契约时,生成器会让 generated registry 同时发射
|
||||
/// request invoker 描述符与对应的开放静态 invoker 方法。
|
||||
@ -3425,6 +3469,47 @@ public class CqrsHandlerRegistryGeneratorTests
|
||||
return !char.IsLetterOrDigit(character) && character != '_';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 替换指定测试类型紧邻的 <c>AttributeUsage</c> 声明,用于构造 runtime contract 的 attribute usage 变体。
|
||||
/// </summary>
|
||||
/// <param name="source">原始测试源码。</param>
|
||||
/// <param name="typeName">需要定位的类型名。</param>
|
||||
/// <param name="replacementAttributeUsage">替换后的完整 <c>AttributeUsage</c> 声明。</param>
|
||||
/// <returns>完成 attribute usage 替换后的源码。</returns>
|
||||
private static string ReplaceAttributeUsageForType(
|
||||
string source,
|
||||
string typeName,
|
||||
string replacementAttributeUsage)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
ArgumentNullException.ThrowIfNull(typeName);
|
||||
ArgumentNullException.ThrowIfNull(replacementAttributeUsage);
|
||||
|
||||
var typeIndex = source.IndexOf($"public sealed class {typeName}", StringComparison.Ordinal);
|
||||
if (typeIndex < 0)
|
||||
{
|
||||
throw new InvalidOperationException("The requested type declaration was not found in the generator test input.");
|
||||
}
|
||||
|
||||
const string attributeUsagePrefix = "[AttributeUsage(";
|
||||
var attributeUsageStartIndex = source.LastIndexOf(attributeUsagePrefix, typeIndex, StringComparison.Ordinal);
|
||||
if (attributeUsageStartIndex < 0)
|
||||
{
|
||||
throw new InvalidOperationException("The requested AttributeUsage declaration was not found in the generator test input.");
|
||||
}
|
||||
|
||||
var attributeUsageEndIndex = source.IndexOf(']', attributeUsageStartIndex);
|
||||
if (attributeUsageEndIndex < 0 || attributeUsageEndIndex > typeIndex)
|
||||
{
|
||||
throw new InvalidOperationException("The requested AttributeUsage declaration is malformed.");
|
||||
}
|
||||
|
||||
return source.Remove(
|
||||
attributeUsageStartIndex,
|
||||
attributeUsageEndIndex - attributeUsageStartIndex + 1)
|
||||
.Insert(attributeUsageStartIndex, replacementAttributeUsage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统计生成源码中某个固定片段的出现次数,用于锁定程序集级 fallback 特性的发射个数。
|
||||
/// </summary>
|
||||
|
||||
@ -7,13 +7,14 @@ CQRS 迁移与收敛。
|
||||
|
||||
## 当前恢复点
|
||||
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-077`
|
||||
- 恢复点编号:`CQRS-REWRITE-RP-078`
|
||||
- 当前阶段:`Phase 8`
|
||||
- 当前 PR 锚点:`PR #307`
|
||||
- 当前结论:
|
||||
- `GFramework.Cqrs` 已完成对外部 `Mediator` 的生产级替代,当前主线已从“是否可替代”转向“仓库内部收口与能力深化顺序”
|
||||
- `dispatch/invoker` 生成前移已扩展到 request / stream 路径,当前 `RP-077` 已补齐 request invoker provider gate 与 stream gate 对称的 descriptor / descriptor entry runtime 合同回归
|
||||
- `ai-plan` active 入口现以 `PR #307` 和 `RP-077` 为唯一权威恢复锚点;更早 PR 与阶段细节均以下方归档为准
|
||||
- `dispatch/invoker` 生成前移已扩展到 request / stream 路径,`RP-077` 已补齐 request invoker provider gate 与 stream gate 对称的 descriptor / descriptor entry runtime 合同回归
|
||||
- 当前 `RP-078` 已补齐 mixed fallback metadata 在 runtime 不允许多个 fallback attribute 实例时的单字符串 attribute 回退回归
|
||||
- `ai-plan` active 入口现以 `PR #307` 和 `RP-078` 为唯一权威恢复锚点;更早 PR 与阶段细节均以下方归档为准
|
||||
|
||||
## 当前活跃事实
|
||||
|
||||
@ -44,11 +45,18 @@ CQRS 迁移与收敛。
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行,避免脚本内部 plain `git ls-files` 误判仓库上下文
|
||||
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes"`
|
||||
- 结果:通过,`1/1` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
|
||||
## 下一推荐步骤
|
||||
|
||||
1. 继续处理 `PR #307` 的剩余 review 收尾,优先保持 `ai-plan` active 入口与 trace 的单一锚点一致
|
||||
2. 若继续推进代码切片,优先复核 request / stream invoker provider runtime 合同以外是否还有同类对称测试缺口
|
||||
2. 若继续推进代码切片,优先复核 fallback metadata 与 generated invoker provider 之外是否还有同类 runtime contract gate 回归缺口
|
||||
3. 在进入下一批 runtime / generator 收敛前,保持最小 Release build 或 targeted test 作为权威验证
|
||||
|
||||
## 活跃文档
|
||||
|
||||
@ -62,3 +62,28 @@
|
||||
|
||||
1. 继续使用 `origin/main` 作为 `$gframework-batch-boot 25` 的基线,复算 branch diff 后决定是否还能接下一批
|
||||
2. 若继续推进代码切片,优先查找 request / stream invoker provider runtime 合同之外的同类对称测试缺口
|
||||
|
||||
### 阶段:mixed fallback attribute usage 回归(CQRS-REWRITE-RP-078)
|
||||
|
||||
- 继续沿用 `$gframework-batch-boot 25`,当前 branch diff 仍低于阈值
|
||||
- 复核 fallback metadata runtime contract 后确认:
|
||||
- mixed fallback 在 runtime 允许多个 fallback attribute 实例时已有直接 `Type` + 字符串拆分回归
|
||||
- runtime 同时支持 `params Type[]` / `params string[]` 但不允许多个 fallback attribute 实例时,缺少锁定“整体回退到单个字符串 attribute”的回归
|
||||
- 已补齐:
|
||||
- `Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes`
|
||||
- `ReplaceAttributeUsageForType` 测试辅助方法,用于构造 runtime attribute usage 变体而不复制大型 source fixture
|
||||
|
||||
### 验证(RP-078)
|
||||
|
||||
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes"`
|
||||
- 结果:通过,`1/1` passed
|
||||
- `python3 scripts/license-header.py --check`
|
||||
- 结果:通过
|
||||
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
|
||||
- `git diff --check`
|
||||
- 结果:通过
|
||||
|
||||
### 当前下一步(RP-078)
|
||||
|
||||
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
|
||||
2. 下一批优先查看 fallback metadata 与 generated invoker provider 之外是否还有同类 runtime contract gate 回归缺口
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user