zizi 6f854851f5 feat(game-runtime): core-protocol-v0 冻结(Gate0.1 受控面补丁,38/38 绿)
- 受控面 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>
2026-06-12 11:28:52 +00:00

135 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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