- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
copy.test.w_compile_tf-aws.md是 Wing 仓库中 Hangar 端到端测试套件自动生成的一个编译产物快照:它记录了把 copy.test.w 这份 Wing 测试程序以-t tf-aws目标编译后,在main.tf.json中生成的完整 Terraform 声明。读懂这份快照,就能理解三件事:Wing 如何把一个cloud.Bucket构造翻译成 AWS S3 的 Terraform 资源、Bucket 的默认 CORS 配置如何被固化进基础设施、以及 Hangar 是如何用「Markdown 文件快照」这类机制把整套测试语料的编译结果纳入回归校验的。
快照文件本身记录了什么
该快照 copy.test.w_compile_tf-aws.md 的标题行格式为:
# [copy.test.w](https://link.gitcode.com/i/3e5d96f78fc6b5d5db3c1e1d63c1fd70) | compile | tf-aws即「源文件copy.test.w,测试阶段compile,目标平台tf-aws」。正文是一个main.tf.json代码块,核心内容如下:
{ "//": { "metadata": { "backend": "local", "stackName": "root" }, "outputs": {} }, "provider": { "aws": [{}] }, "resource": { "aws_s3_bucket": { "Bucket": { "//": { "metadata": { "path": "root/Default/Default/Bucket/Default", "uniqueId": "Bucket" } }, "bucket_prefix": "bucket-c88fdc5f-", "force_destroy": false } }, "aws_s3_bucket_cors_configuration": { "Bucket_CorsConfiguration-1357ca3a_A4CCA40A": { "//": { "metadata": { "path": "root/Default/Default/Bucket/CorsConfiguration-1357ca3a", "uniqueId": "Bucket_CorsConfiguration-1357ca3a_A4CCA40A" } }, "bucket": "${aws_s3_bucket.Bucket.id}", "cors_rule": [ { "allowed_headers": ["*"], "allowed_methods": ["GET", "POST", "PUT", "DELETE", "HEAD"], "allowed_origins": ["*"], "expose_headers": [], "max_age_seconds": 0 } ] } } } }逐段解读:
provider.aws:声明使用 AWS Provider,这是tf-aws目标的基础。aws_s3_bucket.Bucket:Wing 代码里的let b = new cloud.Bucket();被翻译成这个 S3 桶资源。bucket_prefix取值bucket-c88fdc5f-(带尾部-以便区分「Wing 生成的前缀」与「Terraform 随机生成的后缀」),force_destroy为false。aws_s3_bucket_cors_configuration:桶上的默认 CORS 规则。之所以无参new cloud.Bucket()也会生成 CORS 资源,是因为BucketProps.cors选项默认值为true,会应用 SDK 中定义的DEFAULT_BUCKET_CORS_CONFIGURATION——允许所有来源、GET/POST/PUT/DELETE/HEAD方法、max_age_seconds: 0,与快照 JSON 完全一致。"//"注释块中的metadata.path(如root/Default/Default/Bucket/Default)是 Wing 应用树的构造路径,uniqueId是 Terraform 资源地址中的唯一标识;stackName: "root"表示该栈的命名。
这份快照的价值在于:它把「一行 Wing 代码 → 两份 Terraform 资源」这一编译结果钉死下来,任何 SDK 改动导致输出变化时,快照对比会立刻报警。
配套源码:copy.test.w 在验证什么
快照的源头 copy.test.w 是一个cloud.Bucket.copy()的 SDK 集成测试:
bring cloud; bring util; bring expect; let b = new cloud.Bucket(); test "copy()" { let assertThrows = (expected: str, block: (): void) => { let var error = false; try { block(); } catch actual { expect.equal(actual, expected); error = true; } expect.equal(error, true); }; let UNEXISTING_KEY = "no-such-file.txt"; let OBJECT_DOES_NOT_EXIST_ERROR = "Source object does not exist (srcKey={UNEXISTING_KEY})."; let KEY1 = "file1.main.w"; let VALUE1 = "bring cloud;"; let KEY2 = "file2.txt"; let VALUE2 = { msg: "Hello world!" }; b.put(KEY1, VALUE1); b.putJson(KEY2, VALUE2); let file1SrcMetadata = b.metadata(KEY1); let file2SrcMetadata = b.metadata(KEY2); // Sleep 2s to ensure 'metadata.lastModified' changes upon copy. util.sleep(2s); b.copy(KEY1, KEY1); b.copy(KEY2, "dir/{KEY2}"); let file1DstMetadata = b.metadata(KEY1); let file2DstMetadata = b.metadata("dir/{KEY2}"); assert(file1SrcMetadata.contentType == file1DstMetadata.contentType); assert(file1SrcMetadata.size == file1DstMetadata.size); assert(file1SrcMetadata.lastModified != file1DstMetadata.lastModified); assert(file2SrcMetadata.contentType == file2DstMetadata.contentType); assert(file2SrcMetadata.size == file2SrcMetadata.size); assert(file2SrcMetadata.lastModified != file2DstMetadata.lastModified); assert(b.get(KEY2) == b.get("dir/{KEY2}")); assertThrows(OBJECT_DOES_NOT_EXIST_ERROR, () => { b.copy(UNEXISTING_KEY, KEY1); }); }测试覆盖四个行为要点:
- 同键覆盖拷贝(
b.copy(KEY1, KEY1))后contentType/size不变、lastModified变化; - 跨键拷贝到
dir/file2.txt后内容一致(b.get相等); - JSON 对象值(
putJson写入)同样可拷贝; - 源对象不存在时抛出确定性的错误文案
Source object does not exist (srcKey=...)。
这个错误文案与 AWS 平台 inflight 实现精确对应。shared-aws/bucket.inflight.ts 中的copy()先用HeadObjectCommand取源对象的属性,再用CopyObjectCommand以MetadataDirective: "REPLACE"把ContentType、ContentLanguage、ContentEncoding、ContentDisposition、CacheControl、Expires、Metadata等属性原样带到目标键(等价于 AWS CLI 的aws s3 cp --copy-props);捕获NotFound时抛出上述错误信息。copy作为 inflight 操作被声明在 cloud/bucket.ts 的BucketInflightMethods枚举中(COPY = "copy"),各平台(AWS/GCP/Azure/sim)分别提供同名实现,这正是 Wing「一套 API、多平台落地」模型的体现。
而wing test -t sim一侧的运行结果被另一份快照钉住:copy.test.w_test_sim.md 中记录的 stdout 为:
pass ─ copy.test.wsim » root/Default/test:copy() Tests 1 passed (1) Snapshots 1 skipped Test Files 1 passed (1) Duration <DURATION>其中Duration <DURATION>这类占位符是输出脱敏后的结果(详见下文sanitizeOutput)。两份快照合起来构成「编译产物 + 运行时行为」的双重回归基线。
快照是如何生成的:Hangar 的测试语料管线
这份.md快照不是人手维护的,而是 tools/hangar 测试套件自动产出的。从源码结构看,其管线为:
- 语料扫描与用例生成:generate_tests.ts 递归扫描 tests/sdk_tests 目录下的每个
.w文件,为每个文件生成一个*.test.ts用例,里面固定包含两条测试:wing compile -t tf-aws(调用compileTest)与wing test -t sim(调用testTest),并支持通过文件内的 meta 注释指定环境变量、额外命令参数或.skip跳过。 - 编译与产物收集:generated_test_targets.ts 中的
compileTest先清理target/<name>.tfaws目录,再通过runWingCommand执行wing compile(附加-t tf-aws);若是入口文件(.main.w/.test.w等),就把产出的main.tf.json读入fileMap,并收集.wing/目录下匹配的 inflight/preflight JS 文件(本语料中includeJavaScriptInSnapshots为false,故快照只含main.tf.json)。 - 命令执行与输出脱敏:utils.ts 中的
runWingCommand以--no-update-check --no-analytics启动 wing CLI 并按退出码断言;sanitizeOutput把时间戳、端口、IP、绝对路径等易变内容替换为<TIMESTAMP>、<PORT>、<ABSOLUTE>等占位符,保证快照稳定。 - Terraform 产物脱敏:
sanitize_json_paths会移除main.tf.json顶层的terraform块与metadata.version,并把资产哈希、绝对路径等替换为<ASSET_KEY>、<SOURCE>等占位符——这就是为什么快照中看不到terraform.backend的完整细节与 CDKTF 版本号。 - 落盘为 Markdown 快照:
createMarkdownSnapshot把fileMap按文件名排序、逐个包进对应扩展名的代码块,拼成「# [源文件] | 测试阶段 | 目标+ 若干## 文件名小节」的 Markdown,最终通过expect(md).toMatchFileSnapshot(snapPath)与snapshots/test_corpus 下已有文件对比,文件名约定为<源文件名>_<测试阶段>_<目标>.md,本例即copy.test.w_compile_tf-aws.md。
快照里每个字段的 SDK 来源
把快照字段映射回 tf-aws 平台实现 target-tf-aws/bucket.ts,可以确认输出并非巧合:
- 桶前缀
bucket-c88fdc5f-:createEncryptedBucket通过ResourceNames.generateName(scope, BUCKET_PREFIX_OPTS)生成确定性前缀;BUCKET_PREFIX_OPTS限定最长 37 字符、全小写、剔除非法字符,并强制以-结尾以区分生成部分与 Terraform 随机后缀。由于命名基于应用/构造上下文哈希得出,同一份代码在任何机器上编译都会得到同一个前缀,这正是快照可跨环境复现的前提。 force_destroy: false:对应BucketProps.forceDestroy(默认false);只有当App处于测试环境(isTestEnvironment)或显式传参时才会置真。- CORS 资源:构造函数中
props.cors ?? true为真时调用addCorsRule(props.corsOptions ?? cloud.DEFAULT_BUCKET_CORS_CONFIGURATION);addCorsRule惰性创建S3BucketCorsConfiguration,用Lazy.anyValue把所有已累积的规则一次性展开为cors_rule数组——所以无参构造恰好产出快照里那一条「全放行」规则。资源 IDCorsConfiguration-1357ca3a取自构造地址(node.addr)末 8 位,A4CCA40A是 CDKTF 追加的哈希后缀。 metadata.path:root/Default/Default/Bucket/Default记录了构造在 Wing 应用树中的位置(应用根 → 测试作用域Default→ 变量b的构造作用域 →Bucket→ 内部S3Bucket),便于把 Terraform 资源与 Wing 源码节点一一对应。
如何在本地复现与验证
- 查看该语料的完整产物:对比
__snapshots__/test_corpus/sdk_tests/bucket/下同源的copy.test.w_compile_tf-aws.md(本文主体)与copy.test.w_test_sim.md(sim 运行日志)。 - 本地执行 Wing 侧等价操作:在 tests/sdk_tests/bucket 目录下执行
wing compile copy.test.w -t tf-aws生成target/copy.test.tfaws/main.tf.json,再执行wing test copy.test.w -t sim运行 inflight 断言;注意这依赖已安装且与仓库版本匹配的wingCLI(Hangar 内部通过runWingCommand调用的是本地构建产物,并带--no-update-check --no-analytics)。 - 回归校验:运行 Hangar 的 vitest 套件即可让
compileTest/testTest重新编译、重新生成 Markdown 并与__snapshots__逐字节对比;当且仅当 SDK 输出未变时快照保持稳定。若有意修改 SDK(例如调整默认 CORS 规则),则需同步接受新的快照。
小结
这份看似简单的main.tf.json快照,实际是 Wing「基础设施即代码 + 运行时行为」两条测试主线的交汇点:一方面,它锁定了cloud.Bucket在tf-aws平台上的精确合成结果(S3 桶 + 默认 CORS 规则,命名、metadata 路径可溯源到应用树节点);另一方面,与之配对的 sim 快照与 shared-aws/bucket.inflight.ts 的copy()实现共同证明了copy/metadata等 inflight API 在各平台上的行为契约。对于维护者,快照给出了「哪次改动改变了云资源输出」的即时信号;对于使用者,它演示了如何阅读 Wing 编译产物、把 Terraform 资源与 Wing 源码节点相互对映。
- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
相关推荐
Wing 编译快照解析:cloud.Bucket 的 list 行为与 tf-aws Terraform 输出
Wing 编译快照解析:cloud.Bucket 的 list 行为与 tf aws Terraform 输出 本文以 Wing 仓库中的编译快照文件 buck
编程语言编译器云原生语言运行时Wing 中 cloud.Bucket 如何编译为 AWS Terraform:从 Hangar 快照测试 aws-bucket 到 main.tf.json 的完整链路
Wing 中 cloud.Bucket 如何编译为 AWS Terraform:从 Hangar 快照测试 aws bucket 到 main.tf.json
编程语言编译器云原生语言运行时wing 端到端测试语料:hangar 快照如何验证 cloud.Bucket 的 AWS 扩展
wing 端到端测试语料:hangar 快照如何验证 cloud.Bucket 的 AWS 扩展 本文以 wing 仓库 E2E 测试语料中的 aws buck
编程语言编译器云原生语言运行时
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考