Bazel git_repository 集成测试测试数据设计:从归档仓库到规则行为验证

📅 发布时间:2026/9/13 3:29:38
Bazel git_repository 集成测试测试数据设计:从归档仓库到规则行为验证
Bazel git_repository 集成测试测试数据设计从归档仓库到规则行为验证【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel本文以 Bazel 仓库中 src/test/shell/bazel/testdata/README.md 为骨架结合其对应的测试脚本 starlark_git_repository_test.sh 与规则实现 git.bzl系统讲解 Bazel 如何通过一组精心构造的行星主题 Git 测试仓库端到端验证git_repository外部依赖规则的核心行为克隆、submodule、strip_prefix、add_prefix、浅克隆、缓存与重取、错误路径。读完本文你将理解这些.tar.gz与.git_log测试数据的用途、生成与维护方式以及它们如何与测试用例一一对应。一、测试数据是什么四组归档与四份提交日志src/test/shell/bazel/testdata/目录是 Bazel 集成测试的固定测试数据源。README 明确指出以下四个归档文件包含测试用 Git 仓库供git_repositoryworkspace 规则的测试脚本使用归档文件用途对应测试仓库对应的 git log 文件outer-planets-repo.tar.gz含 submodule 的外行星仓库outer-planets.git_logpluto-repo.tar.gz主测试仓库冥王星多 tagpluto.git_logrefetch-repo.tar.gz验证重取refetch行为的仓库refetch.git_logstrip-prefix-repo.tar.gz验证 strip_prefix 目录裁剪的仓库strip-prefix.git_log说明README 中写作strip-prefix.tar.gz而实际仓库中的文件名是strip-prefix-repo.tar.gz请以 testdata/BUILD 与目录实际文件为准。每个归档内部都是一个完整的.git仓库含历史提交、tag、分支而配套的*.git_log文件则是运行git log -p --decorate得到的输出快照用于人工审阅各仓库的历史演进例如核对某个 tag 对应的 commit hash 与文件变更。README 说明这些文件由手动创建 git 仓库后用tar -zcvf打包而来——这正是测试数据可复现、可审计的关键。二、测试数据如何被测试脚本消费BUILD 声明与 set_up 解包2.1 BUILD 中的 filegroup 声明测试数据不是靠路径硬编码被发现的而是通过 src/test/shell/bazel/testdata/BUILD 中的filegroup目标显式暴露给上层测试包filegroup( name git-repos, srcs [ outer-planets-repo.tar.gz, pluto-repo.tar.gz, refetch-repo.tar.gz, strip-prefix-repo.tar.gz, ], visibility [//src/test/shell/bazel:__pkg__], )同时package(default_testonly True)保证这些数据只服务于测试srcs文件组则通过glob([**])全部纳入 Bazel 的 runfiles供测试脚本通过rlocation定位。2.2 set_up在隔离环境中解包测试脚本 starlark_git_repository_test.shREADME 中写作git_repository_test.sh此为规则 Starlark 化后的现名在set_up阶段把四个归档复制到临时目录并解包function set_up() { local repos_dir$TEST_TMPDIR/repos mkdir -p $repos_dir cp $(rlocation io_bazel/src/test/shell/bazel/testdata/pluto-repo.tar.gz) $repos_dir cp $(rlocation io_bazel/src/test/shell/bazel/testdata/outer-planets-repo.tar.gz) $repos_dir cp $(rlocation io_bazel/src/test/shell/bazel/testdata/refetch-repo.tar.gz) $repos_dir cp $(rlocation io_bazel/src/test/shell/bazel/testdata/strip-prefix-repo.tar.gz) $repos_dir cd $repos_dir tar zxf pluto-repo.tar.gz tar zxf outer-planets-repo.tar.gz tar zxf refetch-repo.tar.gz tar zxf strip-prefix-repo.tar.gz ... # Fix environment variables for a hermetic use of git. export GIT_CONFIG_NOSYSTEM1 export GIT_CONFIG_NOGLOBAL1 export HOME export XDG_CONFIG_HOME }解包后的目录直接作为git_repository的remote本地路径形式的远端使用例如$TEST_TMPDIR/repos/pluto。注意对环境变量的处理GIT_CONFIG_NOSYSTEM、GIT_CONFIG_NOGLOBAL与清空HOME、XDG_CONFIG_HOME是为了杜绝开发机上的 git 全局配置污染测试结果保证测试的封闭性hermeticity。每次测试结束时还会调用bazel shutdown以便在 Windows 上安全清理文件。三、pluto 仓库用一条冥王星降级史覆盖多种规则路径pluto-repo.tar.gz是使用频率最高的测试仓库它的历史本身就是一段有趣的行星变更史完整记录在 pluto.git_log 中。三个关键 tag 与 commit 的对应关系均来自 git log 与实际测试调用TagCommit仓库内容对应测试0-initial早期提交仅含info文件内容 Pluto is a planetbuild_file/build_file_content系列1-build52f9a3f87a2dd17ae0e5847bbae9734f09354afd根目录含MODULE.bazel、BUILD、info改为 Pluto is a dwarf planettest_git_repository、add_prefix、strip_prefix_root 等2-subdirdbf9236251a9ea01b7a2eb563ca8e911060fc97c文件被移入pluto/子目录strip_prefix、add_and_strip_prefix3-subdir-bare8753495c2536c9e24fa764f06bf3015758461dd4master 指向删除 BUILD/WORKSPACE 后的裸子目录结构配合build_file的 strip_prefix 测试3.1 最基础按 commit 克隆并构建test_git_repository 用 commit 固定版本通过use_repo_rule在MODULE.bazel中声明外部仓库git_repository use_repo_rule(bazel_tools//tools/build_defs/repo:git.bzl, git_repository) git_repository( name pluto, remote $pluto_repo_dir, commit 52f9a3f87a2dd17ae0e5847bbae9734f09354afd, )然后bazel build //planets:planet-info断言产物内容包含 Pluto is a dwarf planet。值得注意的验证点见 do_git_repository_testgit_repos_count$(find -L $(bazel info output_base)/external/git_repositorypluto -type d -name .git | wc -l) assert_equals 0 $git_repos_count即检查克隆后的外部仓库目录中不存在任何.git元数据——Bazel 不会把整个 Git 历史搬进输出树只会产出干净的源码快照。3.2 strip_prefix裁剪子目录当仓库把源码放在子目录如pluto/时通过strip_prefix把该子目录提升为仓库根。测试 test_git_repository_strip_prefix 固定到2-subdir提交并设置strip_prefix pluto。规则实现 git.bzl 在_clone_or_update_repo中做了层层防御strip_prefix路径必须存在否则报strip_prefix at ... does not exist in repo必须是目录否则报is not a directory不能指向.git等 Git 元数据refers to Git metadata不能通过..或符号链接逃逸检出目录escaped the checkout directory实现上用临时名.bazel_git_strip_prefix及追加_避免冲突先把目标子树改名再删除其余内容、把子树内容提升回根目录。3.3 add_prefix把检出内容下沉到子目录与 strip_prefix 相反add_prefix把仓库内容放到指定前缀目录下如add/a/prefix测试 test_git_repository_add_prefix 验证了这一点。规则侧 git.bzl 的_checkout_path对add_prefix有严格的越界检查若前缀路径逃逸外部仓库根目录例如../git_repositorypluto-victim立即fail(add_prefix ... escaped the base directory ...)。对应测试 test_git_repository_add_prefix_prevent_uproot 预置一个受害目录哨兵文件断言构建失败且哨兵未被破坏。3.4 build_file / build_file_content接管远程 BUILD 定义当远程仓库没有或不想使用自己的 BUILD 文件时可以用本地build_file指向 workspace 内导出的文件需配合exports_files或内联的build_file_content字符串来定义目标。do_git_repository_test_with_build对 pluto 仓库的三个状态0-initial、3-subdir-bare、默认分支分别组合 strip_prefix / add_prefix 进行矩阵测试断言输出分别是 Pluto is a planet 与 Pluto is a dwarf planet。3.5 shallow_since浅克隆边界test_git_repository_shallow_since 传入shallow_since 2015-07-15提交日期的前一天验证按日期浅克隆。规则属性文档git.bzl特别提醒由于 git--shallow-since实现存在 bug该属性可能引发 fetch 失败因此不推荐使用且当指定tag时不允许同时使用shallow_sincetag 一律用--depth1违反时报shallow_since not allowed if a tag is specified由 test_git_repository_shallow_since_with_tag_error 覆盖。四、outer-planetssubmodule 递归克隆的验证载体outer-planets-repo.tar.gz专门用于验证 submodule 支持。仓库在1-submoduletag 下包含neptune/info与作为 submodule 指向../pluto的pluto/见 starlark_git_repository_test.sh 注释。两个对称测试覆盖init_submodules与recursive_init_submodules两种模式构建一个同时依赖outer_planets//:neptune与outer_planets//:pluto的genrule断言两个输出文本都存在Neptune is a planet 与 Pluto is a planet。outer-planets.git_log同样记录了该仓库的提交历史便于核对 submodule 引用的具体提交。五、refetch 仓库缓存、重取与 --nofetch 的行为探针refetch-repo.tar.gz里的内容在不同提交间只有一行文本差异GIT 1、GIT 2是测试 Bazel 外部仓库缓存语义的探针。这些测试统一先执行add_to_bazelrc common --repo_contents_cache关闭仓库内容缓存以观察真实的重新克隆行为服务重启不重取test_git_repository_not_refetched_on_server_restart用--batch强制每次重启 Bazel server断言第一次出现Cloning重启后不再出现且产物仍是GIT 1commit 变更触发重取test_git_repository_refetched_when_commit_changes把 commit 从22095302...换到db134ae9...断言重新Cloning且产物变为GIT 2注释行变化不触发重取仅修改MODULE.bazel中注释的行号位置commit 不变断言不重新克隆——这验证了仓库指纹只依赖语义属性而非文本strip_prefix 变化触发重取test_git_repository_not_refetched_on_server_restart_strip_prefix同样的 commit 从无strip_prefix改为strip_prefix gdir需要重新检出--nofetch 语义test_git_repository_and_nofetch首次未克隆时bazel build --nofetch报fetching repositories is disabled已克隆但属性变更commit 或 strip_prefix后--nofetch报External repository git_repositoryg is not up-to-date但仍复用旧内容直到正常 build 才完成重取。这些用例精确刻画了git_repository在 Bazel 磁盘缓存、Skyframe 重分析与仓库指纹三方协同下的重取语义。六、错误路径测试让规则正确地失败除了功能路径测试数据还支撑了一批错误路径用例错误信息与 git.bzl 实现一一对应commit 与 tag 冲突test_git_repository_both_commit_tag_errortag 1-build与commit同时给出报At most one of commit, tag, or branch may be provided见 git.bzlstrip_prefix 不存在test_invalid_strip_prefix_errorstrip_prefix dir_does_not_exist报strip_prefix at dir_does_not_exist does not exist in repostrip_prefix 系列非法值test_strip_prefix_errors针对文件而非目录、../..目录穿越、指向.git/objects元数据、以及符号链接逃逸/指向元数据五种情形逐一断言报错并额外断言失败后 external 目录中不留残余assert_not_exists .../configtag 与 shallow_since 冲突见上文 3.5 节。七、测试数据的生成与维护可复现的手工流水线README 明确了数据的生产流程手动创建 git 仓库 → 提交若干带 tag 的历史 → 用tar -zcvf打包成归档。这意味着维护者只需保证每次修改仓库内容后同步更新归档保持解包即仓库的完整性包括.git目录用git log -p --decorate重新生成对应的*.git_log快照作为提交历史与 tag/commit 映射的权威参考测试脚本中引用的 commit hash 与 tag 必须能在.git_log中找到对应条目测试注释里也反复出现 See testdata/pluto.git_log 字样如 starlark_git_repository_test.sh。由于归档内是完整仓库tar zxf后无需任何网络即可作为本地remote使用这保证了集成测试在离线、无外网 CI 环境下依然可复现。八、如何在本地复现这些测试以下命令可在 Bazel 源码树中运行对应测试需要本机具备 git 与可用的 Bazel 发行版# 运行全部 git_repository 集成测试 bazel test //src/test/shell/bazel:starlark_git_repository_test # 仅查看测试脚本中的具体用例函数名即测试名 bazel test //src/test/shell/bazel:starlark_git_repository_test --test_filtertest_git_repository_submodules若只想人工检查数据本身可直接解包归档并查看历史mkdir -p /tmp/repo-check cd /tmp/repo-check tar zxf 仓库根/src/test/shell/bazel/testdata/pluto-repo.tar.gz cd pluto git log --oneline --decorate对照 pluto.git_log 可以看到1-build、2-subdir、3-subdir-bare三个 tag 依次完成加入 BUILD → 移入子目录 → 删除 BUILD的演进这正是驱动 strip_prefix、build_file 等全部核心测试场景的仓库骨架。小结src/test/shell/bazel/testdata/下的归档与 git log 文件是 Bazelgit_repository规则质量保障的最小宇宙四个小而完整的 Git 仓库pluto、outer-planets、refetch、strip-prefix以本地路径形式充当 remote配合 starlark_git_repository_test.sh 中数十个用例覆盖了克隆、submodule、目录裁剪/下沉、浅克隆、缓存重取与全部关键错误路径。理解这套测试数据的组织方式既能帮助你在修改git_repository相关行为时快速定位回归风险也为自建外部依赖规则时设计小而准的测试仓库提供了可直接借鉴的范本。【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考