- 受控面 v0 六项冻结:getContext2d/onFrame/getInput/getAudioContext/time/random - getInput=归一化事件订阅面(5枚举,host注入桥+_emit测试口,dispose自动清理防泄漏);getAudioContext=lazy单例无工厂返null告警降级 - per-plugin 派生随机流(FNV-1a子种子,序列互不影响同seed复现,向后兼容回退);useContext 守卫(友好错误带插件名) - 向后兼容增量不bump版本;manifest schema 未动;三 lane 按此冻结面开工 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
135 lines
9.6 KiB
Plaintext
135 lines
9.6 KiB
Plaintext
# game-runtime 全量单测原始输出(node --test)
|
||
# 生成命令:bash scripts/test.sh
|
||
# 生成时间:2026-06-12 11:26:28 UTC
|
||
# node 版本:v24.16.0
|
||
# 覆盖:src/core/plugin.test.mjs(core 31:17 旧 + Gate0.1 新 14)+ src/plugins/_example/test/example.test.mjs(_example 7:5 旧 + Gate0.1 新 2)
|
||
# ============================================================================
|
||
|
||
[test.sh] 仓根:/root/games-development-ai/game-runtime
|
||
[test.sh] 收集测试文件(*.test.mjs / *.test.cjs)...
|
||
[test.sh] 共 2 个测试文件:
|
||
- src/core/plugin.test.mjs
|
||
- src/plugins/_example/test/example.test.mjs
|
||
[test.sh] 开始 node --test ...
|
||
|
||
[PluginRegistry] initAll 重复调用,已忽略(已处于 initialized)
|
||
[PluginRegistry] 插件 init 抛错(已隔离,不连坐):bad:Error: boom-init:bad
|
||
at Object.init (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:58:35)
|
||
at PluginRegistry.initAll (file:///root/games-development-ai/game-runtime/src/core/plugin.js:670:16)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:183:17)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
at Test.run (node:internal/test_runner/test:1372:12)
|
||
at async Test.processPendingSubtests (node:internal/test_runner/test:897:7)
|
||
[PluginRegistry] 跳过 init(依赖缺失,已隔离):needsX:Error: [PluginRegistry] 插件 needsX 依赖缺失:x(未注册)
|
||
at PluginRegistry.initAll (file:///root/games-development-ai/game-runtime/src/core/plugin.js:657:21)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:208:17)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
at Test.run (node:internal/test_runner/test:1372:12)
|
||
at async Test.processPendingSubtests (node:internal/test_runner/test:897:7)
|
||
[PluginRegistry] 插件 dispose 抛错(已隔离):bad:Error: boom-dispose:bad
|
||
at p.dispose (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:72:38)
|
||
at PluginRegistry.disposeAll (file:///root/games-development-ai/game-runtime/src/core/plugin.js:731:18)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:240:17)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
at Test.run (node:internal/test_runner/test:1372:12)
|
||
at async Test.processPendingSubtests (node:internal/test_runner/test:897:7)
|
||
[host-dev tick] 帧回调抛错(已隔离)frame=1:Error: frame-boom
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:320:33
|
||
at tick (file:///root/games-development-ai/game-runtime/src/core/plugin.js:481:11)
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:323:31
|
||
at getActual (node:assert:611:5)
|
||
at strict.doesNotThrow (node:assert:779:32)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:323:10)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
[host-dev tick] 帧回调抛错(已隔离)frame=2:Error: frame-boom
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:320:33
|
||
at tick (file:///root/games-development-ai/game-runtime/src/core/plugin.js:481:11)
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:323:44
|
||
at getActual (node:assert:611:5)
|
||
at strict.doesNotThrow (node:assert:779:32)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:323:10)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
[host-dev input] 输入 handler 抛错(已隔离)type=pointerdown:Error: input-boom
|
||
at Object.handler (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:442:41)
|
||
at HostDevInputBridge._emit (file:///root/games-development-ai/game-runtime/src/core/plugin.js:312:15)
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:445:43
|
||
at getActual (node:assert:611:5)
|
||
at strict.doesNotThrow (node:assert:779:32)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:445:10)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
[host-dev input] 输入 handler 抛错(已隔离)type=pointerdown:Error: input-boom
|
||
at Object.handler (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:442:41)
|
||
at HostDevInputBridge._emit (file:///root/games-development-ai/game-runtime/src/core/plugin.js:312:15)
|
||
at file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:445:81
|
||
at getActual (node:assert:611:5)
|
||
at strict.doesNotThrow (node:assert:779:32)
|
||
at TestContext.<anonymous> (file:///root/games-development-ai/game-runtime/src/core/plugin.test.mjs:445:10)
|
||
at Test.runInAsyncScope (node:async_hooks:227:14)
|
||
at Test.run (node:internal/test_runner/test:1306:25)
|
||
at Test.processPendingSubtests (node:internal/test_runner/test:897:18)
|
||
at Test.postRun (node:internal/test_runner/test:1447:19)
|
||
✔ 注册成功 + list/has/get 反映注册态 (8.102551ms)
|
||
✔ 重名注册抛错拒绝 (1.760719ms)
|
||
✔ 形状非法注册抛错(缺 name/version/init、dispose 非函数) (1.489075ms)
|
||
✔ init 按注册正序,dispose 按注册逆序(后进先出) (6.242631ms)
|
||
✔ disposeAll 幂等:重复调用不重复触发 dispose (3.960417ms)
|
||
✔ initAll 幂等:重复 init 不重复触发 init (2.555656ms)
|
||
✔ dispose 后再 initAll 抛错(生命周期非法转移) (0.997158ms)
|
||
✔ 单插件 init 抛错被隔离,其它插件照常 init (2.066683ms)
|
||
✔ 依赖缺失被隔离,不连坐其它插件 (1.518294ms)
|
||
✔ 依赖已注册则正常 init(声明依赖校验通过) (1.263549ms)
|
||
✔ 单插件 dispose 抛错被隔离,其它 dispose 照常 (1.127486ms)
|
||
✔ SeededRandom 确定性:同种子同序列,reseed 复位 (0.992655ms)
|
||
✔ HostDevTime:nowMs 走注入时钟,elapsedMs 自起点递增 (1.546431ms)
|
||
✔ getContext2d:注入 null 时返回 null(node 侧无 canvas 可容忍) (0.59474ms)
|
||
✔ onFrame + tick:帧回调被驱动,frame 从 1 单调,dt 透传 (0.856982ms)
|
||
✔ FrameHandle.cancel 注销帧回调 (0.664724ms)
|
||
✔ 帧回调抛错被隔离:不连坐同帧其它回调,也不中断后续帧 (1.526119ms)
|
||
✔ getInput 订阅:on 收到归一化事件,坐标/键码/时间戳正确(时间戳取自受控时间源) (1.107895ms)
|
||
✔ getInput.off / 句柄 cancel 退订:退订后不再收事件 (0.882527ms)
|
||
✔ 插件经 getInput 注册的订阅,dispose 时由注册器自动清理(防泄漏) (0.931805ms)
|
||
✔ 多插件各自的输入 scope 独立回收:dispose 一个不误伤其它(但本波整体 disposeAll 全回收) (0.564589ms)
|
||
✔ getInput 非法事件类型拒绝(防误用裸 DOM 事件名) (0.928869ms)
|
||
✔ getInput 单个 handler 抛错被隔离:不连坐同类型其它 handler (1.121242ms)
|
||
✔ getAudioContext 无工厂:返回 null 且仅告警一次(P6 容错降级,不抛错) (0.587583ms)
|
||
✔ getAudioContext 有工厂:lazy 创建 + 单例(多次调用返回同一实例,工厂只造一次) (0.45052ms)
|
||
✔ per-plugin 派生随机:两插件各取随机序列互不影响 + 同 seed 复现 (1.088156ms)
|
||
✔ per-plugin 派生随机:插件 A 先取随机不推进插件 B 的序列(独立性证明) (0.884436ms)
|
||
✔ deriveSeed 确定性:同(主种子,插件名)同子种子;异名/异主种子异子种子 (0.345888ms)
|
||
✔ 忘调 useContext 即 initAll:抛含修复提示的友好错误(非裸 TypeError) (0.617065ms)
|
||
✔ useContext 传 null/非对象:抛友好错误 (0.652191ms)
|
||
✔ useContext 在 initAll 之后调用:抛错并点出当前阶段 (0.503247ms)
|
||
✔ 空插件样例可被 PluginRegistry 全流程接纳(register/initAll/disposeAll) (8.867701ms)
|
||
✔ 受控面 onFrame:tick 驱动后探针帧数递增、记录最近随机值 (1.335529ms)
|
||
✔ 受控随机源注种子后确定可复现:同种子两实例随机序列一致 (1.654138ms)
|
||
✔ getContext2d 容忍 null(node 侧);注入 mock 上下文则探针 hasContext2d=true (0.816929ms)
|
||
✔ dispose 幂等且精确撤销帧回调:dispose 后再 tick 不再增帧 (0.623579ms)
|
||
✔ 受控面 getInput:_emit 驱动后探针 inputEvents 递增;dispose 后不再增(精确撤销) (0.909204ms)
|
||
✔ 受控面 getAudioContext:无工厂时 hasAudio=false(降级),注入工厂则 hasAudio=true (0.905139ms)
|
||
ℹ tests 38
|
||
ℹ suites 0
|
||
ℹ pass 38
|
||
ℹ fail 0
|
||
ℹ cancelled 0
|
||
ℹ skipped 0
|
||
ℹ todo 0
|
||
ℹ duration_ms 280.755392
|