☰
Eglantine 模拟器 PR 测试实战指南:从 based master 对比到 git bisect 定位回归
2026/11/2 15:18:04 网站建设 项目流程

【免费下载链接】Eglantine

VERY experimental Nintendo Switch 2 emulator

项目地址:https://gitcode.com/gh_mirrors/eg/Eglantine
点击查看免费下载

本文以 Eglantine(源自 Eden 的 Switch 2 模拟器)用户手册中的测试指南为核心,完整讲解社区在测试 Pull Request(PR)时的标准工作流:如何用 based master 分支判定回归归属、如何维护一致的测试环境与干净的 shader cache、如何按清单执行系统性测试与 bisect 二分定位,以及如何撰写开发者能直接采用的测试结果报告。读完本文,你可以独立承接一个 PR 的测试任务,并给出可复现、可定位、可追责的结论。

一、核心原则:一切以 based master 分支为参照系

测试一个 PR 时遇到异常行为,第一个要回答的问题是:这个问题是 PR 引入的,还是基线代码里本来就有的?原始指南给出的方法是:将行为与该 PR 所基于的 master 分支(based master)进行对比。

  • 若 based master 上同样出现该问题,说明它在 PR 之前就已存在,PR 大概率没有引入回归;
  • 若 based master 上没有问题,则说明 PR 很可能引入了回归,需要进一步排查。

在问题出现之前,指南还强调了一条最佳实践:保持测试设置一致,并删除 shader cache。使用已有的 shader cache 在少数情况下会让一个 PR 看起来像是发生了性能/渲染回归。这条建议在 Eglantine 源码中可以得到印证:

  • shader 缓存目录由路径管理器统一分配,位于 Eden 数据目录下的 cache 子目录中的shader目录。从 path_util.cpp 可以看到ShaderDir被注册为eden_path_cache / SHADER_DIR,常量"shader"定义于 fs_paths.h;
  • 缓存按游戏 program id 分目录存放(目录名为 16 位十六进制 program id),具体文件包括可移植缓存opengl.bin、vulkan.bin以及驱动管线缓存vulkan_pipelines.bin,删除逻辑实现在 game.cpp 的RemoveTransferableShaderCache、RemoveVulkanDriverPipelineCache与RemoveAllTransferableShaderCaches中;
  • Qt 前端在 main_window.cpp 里将这些函数接到游戏列表的“删除 shader 缓存”菜单项上。

因此“删除 shader cache”在工程上就是清空对应游戏的缓存目录(或删除全部shader目录内容),确保 PR 构建与 master 构建都从空缓存开始着色器编译,排除缓存命中差异造成的干扰。

二、源码之树:测试视角下的分支模型

指南建议把源码想象成一棵“树”:

  • 树干是master分支:所有已合并代码汇入此处;稳定发布版本只从master拉取;
  • 其余分支都是 PR 或独立开发分支,均视为不稳定,不建议直接拉取,除非你在一次测试中需要对比多个分支。

需要熟悉的术语如下(这是测试报告沟通的基础词汇):

术语含义
PRPull Request,一次代码变更;作者请求将该分支并入 master,使新代码最终进入发布版本
Bisect二分搜索回归的方法;少数回归具有偶发性、无法二分,但绝大多数可以
WIPWork-in-progress,进行中的未完成工作
Regression由新代码引入的新 bug/异常,例如“某游戏在提交 xyz 之后的 Android 上坏了”
Master“根部”分支,所有已合并代码所在之处,传统上也叫main、trunk
HEAD给定分支的最新提交;master的HEAD即master分支上的最新提交
origin默认远程仓库,即 git 代码库所在位置(本项目上游官方仓库)

三、测试范围选择:不必测所有 PR

指南明确给出了取舍标准,避免把测试精力浪费在不产生风险的变更上:

  • 文档类 PR 与极琐碎的改动(例如只改应用图标的 PR)原则上不需要测试,除非你确实想测;
  • 标记为[docs]的 PR 一般应跳过;
  • 平台定向 PR:若 PR 声明只针对某平台(如linux),就只在 Linux 上测;
  • 标记NCE的 PR:NCE 是 Eglantine 对 Switch 2 CPU 的模拟器实现,此类 PR 应在Android 与 Linux ARM64(如 Raspberry Pi)上测试;
  • macOS 修复:也可能影响 Asahi(苹果 Silicon 上的 Linux 发行版),条件允许时顺带验证。

四、自建构建的局限性

你也可以自行构建 PR 产物来测试,但指南特别提醒:自构建产物与 CI 产物并不完全相同,原因是包版本与构建环境存在差异。文中给出的著名例子是:FFmpeg 在不少 Arch 系发行版上因打包差异而“随机”出问题。因此当你在自构建上观察到异常时,需要意识到这有可能是构建环境噪音而非 PR 引入的回归。自建构建可参考 Build.md,最简流程为:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -G Ninja cmake --build build

构建完成后,可执行文件位于build/bin/eden(Windows 为build/bin/eden.exe,macOS 为build/bin/eden.app/Contents/MacOS/eden),另有 SDL 前端eden-cli(目标名yuzu-cmd,见 CMakeLists.txt)。

五、Testing Checklist:系统性排查清单

对 PR 或提交引起的回归/bug,指南给出了一份完整的决策树清单,这里完整保留:

针对 PR/提交引起的回归/bug:

  • 在 master 上复现吗?
    • 如果在 master 上复现:
      • 在更早的稳定发布版本上复现吗?(该 PR 之前的版本)
        • 如果在更早稳定版本上复现:
          • 在再更早的稳定版本上复现吗?
            • 如此类推……有些 bug 的来源比整个项目的历史还要久远。
        • 否则,在上一个稳定版本与master 的最新HEAD之间做 bisect:
          • 在给定提交上复现吗?
  • 在 PR 上复现吗?
    • 如果在 PR 上复现:
      • 对 PR 做过分叉(bisected PR,前提是其包含多个 commit)?
      • 找到了引发问题的提交?

对于偶发性问题,指南给出了量化方法:尽量多跑若干次,统计失败次数与正常次数。例如某行为 4 次运行中成功 3 次、失败 1 次,则每次运行有 1/4 的概率触发问题——因此bisect 的每一轮都需要跑 4 次,才能保证至少有一次机会触发该 bug。

六、发现异常后的标准动作

如果在测试中发现行为不对劲:

  1. 用 based master 分支重新复现该问题;
  2. 观察是否出现相同行为。

之后只有两种结论:

  • based master 上同样存在:问题在 PR 之前就有,PR 大概率没有引入回归;
  • based master 上不存在:PR 很可能引入了回归,需要进一步调查。

两个补充情形:

  • 如果某行为对某个特定游戏/功能而言属于正常表现,则未必每次都需要对照 based master 验证;
  • 如果 PR 所对应的 based master 没有现成构建产物,指南建议测试其前后邻近的构建,这有助于收集更多关于问题的信息。

七、报告结果:让结论一目了然

汇报测试结果时必须做到两点:

  • 明确说明该行为是否在 based master 上出现;
  • 明确标注结果是 good(符合预期)还是 bad(异常/损坏)。不说明好坏会让 PR 开发者困惑。

指南给出的标准句式示例:

  1. "Bad result for PR: Tested on based master - issue not present. Likely regression introduced." (PR 结果为差:在 based master 上测试,问题不存在,很可能为 PR 引入的回归。)
  2. "Good result for PR: Tested on based master - issue already present. Not a regression." (PR 结果为好:在 based master 上测试,问题已存在,不是回归。)

这种“是否回归 + 好/坏结论 + 复现范围”的表述方式,保证了测试过程清晰、责任可追溯,也让回归能被高效地捕获与处理。

另外,报告中按需附上调试信息(docs/Debug.md 所述的调试日志、图形调试输出等)——Testing 指南特别强调“Always include debugging info as needed”。

八、Bisecting:会用二分定位才算会测试

指南有一句强调:测试时,要懂得 bisect!其原理是把“坏的区间”不断对半切开,快速收敛到第一个出问题的提交。

以“问题出现在 1 月 1 日 与 1 月 8 日 之间”为例:

  • 检查 1 月 4 日:若 4 日正常,问题必在 4 日之后;
  • 于是检查 1 月 6 日:若 6 日不正常,问题必在 6 日及之前;
  • 于是检查 1 月 5 日:若 5 日正常,则问题从 6 日开始。

结论:引发问题的提交即1 月 6 日的那一个。这就是 git bisect(二分查找)的典型执行路径,区间每检查一次缩小一半,n 个提交通常只需 log₂(n) 次验证即可定位。

结合 Eglantine 的命令行能力,验证某个提交是否触发问题时的常用手段(参数含义参见 CommandLine.md):

./build/bin/eden-cli -c <config.ini 路径> -d -g <game path>
  • -d/--debug:进入调试模式,允许 GDB stub;
  • -c/--config:指定替代配置文件(正常运行的日志中会提示配置路径);
  • -g/--game:指定加载的游戏;
  • 排查图形问题时可加-n/--null-render强制使用 Null 渲染后端,把“渲染回归”与“非渲染回归”区分开。

九、Notes:CI 与仓库协作细节

原始指南末尾的 Notes 包含几条直接影响测试执行效率的实操信息:

  • 标记 WIP 的 PR 无需测试(除非被明确点名要求;可通过 git 信息确认其是否仍为 WIP);
  • 许可证检查(license check)可能失败:此时把鼠标悬停在构建图标上查看构建本身是否成功——CI 即使在 license 检查失败时也会推送构建产物;
  • 所有开放的 PR 可以在上游仓库的 PR 列表中查看;
  • 若上游站点不可用,可改用 ThirdParty.md 中列出的镜像仓库继续获取代码与构建。

十、小结:一条可复用的 PR 测试流程

把上述内容串起来,一个完整的 PR 测试流程是:

  1. 确认 PR 是否需要测(跳过[docs]、WIP 与琐碎改动,按平台标签选定测试平台);
  2. 准备干净环境:固定设置、删除目标游戏的 shader cache(对应shader/<program_id>缓存目录);
  3. 分别在PR 构建与based master 构建(或邻近构建)上执行同一测试用例;
  4. 出现异常时,按 Testing Checklist 逐级回溯,必要时用 bisect 二分定位提交;偶发问题按触发概率决定每轮运行次数;
  5. 按“是否回归 + Good/Bad 结论 + 调试信息”的标准格式上报。

这套流程的价值在于:它不依赖任何人的主观印象,而是让“这个 PR 是否有回归”成为一个可以被任何人按同一清单复核的客观结论。

附:本文引用的仓库文件

  • 原始文档:docs/user/Testing.md
  • 调试信息规范:docs/Debug.md
  • 构建指南:docs/Build.md
  • 命令行参数:docs/user/CommandLine.md
  • 镜像与第三方工具:docs/user/ThirdParty.md
  • shader 缓存路径:src/common/fs/path_util.cpp、src/common/fs/fs_paths.h
  • shader 缓存删除实现:src/qt_common/util/game.cpp、src/yuzu/main_window.cpp

【免费下载链接】Eglantine

VERY experimental Nintendo Switch 2 emulator

项目地址:https://gitcode.com/gh_mirrors/eg/Eglantine
点击查看免费下载

相关推荐

上一篇:681M视觉编码器深拆解:MiMo-V2.6-Flash-MOPD的MiMo ViT如何看懂图像与视频
下一篇:IQuest-Q1架构深度剖析:88层混合注意力+256专家MoE设计逐项解读

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询