ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Dart SDK 前端编译器 Rasta 回归测试套件详解:`pkg/front_end/testcases/rasta` 的结构、期望文件与运行机制

Dart SDK 前端编译器 Rasta 回归测试套件详解:`pkg/front_end/testcases/rasta` 的结构、期望文件与运行机制 编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载本文围绕 Dart SDK 中pkg/front_end即 Fasta 前端编译器 / CFE的testcases/rasta回归测试目录展开说明这批测试的起源rasta 项目、*.dart测试文件与多套.expect期望文件的组织方式、期望文件中 kernel IR 文本与错误诊断的阅读方法以及如何通过官方工具运行测试、更新期望。读完本文你可以独立读懂任意一个 rasta 测试用例并掌握在 SDK 开发中维护这类前端编译器回归测试的标准流程。1. 什么是 Rasta 回归测试来源与定位pkg/front_end/testcases/rasta/README.md的开宗明义指出本目录中的测试用例全部复制自 rasta 项目的test/kernel/regression目录对应的原始提交为dace1ed5964953ce53065fd41eebfa8920419ff0rasta 原本的期望文件*.dart.txt被复制了三份分别保存为.outline.expect、.direct.expect和.dart.dartk.expect。rasta 是 Dart 语言早期的一个前端实验项目其test/kernel/regression目录沉淀了一批曾经出过 bug 或行为不一致的 kernel 编译回归用例。当 Fastapackage:front_end成为 Dart 官方前端后这批用例被整体移植进 SDK用于持续验证 CFE 的行为没有回归。从当前仓库的实际目录看命名已经演化为.strong.expect、.strong.outline.expect、.strong.modular.expect、.strong.transformed.expect、.textual_outline.expect、.textual_outline_modelled.expect等多套变体——可以推断 README 记载的三种原始拷贝在后续演进中逐步对应到了不同编译模式详见第 4 节。2. 目录结构与测试形态rasta/目录遵循pkg/front_end/testcases的整体约定每个.dart文件是一个测试输入同名的.expect文件是编译输出快照。从目录清单可以看到以下三类素材类别示例文件说明错误诊断测试bad_*/malformed_*/parser_errorbad_continue.dart、bad_interpolation.dart、bad_unicode.dart、malformed_const_constructor.dart、malformed_function_type.dart、parser_error.dart故意写入非法代码验证 CFE 报错位置、消息与源码标记^历史缺陷回归测试issue_*issue_000001.dart、issue_000002.dart、…、issue_000081.dart每个编号对应 rasta 时代的一个具体缺陷验证其不再复现语法/语义特性覆盖super.dart、cascades.dart、enum.dart、deferred_load.dart、class_hierarchy.dart、generic_factory.dart、for_loop.dart、export.dart对语言特性做系统化输入覆盖验证 kernel 输出符合预期此外目录顶部还有一个空的folder.options文件当前为空表明该目录继承默认测试选项并包含若干辅助库文件如foo.dart、deferred_lib.dart、mixin_library.dart它们供同目录测试文件import/export使用例如foo.dart声明了library foo;和顶层函数foo()。3. 期望文件格式深度解读期望文件是这类测试的灵魂——它是 CFE 编译测试输入后得到的格式化输出快照。以 hello.dart.strong.expect 为例一个无错误的简单用例输出为library; import self as self; import dart:core as core; static method main() → dynamic { core::print(Hello, World!); }这段文本是 kernel IR 的人类可读形式包含几个高频符号library;标记当前编译库import self as self表示库自身的别名→是返回类型箭头如→ dynamic、→ voidcore::print表示对dart:core库中print的库限定引用static method、field、get、set、operator、synthetic constructor等关键字对应 kernel 中的各种成员声明。3.1 错误诊断的三种载体再看 issue_000001.dart.strong.expect它展示了诊断信息在期望文件中的呈现方式library; // // Problems in library: // // pkg/front_end/testcases/rasta/issue_000001.dart:11:8: Error: Too many positional arguments: 1 allowed, but 2 found. // Try removing the extra positional arguments. // test0(0, 1); // ^诊断以路径:行:列: Error: 消息形式给出附带Try …修复建议随后是源码片段与^光标标记精确定位到出错 token当 CFE 无法为出错表达式构造合法 kernel 节点时会在 IR 中以invalid-expression …错误文本…占位例如issue_000001.dart.strong.expect中main的方法体static method main() → dynamic { invalid-expression pkg/front_end/testcases/rasta/issue_000001.dart:11:8: Error: Too many positional arguments: 1 allowed, but 2 found. Try removing the extra positional arguments. test0(0, 1); ^; }也就是说同一个错误信息在期望文件中出现了两次一次汇总在文件头部的Problems in library:清单里一次作为invalid-expression内嵌在 IR 的对应位置——后者是 kernel 保留坏表达式以便后续阶段如 dart2js、VM 编译器继续工作的机制。3.2 从super.dart看 IR 的降级细节super.dart 是一个极具价值的特性覆盖用例class C extends B extends A的三级继承下对super的所有访问形式做了穷举——一元运算符~super、-super、非法的super、比较super 87、getter/settersuper.a、super.a 42、下标读写super[87]、方法调用super.m()、复合赋值、-以及前后缀自增自减super.a、super.b。其期望文件 super.dart.strong.expect 恰好展示了 CFE 对这些形式在 kernel 层面的展开成员访问被解析为带声明来源的精确引用super.{self::A::a}、super.{self::B::b}——括号中的self::A/self::B指明该成员实际定义在哪个类复合赋值与自增展开为let final临时变量序列如let final core::int #t13 87 in super.{self::A::[]}(#t13, super.{self::A::[]}(#t13){dynamic}.(1))保证读取一次、求值一次、按序执行的语义{dynamic}.(1)中的花括号是显式类型参数/接受者类型注解标明这是一个动态调用通配形式参数写作wildcard dynamic _#wc0#formal如set g(wildcard dynamic _#wc0#formal) → void {}非法代码如super、访问不存在的 settersuper.e同样以invalid-expression形式保留在 IR 中便于下游阶段与调试器理解这里原本是坏代码。这意味着期望文件不只是文本比对它同时锁定了 kernel IR 的降级细节——一旦 CFE 调整了复合赋值的展开顺序、成员解析的限定方式或错误保留策略对应的.expect快照就会变化从而在 CI 中暴露行为变更。4. 测试配置与编译模式pkg/front_end/testcases/README.mdrasta 目录的上级文档说明本目录及子目录的所有测试都会在多种不同配置下编译以覆盖package:front_endFasta的各个编译阶段配置的权威定义在 pkg/front_end/testing.json。与 rasta 目录直接相关的配置包括配置期望文件后缀状态文件独立测试入口Dart 3.0strong mode.strong.expectstrong.statusstrong_suite.dartDart 3.0 outlines.outline.expectoutline.statusoutline_suite.dart模块化modular编译.strong.modular.expectmodular.status—文本 outline.textual_outline.expect/.textual_outline_modelled.expecttextual_outline.status—README 特别强调strong mode 配置还会解析测试文件中的注释能精确匹配编译器内部细节如某个表达式的推断类型、某位置是否产生了警告因此.strong.expect的比对粒度比普通文本快照更细。rasta/目录中绝大多数.dart都配套了全部六套期望文件说明这批回归用例默认跑在所有上述配置下而.strong.transformed.expect的存在还表明存在一个转换后transformed的编译输出快照。从源码结构看各配置对应 CFE 的不同处理流水线直接编译、生成 outline、模块化增量编译、文本形式 outline 等同一份测试输入在不同流水线上应当产生一致的语义结果——这正是回归测试的价值所在。5. 运行测试与更新期望5.1 全量/单点更新期望按 testcases/README.md 的说明批量更新所有测试期望耗时较长仅当大量测试需更新时使用dart pkg/front_end/tool/update_expectations.dart更新单个测试的期望传入文件夹/测试名dart pkg/front_end/tool/update_expectations.dart general/abstract_instantiation更新某个文件夹内全部测试的期望在文件夹名后加/...dart pkg/front_end/tool/update_expectations.dart general/...对 rasta 目录可类比执行dart pkg/front_end/tool/update_expectations.dart rasta/...。5.2 按配置单独更新特定配置下的期望更新需要显式传入配置名与-DupdateExpectationstrueoutlines 配置./pkg/front_end/tool/cfe testing -DupdateExpectationstrue outline/test1 outline/test2 ...strong mode 配置额外加-DupdateCommentstrue以同步更新注释级期望./pkg/front_end/tool/cfe testing -DupdateExpectationstrue -DupdateCommentstrue strong/test1 strong/test2 ...注意update_expectations.dart和tool/cfe属于修改仓库内容的开发流程仅适合 SDK 开发者在本地提交变更前运行对一般读者而言这些命令用于理解期望文件是如何生成的。CI 中的常规做法是不更新期望直接跑既有测试任何.expect与当前编译输出的不一致都会被当作失败上报。5.3 状态文件的作用rasta/没有自己的.status文件但配置级状态文件如 strong.status、outline.status、modular.status位于testcases/顶层用于在特定配置下跳过或标记已知失败的用例。当你在某个平台/配置下看到 rasta 测试被 skip 时应先检查对应配置的状态文件。6. 典型回归案例剖析6.1issue_000001.dart参数数量错误不再崩溃测试输入issue_000001.darttest0(x) { print(test0); } main() { // Incorrect number of arguments, should be NoSuchMethodError but crashes. test0(0, 1); }注释揭示了历史缺陷调用test0(0, 1)时参数数量错误语义上应触发NoSuchMethodError但旧实现会崩溃。期望文件中 CFE 正确报出Too many positional arguments: 1 allowed, but 2 found.并以invalid-expression保留坏表达式继续产出 kernel——这就是从崩溃到可诊断的回归修复写照。6.2issue_*编号的阅读方式rasta/内issue_000001到issue_000081等编号来自 rasta 仓库的缺陷跟踪体系命名本身即历史 bug 清单。当你在 SDK 开发中改动解析器、类型检查器或 kernel 生成代码时如果某个 rasta 用例变红很可能就是你改变了与历史缺陷相关的行为——此时应回到*.dart顶部注释与期望文件头部Problems in library:清单确认新行为是否符合语言规范。7. 总结如何在 SDK 开发中用好这批测试回顾全文pkg/front_end/testcases/rasta是历史缺陷 语言特性 错误诊断三位一体的回归资产读用例*.dart是输入*.strong.expect是最全的期望含诊断与 IR两者对照即可理解某个语法结构在 CFE 中的编译结果查行为变更修改pkg/front_end的解析、类型推断或 IR 生成逻辑后运行 rasta 相关测试观察哪些.expect出现 diff更新期望确认新行为正确后使用dart pkg/front_end/tool/update_expectations.dart rasta/...或按配置的cfe testing -DupdateExpectationstrue …命令刷新快照这属于开发者本地流程需谨慎提交追溯历史每个issue_*编号都是可检索的历史缺陷遇到相关报错时可反向查找原始问题。对任何 Dart 编译链路VM、dart2js、dart2wasm的开发者而言rasta/都是一份高质量的前端行为契约——理解其结构与期望格式是参与 Dart SDK 编译器开发的基础功。赞分享编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载相关推荐B站评论如何完整获取BilibiliCommentScraper 爬虫工具从入门到实战B站评论如何完整获取BilibiliCommentScraper 爬虫工具从入门到实战 如果你正在做内容运营、用户研究或舆情分析一定遇到过这种尴尬明明想分编程语言编译器语言运行时标准库开发工具Dart SDK 测试状态文件.status完全指南格式语法、期望值体系与 test.dart 运行机制Dart SDK 测试状态文件.status完全指南格式语法、期望值体系与 test.dart 运行机制 导读 Dart 官方仓库 sdk1/sdk 编程语言编译器语言运行时标准库开发工具M/o/Vfuscator编译器测试框架回归测试套件M/o/Vfuscator编译器测试框架回归测试套件 你是否在开发M/o/Vfuscator编译器时遇到过这些问题新功能上线后旧代码突然失效算法优化后加密编译器上一篇Dear PyGui终极布局指南5种容器管理技巧打造专业级界面下一篇gpui-kit Stepper 组件完全指南用 GPUI 构建多步骤导航流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表