ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Hermes 测试运行器(Test Runner)完全指南:test262 / mjsunit / esprima / flow / CVE 测试套件集成运行与 Skiplist 管理

2026/9/24 17:23:14 拓冰建站 浏览量
Hermes 测试运行器(Test Runner)完全指南:test262 / mjsunit / esprima / flow / CVE 测试套件集成运行与 Skiplist 管理 语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载本篇技术指南聚焦 Hermes JavaScript 引擎仓库中的utils/testsuite/测试运行器Test Runner它负责将 test262、mjsunit、esprima、flow 与 CVE 等外部/内部测试套件统一接入 Hermes通过异步并发方式批量编译并执行每个测试用例、汇总通过率并输出失败明细。读完本文你将掌握该运行器的完整命令行用法、编译/VM 参数注入方式、九个 Skiplist 分类的语义与维护流程以及从源码层面理解其并发调度、测试预处理与结果判定的实现原理。一、为什么需要一个统一的 Test RunnerHermes 作为面向 React Native 的 JavaScript 引擎需要持续验证两件事语言规范符合度与 ECMAScript 规范的一致性与AST/语法兼容性对 esprima、flow 生态语法树的还原能力。这两类验证分别依赖不同的测试资产test262ECMAScript 官方一致性测试套件用例带有 frontmatter 元数据flags、negative、features、includes需要预处理后才能运行mjsunitV8 的回归测试风格套件要求直接运行源码并校验编译/运行时错误esprima / flow仅做 AST 校验需要把源码交给 Hermes 解析后与预期的*.tree.json/*.failure.json结果比对CVEs与 test262 同风格 frontmatter 的安全回归用例。如果为每一套件各写一套脚本参数、统计口径与跳过逻辑会严重重复。Hermes 的做法是提供一个统一入口 utils/test_runner.py它只是薄薄一层包装导入testsuite.cli并执行asyncio.run(main())真正的逻辑全部落在utils/testsuite/包内。README即 utils/testsuite/README.md给出了该运行器的设计定位与用法概要本文以下内容将结合仓库源码逐层展开。二、快速开始运行一个测试套件运行器需要两类输入路径见 utils/testsuite/README.md 的 How to run测试套件目录当前支持的套件根目录包括 test262、mjsunit、esprima、flow 以及 CVE 套件多个套件路径可用空格分隔一次传入同时运行多套测试Hermes 二进制目录包含hermes可执行文件若启用--shermes还需shermes若启用--bytecode-compat-check还需b_hermes的构建输出目录通常是 CMake 构建目录下的bin/。README 中的示例用法如下假设./build是 cmake 构建目录# flow 套件 ./utils/test_runner.py external/flowtest/test/flow -b ./build/bin # esprima 套件 ./utils/test_runner.py external/esprima/test_fixtures -b ./build/bin其中external/flowtest/test/flow与external/esprima/test_fixtures均位于本仓库的external/目录下见 external/flowtest/test 与 external/esprima/test_fixtures可直接使用。test262、mjsunit 与 CVE 套件则需要自行准备对应目录仓库内test/下存放的是 Hermes 自身的回归用例与上述外部套件不同。运行前utils/testsuite/utils.py 中的check_hermes_exe()会校验-b指定的目录中是否存在所需可执行文件缺失时直接报错退出路径参数既可以是目录递归收集其中所有.js文件test262目录下以_FIXTURE.js结尾的 fixture 文件会被排除也可以是单个文件。三、支持的测试套件与自动识别机制运行器如何知道一个测试文件属于哪套测试答案在 utils/testsuite/test_run_defs.py 的Suite.create()它按路径子串识别从路径末尾往前查找第一个匹配的目录名避免路径中出现重复目录名时误判路径子串Suite 类套件名test262/Test262Suitetest262mjsunit/MjsunitSuitemjsunitCVEs/CvesSuite继承Test262SuiteCVEsesprima/EsprimaAstCheckSuiteesprimaflow/FlowAstCheckSuite注意用flow/前缀避免误匹配flowtest/flow每个用例的完整测试名格式为{suite_name} :: {相对路径}例如mjsunit :: regress-011.js这个名称会出现在输出、Skiplist 更新交互与最终统计中。不同的 Suite 决定不同的运行策略Test262Suite / CvesSuite先解析 test262 风格 frontmatter 做预处理再执行编译 运行两阶段流程详见第四节MjsunitSuite同样走编译 运行但无需 test262 harness 逻辑AstCheckSuiteesprima/flow 基类调用generate_ast()生成 AST与期望文件比对。期望文件按优先级查找*.tree.json→*.failure.json→*.tokens.json后者不被支持、直接 SKIP见 utils/testsuite/test_run_defs.py。四、命令行参数详解运行器的全部参数在 utils/testsuite/cli.py 的create_parser()中定义。README 只点出了其中最关键的几个下表基于源码补齐了完整参数集、默认值与作用参数默认值说明paths位置参数nargs必填测试套件路径可传目录或文件、可传多个空格分隔-b, --binary-dir包根目录Hermes 构建产物目录需含hermes必要时含shermes/b_hermes-j, --jobs逻辑 CPU 数兜底 10同时运行的测试任务数用于限制资源争用--compile-args空追加的编译器参数多个参数用空格分隔nargs--vm-args空追加的 VM运行字节码参数多个参数用空格分隔--test-skiplist关闭强制运行 Skiplist 配置中的测试通过后询问是否从配置移除--test-intl关闭运行需要 INTL 的测试对应intl_tests分类--lazy关闭强制惰性求值lazy evaluation模式与--shermes互斥--shermes关闭使用shermes二进制测试与--lazy互斥--opt关闭编译时启用优化器用-O而非-O0--bytecode-compat-check关闭用hermes编译、b_hermes运行校验字节码兼容性对 shermes/lazy 模式无效果-v, --verbose关闭输出中间过程-d, --dump-source关闭不运行测试仅把预处理后的源码打印到 stdout此时只允许传一个路径--work-dir自动临时目录生成预处理测试文件的工作目录若已存在会先删除--timeout200秒单个测试编译与运行的超时上限--show-slowest-tests N0关闭结束时打印耗时最长的 N 个测试其中--compile-args/--vm-args支持一种实用的小技巧由于 argparse 会把以-开头的值误判为标志源码在 utils/testsuite/cli.py 提供了strip_nargs()允许在参数值前后补空格传入例如--compile-args -Xes6-block-scoping。五、默认编译与 VM 标志README 指出默认情况下test262 与 CVE 套件会使用以下编译器/VM 标志。这些标志在 utils/testsuite/hermes.py 中定义为常量# 编译器hermes 编译字节码时追加 -test262 -fno-static-builtins -Xes6-block-scoping -Xenable-tdz -Xasync-generators # VM运行字节码时追加 -Xes6-proxy -Xhermes-internal-test-methods -Xmicrotask-queue各标志的作用从名称与上下文可推断-test262启用 test262 兼容的宿主环境如提供$262对象-fno-static-builtins关闭静态内建函数优化保证内建函数可被测试覆写-Xes6-block-scoping/-Xenable-tdz开启 ES6 块级作用域与暂时性死区TDZ检查-Xasync-generators开启 async generator 支持-Xes6-proxy开启 ES6 Proxy-Xhermes-internal-test-methods暴露内部测试方法-Xmicrotask-queue启用微任务队列async 测试依赖 Promise 微任务调度。运行字节码时utils/testsuite/hermes.py 还会附加-b以字节码方式运行.out文件与-Xes6-proxy、-Xhermes-internal-test-methods、-Xmicrotask-queue在 lazy 模式下则改为直接运行源码并追加-lazy与上述 COMPILE_ARGS。由于 esprima 套件只做 AST 校验运行器对 esprima 直接使用-dump-ast见 utils/testsuite/hermes.py 的generate_ast()而 flow 套件在此基础上追加-parse-flow -Xparse-component-syntax -parse-jsx -Xinclude-empty-ast-nodes -Xparse-flow-matchgenerate_ast()中还会根据测试文件路径是否含JSX追加--parse-jsx并支持-dump-transformed-ast当首次解析未报错、但期望文件要求失败时用语义校验模式重跑一次见 utils/testsuite/test_run_defs.py。对于 esprima 套件中形如var source ...的*.source.js文件会先用 Hermes 求值出source变量的内容再交给解析器处理见 utils/testsuite/hermes.py。六、Skiplist 配置机制skiplist.json即 utils/testsuite/skiplist.json是控制哪些测试默认跳过的配置文件。README 列出的九个分类在 utils/testsuite/skiplist.py 中被定义为SkipCategory枚举与 README 一一对应分类键语义判定结果码manual_skip_list人工维护通常是计划近期支持、支持后手动移除的测试也可附注释说明原因SKIPPEDskip_list因规范不完全符合或特性未支持而当前失败的测试可被--test-skiplist反跑移除SKIPPEDlazy_skip_list传入--lazy时需要跳过的测试SKIPPEDpermanent_skip_list不计划修复/支持的测试PERMANENTLY_SKIPPEDhandlesan_skip_list需以-gc-sanitize-handles0运行的测试关闭句柄 sanitizer 以提速—运行时附加参数unsupported_featurestest262 中暂不支持的特性未来可能支持按 feature 名匹配SKIPPEDpermanent_unsupported_featurestest262 中不支持且无支持计划的特性按 feature 名匹配PERMANENTLY_SKIPPEDintl_tests需要启用 INTL 才能运行的测试配合--test-intl使用SKIPPEDplatform_skip_list按平台跳过的测试JSON 内按linux/darwin/win32分组SKIPPED从当前 utils/testsuite/skiplist.json 的实际规模看skip_list约 1600 条、permanent_skip_list约 430 条、handlesan_skip_list约 86 条、unsupported_features22 条、permanent_unsupported_features4 条含Atomics、SharedArrayBuffer、IsHTMLDDA、cross-realm、lazy_skip_list1 条、intl_tests指向test262/test/intl402目录、manual_skip_list8 组、platform_skip_list覆盖 3 个平台。配置项的值有两种形式纯字符串路径可以是完整文件路径、目录路径.../formatRange/或部分路径前缀如mjsunit/mul-exhaustive-匹配多个文件带注释的对象形如{paths: [...], comment: ...}comment记录跳过原因如 Timeout on Sandcastle、跟踪 issue 编号等manual_skip_list中的条目几乎都带注释。匹配逻辑在 utils/testsuite/skiplist.py 的should_skip_cat()中字符串做子串包含匹配所以目录路径与部分前缀都能命中同时也支持正则 Pattern 匹配供 test262 的 feature 匹配使用。运行时的跳过决策主循环中utils/testsuite/cli.py每个测试文件依次检查默认跳过分类skip_list、permanent_skip_list、manual_skip_list、platform_skip_listlazy 模式追加lazy_skip_listIntl 分类intl_tests单独检查只有传--test-intl才运行test262 特性分类对每个features元数据先查构建出的hermes --version输出中动态支持的特性见 utils/testsuite/utils.py 的get_hermes_supported_test262_features()当前映射如Unicode RegExp Property Escapes→regexp-unicode-property-escapes支持则跳过 Skiplist 检查否则再查unsupported_features/permanent_unsupported_features。跳过结果映射到SKIPPED或PERMANENTLY_SKIPPED两种结果码见 utils/testsuite/skiplist.py并计入最终统计。七、用--test-skiplist反跑并自动清理 Skiplist这是 Skiplist 机制中最有价值的工作流README 对其进行了重点描述# 强制运行 skiplist.json 中列出的所有测试 ./utils/test_runner.py external/flowtest/test/flow -b ./build/bin --test-skiplist行为细节如下加了--test-skiplist后原本会被跳过的测试照常执行--lazy时额外反跑lazy_skip_list--test-intl时额外反跑intl_tests结束后运行器打印所有已通过的 Skiplist 测试Passed tests in skiplist:然后通过input()提示Remove these passed tests from skiplist? [y]es/[n]o:确认后把这些测试从配置中移除见 utils/testsuite/cli.py 的remove_tests_from_skiplist()目前只有skip_list与permanent_skip_list两个分类会被自动更新见 utils/testsuite/skiplist.py 的remove_tests()其余分类不会被触碰。针对配置中写的是目录/部分路径的情况运行器会先执行unfold展开把目录路径递归展开为其中所有测试文件、把部分路径展开为所有匹配文件剔除已通过的用例后将剩余文件以文件粒度写回配置utils/testsuite/skiplist.py。这一设计的价值在于skip_list中常见的整目录跳过项如test262/test/intl402/NumberFormat/在个别用例通过后无需人工去拆目录。README 特别提醒如果你不希望某个目录被自动展开请把它放进manual_skip_list并附注释说明原因因为manual_skip_list不会被自动更新。八、结果统计与运行输出解读每次运行结束utils/testsuite/cli.py 的print_stats()会输出一张 ASCII 统计表字段与 utils/testsuite/utils.py 中的TestResultCode一一对应----------------------------------- | Results | PASS | |--------------------------------| | Total | 10000 | | Passes | 9850 | | Failures | 80 | | Skipped | 60 | | Permanently Skipped | 10 | | Pass Rate | 99.19% | -----------------------------------Failures Compile fail Compile timeout Execute fail Execute timeout Other即TEST_FAILED用于 JSON 错误等未分类失败Pass Rate Passes /Total − Skipped − Permanently Skipped失败用例会在 Details: 段按 Compile failed / Compile timeout / Execute failed / Execute timeout / Other test failure 分组打印完整路径与输出配合--show-slowest-tests N可输出按子进程墙钟耗时排序的 Top-N 慢测试。TestResultCode的is_failure属性utils/testsuite/utils.py定义很关键只有TEST_PASSED、TEST_SKIPPED、TEST_PERMANENTLY_SKIPPED不算失败其余全部计为失败这也决定了进程退出码存在失败返回 1否则返回 0。九、并发调度与测试执行的源码原理运行器采用asyncio 子进程 信号量的并发模型核心逻辑在 utils/testsuite/cli.py 的run()中先递归收集所有测试文件list_all_files()为每个文件构造TestRunArgs用asyncio.Semaphore(n_jobs)限制存活任务数每个任务包裹一个子进程调用用asyncio.as_completed()按完成顺序消费结果任务完成后释放信号量、让新任务进入进度通过ProgressBar/SimpleProgressBar显示-v时输出每条用例的中间结果。对每个 test262 用例Test262Suite.run_test()utils/testsuite/test_run_defs.py的完整流程是读取源码交给 utils/testsuite/preprocess.py 的generate_source()解析 frontmatter确定flagsonlyStrict/noStrict/raw/async/module等、strict_mode、negative期望失败的phase与type、features并把includes指定的 harness 文件如sta.js、assert.jsasync 用例还会附加doneprintHandle.js内容拼接到源码前module标志的用例直接 SKIP包含testIntl.jsharness 的用例 SKIP当前不支持多 Intl 构造器async标志的用例在结果判定时额外检查 stdout 中的Test262:AsyncTestComplete/Test262:AsyncTestFailure标记见 utils/testsuite/hermes.py根据strict_mode生成一个或两个变体文件严格模式变体文件名带.strict且会在开头插入use strict;按negative.phase校验期望失败阶段parse期望编译失败runtime期望运行抛错——预期与实际不符都判 FAILutils/testsuite/hermes.py 的compile_with_args()与run()若命中handlesan_skip_list追加-gc-sanitize-handles0运行参数最后统计各变体的编译 运行总耗时并返回TestCaseResult。调试小技巧-d, --dump-source可以把某个用例预处理后的源码含插入的 harness 代码与use strict;指令直接打印到终端方便确认预处理是否正确此时只允许传入一个路径utils/testsuite/cli.py。十、环境与兼容性注意事项运行器为每个子进程传递当前环境变量便于设置 shermes / ASAN 等选项并强制LC_ALLen_US.UTF-8Linux 下还会设置ICU_DATA指向二进制目录utils/testsuite/hermes.pyprogress.py模块源自 Hermes 所携带的 LLVM 工具external/llvh/utils/lit经简化改造后使用见 utils/testsuite/README.facebook字节码兼容性检查--bytecode-compat-check要求-b目录中同时存在hermes与b_hermes且该模式在 shermes 与 lazy 模式下不生效若要调试预处理逻辑可直接阅读 utils/testsuite/preprocess.pytest262 元数据解析与 utils/testsuite/external/parse_test262.pyfrontmatter 语法解析来自 test262 官方工具。通过上述机制Hermes 团队得以在单一命令下持续跟踪数十万级测试用例的通过率并把新修复的用例从 Skiplist 中毕业这一日常维护动作自动化——这正是 utils/testsuite/README.md 所描述的核心工作流也是本文所有实操命令与配置的最终落点。赞分享语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载相关推荐curl 测试套件Test Suite完全指南运行、调试与编写测试用例curl 测试套件Test Suite完全指南运行、调试与编写测试用例 本文围绕 curl 仓库中的测试套件展开系统讲解如何从零构建并运行 curl 的CLI网络通信vim-plug 测试套件完全指南用 Vader.vim 运行与扩展插件管理器测试vim plug 测试套件完全指南用 Vader.vim 运行与扩展插件管理器测试 本篇指南围绕 vim plug 仓库的 test 测试目录 https:/开发工具插件系统Flow 项目测试框架指南使用 ./tool test 编写与运行 newtests 集成测试Flow 项目测试框架指南使用 ./tool test 编写与运行 newtests 集成测试 导读 本指南基于 Flow 仓库中的 newtests/REA开发工具静态分析代码质量上一篇MLflow AI Gateway 集成 Hugging Face Text Generation InferenceTGI实战指南下一篇WezTerm Lua API 详解wezterm.procinfo.pid() 获取当前进程 ID创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考