using System.Diagnostics; using System.IO; namespace GFramework.Core.Tests.Packaging; /// /// 验证模块级可选 Global Usings 的生成脚本与仓库中的已提交产物保持同步。 /// 该测试用于防止新增模块、命名空间清单或打包声明发生漂移后静默进入仓库。 /// [TestFixture] public class TransitiveGlobalUsingsGenerationTests { /// /// 验证生成脚本的检查模式可以在当前仓库状态下通过。 /// 如果此断言失败,说明清单、生成的 props 文件或 csproj 打包声明至少有一处未同步。 /// [Test] public void GenerateModuleGlobalUsingsScript_CheckMode_Should_Pass() { var repositoryRoot = FindRepositoryRoot(); using var process = StartScriptCheck(repositoryRoot); var standardOutput = process.StandardOutput.ReadToEnd(); var standardError = process.StandardError.ReadToEnd(); process.WaitForExit(); Assert.That( process.ExitCode, Is.EqualTo(0), $"Expected module global usings generation to be up to date.{System.Environment.NewLine}" + $"stdout:{System.Environment.NewLine}{standardOutput}{System.Environment.NewLine}" + $"stderr:{System.Environment.NewLine}{standardError}"); } /// /// 启动生成脚本的检查模式。 /// 该模式不会修改仓库内容,只验证仓库中的生成产物是否已与当前规则对齐。 /// /// 仓库根目录。 /// 已启动的进程实例。 private static Process StartScriptCheck(string repositoryRoot) { var startInfo = new ProcessStartInfo("python3", "scripts/generate-module-global-usings.py --check") { WorkingDirectory = repositoryRoot, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; return Process.Start(startInfo) ?? throw new InvalidOperationException("Failed to start the module global usings generation check."); } /// /// 从测试输出目录向上回溯,定位包含解决方案文件的仓库根目录。 /// /// 仓库根目录绝对路径。 private static string FindRepositoryRoot() { var currentDirectory = new DirectoryInfo(TestContext.CurrentContext.TestDirectory); while (currentDirectory != null) { var solutionPath = Path.Combine(currentDirectory.FullName, "GFramework.sln"); if (File.Exists(solutionPath)) return currentDirectory.FullName; currentDirectory = currentDirectory.Parent; } throw new DirectoryNotFoundException("Could not locate the repository root for GFramework."); } }