Wing 语言 math.sin 正弦函数实战:从边界断言到 hangar 快照测试
Wing 语言 math.sin 正弦函数实战:从边界断言到 hangar 快照测试
本文以 Wing 标准库 math 模块中的正弦函数 math.sin 为核心,结合仓库中的 SDK 测试用例 sin.test.w、底层实现 math.ts 以及 hangar 测试框架的 快照输出,完整讲解 math.sin 的调用方式、边界行为、运行测试的方法,并深入剖析 Wing 的 test 关键字、simulator 测试流程与快照校验机制。读完本文,你将能在自己的 Wing 项目中正确使用 math.sin 及配套三角函数,并理解 SDK 测试是如何被 hangar 自动采集与快照验证的。
math.sin 是什么:签名与语义
math.sin 是 Wing 标准库 math 模块(SDK 中对应 packages/@winglang/sdk/src/math/math.ts 的 Util 类)提供的三角函数之一,用于计算一个数的正弦值。它的函数签名在官方 API 参考文档 docs/api/04-standard-library/math/api-reference.md 中定义为:
bring math;
math.sin(value: num);
要点说明:
- 参数类型:
value是必填的num(Wing 中的数值类型),表示以**弧度(radians)**为单位的角度; - 返回值:返回该角度的正弦值(
num); - 使用前提:必须先通过
bring math;引入math模块才能调用; - 调用形式:
math.sin是Util类上的静态方法,因此在 Wing 代码中以math.sin(...)直接调用,无需实例化对象。
从源码结构看,Util 类还导出了大量数学工具方法,包括绝对值、取整、对数、随机数、均值、组合数等,本文聚焦其中的正弦函数及其测试链路。
从 SDK 测试用例看 sin 的边界行为
仓库中的 SDK 数学测试目录 tests/sdk_tests/math/ 下共有 33 个针对 math 模块的测试文件(abs、acos、sin、tan、factorial 等)。其中 sin.test.w 完整覆盖了 math.sin 的核心边界场景,全文如下:
bring math;
assert(math.sin(-0) == -0);
assert(math.sin(0) == 0);
assert(math.sin(1) == 0.8414709848078965);
assert(math.sin(-5) == 0.9589242746631385);
assert(math.sin(math.PI / 2) == 1);
test "inflight sine" {
assert(math.sin(-0) == -0);
assert(math.sin(0) == 0);
assert(math.sin(1) == 0.8414709848078965);
assert(math.sin(-5) == 0.9589242746631385);
assert(math.sin(math.PI / 2) == 1);
}
该文件一次覆盖了五个关键事实,每个断言都值得逐条分析:
| 断言 | 期望值 | 语义说明 |
|---|---|---|
math.sin(-0) == -0 |
-0(负零) |
负零的符号被保留,体现 IEEE 754 浮点语义;若写成 == 0 虽也能通过(-0 == 0),但 -0 的精确返回体现了底层实现直接透传 JavaScript Math.sin 的行为 |
math.sin(0) == 0 |
0 |
零弧度正弦为 0 |
math.sin(1) == 0.8414709848078965 |
0.8414709848078965 |
1 弧度(约 57.3°)的正弦值,断言直接写死完整精度,防止实现回归 |
math.sin(-5) == 0.9589242746631385 |
0.9589242746631385 |
负角度输入:sin(-5) ≈ 0.9589,验证负参数路径 |
math.sin(math.PI / 2) == 1 |
1 |
90°(π/2 弧度)正弦恰为 1,同时验证了常量 math.PI 与 sin 的联用 |
测试文件还演示了 Wing 特有的双相位执行模型:文件顶层的 assert 在**preflight(预飞行/编译期)**阶段直接执行,作为编译期的数学验证;而 test "inflight sine" { ... } 声明的测试块则在测试运行阶段(simulator 或云端)执行,验证 math.sin 在 inflight(运行时) 环境下同样可用。也就是说,同一个正弦函数在两种执行相位下都经过了断言校验。
底层实现:Util.sin 如何映射到 Math.sin
math.sin 的实现非常薄,它直接委托给 JavaScript 引擎的内置 Math.sin。在 packages/@winglang/sdk/src/math/math.ts 中可以找到:
/**
* Returns the sine of a number in radians.
* @param value A number representing an angle in radians.
*/
public static sin(value: number): number {
return Math.sin(value);
}
由此可以得出几个实现层面的结论:
- 精度一致性:
sin.test.w中断言的0.8414709848078965等浮点结果,正是 JavaScriptMath.sin在 IEEE 754 双精度下的计算结果,测试因此可以直接与底层引擎行为对齐; - 负零行为:
Math.sin(-0)在 JavaScript 中返回-0,所以Util.sin透传后也保留负零,这正是assert(math.sin(-0) == -0)能成立的根本原因; - 纯计算、无云资源:
math.sin不依赖任何云服务。这一点在 hangar 的 tf-aws 编译快照 sin.test.w_compile_tf-aws.md 中得到印证——编译到tf-aws目标后生成的main.tf.json中只有awsprovider 的空配置,没有任何基础设施资源。也就是说,纯数学运算不会在云上产生任何资源开销,这是math模块区别于cloud.Bucket、cloud.Queue等资源类模块的关键特征。
Util 类还通过 _toInflightType() 与 InflightClient.forType(...) 配合,使这些静态数学方法可以在 inflight 闭包中被引用,这也是 test "inflight sine" 能在运行时调用 math.sin 的基础设施。
配套常量与三角函数族
math.sin 常与 math 模块的其他常量和三角函数配合使用,测试用例中的 math.PI / 2 就是一个典型例子。Util 类提供四个数学常量(均在 math.ts 中定义):
| 常量 | 值 | 说明 |
|---|---|---|
math.PI |
Math.PI |
圆周率 π,圆周长与直径之比 |
math.TAU |
2 * Math.PI |
圆周率 τ,圆周长与半径之比(2π) |
math.E |
Math.E |
自然常数 e,约等于 2.71828 |
math.INF |
Number.POSITIVE_INFINITY |
正无穷 |
与 sin 同族的三角函数还包括:
- 基础三角:
math.cos(value)、math.tan(value)(均以弧度输入); - 反三角:
math.asin(value)、math.acos(value)(要求-1 ≤ value ≤ 1,越界会抛出"Input value must be between -1 and 1, inclusive.")、math.atan(value)、math.atan2(y, x); - 余割族:
math.sec(value)(1 / cos)、math.csc(value)(1 / sin)、math.cot(value)(1 / tan),以及对应的反函数math.asec、math.acsc、math.acot(后两者要求|value| ≥ 1); - 角度换算:
math.degreesToRadians(degrees)与math.radiansToDegrees(radians),可用于将日常使用的角度制转换为sin所需的弧度制。
完整的函数签名与参数说明可见 docs/api/04-standard-library/math/api-reference.md,其中每个函数都给出了可直接复制的 Wing 调用示例。
运行测试:wing test 与快照输出解读
在 simulator 中运行
将 sin.test.w 放到任意目录,执行(--target sim 是默认目标,可省略):
wing test sin.test.w --target sim
对应的 hangar 快照 sin.test.w_test_sim.md 记录了标准输出:
pass ─ sin.test.wsim » root/Default/test:inflight sine
Tests 1 passed (1)
Snapshots 1 skipped
Test Files 1 passed (1)
Duration <DURATION>
逐行解读这份输出:
pass ─ sin.test.wsim » root/Default/test:inflight sine:测试用例inflight sine通过,运行目标是sin.test.wsim(即该文件编译成的 simulator 应用),测试路径为root/Default/test:inflight sine;Tests 1 passed (1):共 1 个测试全部通过;Snapshots 1 skipped:runner 的测试输出中有一项快照被跳过(测试未涉及快照比对场景,属正常现象);Duration <DURATION>:<DURATION>是 hangar 在比对快照前对动态耗时字段做的归一化替换——由于每次运行耗时不同,hangar 用占位符代替实际时间,从而保证快照内容可稳定比对。
关于 test 关键字的更多用法(测试隔离执行、-o/--output-file 导出 JSON 结果、tf-aws 云端运行、--no-clean 保留资源等),可参考 docs/docs/02-concepts/04-tests.md。
在 tf-aws 目标上编译
同一份测试还会被 hangar 编译到 tf-aws 目标,快照 sin.test.w_compile_tf-aws.md 中的 main.tf.json 输出为:
{
"//": {
"metadata": {
"backend": "local",
"stackName": "root"
},
"outputs": {}
},
"provider": {
"aws": [
{}
]
}
}
这份空壳 Terraform 配置再次证明:math.sin 是纯函数计算,编译到云目标时不会产生任何 AWS 资源定义。如果你在测试代码里只做数学运算,云端部署的 Terraform 状态文件就是如此干净——只有 provider 声明,没有资源块。
hangar 快照测试机制:快照如何生成与校验
上面两份 .md 快照并非手写维护,而是由 Wing 的测试编排工具 hangar(位于 tools/hangar)自动生成与校验的。整个过程可以分为三条链路:
1. 测试用例生成:脚本 tools/hangar/src/generate_tests.ts 会递归扫描 tests/sdk_tests/ 等测试目录,为每个 .w 文件生成对应的 vitest 用例,例如对 sin.test.w 生成两类测试:
wing compile -t tf-aws:执行编译并校验 Terraform 产物快照;wing test -t sim:在 simulator 上运行测试并校验 stdout 快照。
生成器还支持读取 .w 文件头部的 meta 注释(parseMetaCommentFromPath)来决定是否跳过某类目标,并自动处理 target、node_modules 等目录的排除。
2. 快照存放:快照统一沉淀在 tools/hangar/snapshots/test_corpus/sdk_tests/math/ 目录,命名规则为 <文件名>_compile_tf-aws.md 与 <文件名>_test_sim.md,分别对应编译产物与 sim 测试输出。sin.test.w 的两个快照正是本文引用的这两份文件。
3. 动态内容归一化:为了让快照在每次 CI 运行中保持字节级稳定,hangar 会对 <DURATION> 这类运行时差异字段做占位替换,因此快照可以长期作为回归基线:一旦 math.sin 的实现或测试断言发生变化(例如浮点结果被改动),CI 就会通过快照比对立即暴露差异。
从这层机制可以看出,sin.test.w 的测试并不只是"写几个断言",它同时承担了三重职责:preflight 期的数学正确性校验、inflight 期的运行时行为校验、以及 tf-aws 编译产物的回归守护——这正是 Wing SDK 质量保障链路的一部分。
小结
通过 math.sin 这个入口,我们完整走通了一条从「语言 API → 测试用例 → 底层实现 → 测试编排与快照」的链路:
- 使用层面:
bring math;后调用math.sin(弧度值)即可,配合math.PI、math.degreesToRadians可以方便地处理角度换算; - 语义层面:
sin直接透传 JavaScriptMath.sin,天然继承 IEEE 754 的精度与负零行为,且因为是纯计算,编译到任何云目标都不会产生基础设施资源; - 测试层面:Wing 的
test关键字支持 preflight 断言与 inflight 测试块,wing test --target sim即可本地验证,而 hangar 会通过__snapshots__快照对 sim 输出与 tf-aws 编译产物做自动化回归校验。
如果你需要在 Wing 中做三角运算、波动模拟或任何角度相关的数值计算,math.sin 及配套的 cos、tan、反三角与角度换算函数,就是标准库给出的官方答案。