Skip to content

Lua API 测试用例设计

本文定义 Lua API 契约的测试矩阵。examples/hello_world/ 是用户参考示例,不作为 API 正确性的唯一验收;API 正确性必须由独立测试覆盖。

测试目标:

  • 每个 shield.* API 都有成功、失败和边界行为测试。
  • coroutine 挂起语义必须通过运行时测试验证。
  • 错误返回必须验证 ok=falseError.code
  • 旧 API 必须有负向测试,确保不会被重新引入。

测试目录建议

txt
tests/lua_api/
├── CMakeLists.txt
├── lua_api_test_harness.cpp
├── scripts/
│   ├── lifecycle_service.lua
│   ├── messaging_echo.lua
│   ├── timer_service.lua
│   ├── data_service.lua
│   ├── gateway_service.lua
│   └── legacy_api_service.lua
└── test_*.cpp

Harness 要求:

  • 能启动最小 shield_core + shield_lua runtime。
  • 能加载 Lua service module。
  • 能模拟 service 间 send/call
  • 能推进 fake clock 或使用可控 timer scheduler。
  • 能注入 fake DB/Redis backend。
  • 能捕获 Lua log、error、panic 和 dead letter。

LAPI-001 Module Loader

Case设置操作断言
LAPI-001-01Lua 文件返回 tablespawn servicespawn 成功
LAPI-001-02Lua 文件返回 nilspawn serviceinvalid_service_module
LAPI-001-03Lua 文件语法错误spawn servicescript_load_failed
LAPI-001-04module 顶层抛错spawn servicescript_load_failed

LAPI-002 Lifecycle

Case设置操作断言
LAPI-002-01on_init 无返回值spawn成功
LAPI-002-02on_init 返回 truespawn成功
LAPI-002-03on_init 返回 false, errspawninit_failed,name rollback
LAPI-002-04on_init 抛错spawninit_failed,触发 panic 记录
LAPI-002-05service exitshield.exit("normal")调用 on_exit("normal")
LAPI-002-06on_exit 调用 shield.callexit返回/记录 api_not_allowed_in_exit

LAPI-003 Registry

Case设置操作断言
LAPI-003-01spawn with nameshield.query(name)返回等价 handle
LAPI-003-02重复 namespawn secondname_conflict
LAPI-003-03init 失败占名query name不可见
LAPI-003-04shield.register 新 namequery可见
LAPI-003-05service exitquery old namesservice_not_found
LAPI-003-06invalid nameregisterinvalid_name

LAPI-004 Message Send

Case设置操作断言
LAPI-004-01target by namesend method argsreceiver handler 收到业务参数
LAPI-004-02target by handlesendreceiver 收到
LAPI-004-03target missingsendfalse, service_not_found
LAPI-004-04method missingsenddead letter 记录
LAPI-004-05mailbox fullsendmailbox_full
LAPI-004-06self-sendsend self不 reentrant,下一调度点执行

LAPI-005 Message Call

Case设置操作断言
LAPI-005-01callee returns one valuecalltrue, value
LAPI-005-02callee returns false, reasoncalltrue, false, reason
LAPI-005-03callee returns trailing nilcallargc 保留
LAPI-005-04callee throwscallfalse, handler_error
LAPI-005-05method missingcallfalse, method_not_found
LAPI-005-06timeoutcall_timeoutfalse, timeout
LAPI-005-07late responsecallee returns after timeoutresponse discarded
LAPI-005-08nested callhandler calls another serviceruntime thread 不阻塞

LAPI-006 Context

Case设置操作断言
LAPI-006-01send from A to BB calls shield.sender()equals A handle
LAPI-006-02handler returnssaved callback reads sendernil or context_expired
LAPI-006-03timer callbackshield.sender()nil
LAPI-006-04trace enabledcall chaintrace id propagated
LAPI-006-05deadline enabledcall_timeoutremaining deadline visible

LAPI-007 Timers And Tasks

Case设置操作断言
LAPI-007-01timer_onceadvance clockcallback once
LAPI-007-02timer fixed-delaycallback takes timenext run after callback completes
LAPI-007-03cancel timeradvance clockcallback not called
LAPI-007-04timer errorcallback throwson_error called,timer stops
LAPI-007-05sleepcoroutine sleepsruntime can process other message
LAPI-007-06forktask runsowner service tracked
LAPI-007-07service exitowned timers/taskscanceled

LAPI-008 Data API

Case设置操作断言
LAPI-008-01fake DB enabledshield.db.querytrue, rows
LAPI-008-02DB disabledshield.db.queryfalse, module_unavailable
LAPI-008-03SQL errorqueryfalse, db_query_failed
LAPI-008-04fake Redis enabledshield.redis.gettrue, value
LAPI-008-05Redis disabledshield.redis.getfalse, module_unavailable
LAPI-008-06subscribe then exitservice exitsubscription canceled

LAPI-009 Gateway API

Case设置操作断言
LAPI-009-01gateway servicesimulated connecton_connect(session) called
LAPI-009-02client frame decodeddeliver payloadon_client_message(session, payload) called
LAPI-009-03disconnectclose sessionon_disconnect(session, reason) called
LAPI-009-04send queue fullsession:sendfalse, session_send_queue_full
LAPI-009-05stale sessionsend after closefalse, session_closed

LAPI-010 Legacy API Rejection

Case操作断言
LAPI-010-01shield.service("x")nil or legacy_api_removed
LAPI-010-02shield.plugin.on(...)nil or legacy_api_removed
LAPI-010-03shield.db:query(...)fails; dot API required
LAPI-010-04service only defines on_message(src, type, data)send method does not dispatch through legacy entrypoint
LAPI-010-05DI injection APIunavailable

LAPI-011 Player Lifecycle

适用前提:shield_player 已启用。未启用时整个 LAPI-011 矩阵跳过,且 shield.player.* 调用应返回 module_unavailable

Case设置操作断言
LAPI-011-01setup 缺 auth 字段spawn player servicenil, setup_invalid
LAPI-011-02setup 缺 login 字段spawn player servicenil, setup_invalid
LAPI-011-03setup 缺 client_message 字段spawn player servicenil, setup_invalid
LAPI-011-04setup 缺 disconnect 字段触发断线进入重连窗口,默认实现被调用
LAPI-011-05setup 缺 logout 字段玩家离线PlayerManager.unregister 被调用
LAPI-011-06setup 缺 save 字段且未配置 persistence触发定时保存no-op,无 shield_data 调用
LAPI-011-07setup 覆盖 disconnect触发断线业务实现被调用,默认实现不执行
LAPI-011-08setup 完整 + persistence 启用触发 on_save 默认实现adapter 调用 shield_data 持久化白名单字段
LAPI-011-09setup 完整 + persistence 未启用触发 on_save 默认实现no-op,无 shield_data 调用
LAPI-011-10persistence save 失败(on_save_error="log"adapter 返回错误错误码 persistence_save_failed,service 继续运行
LAPI-011-11persistence save 失败(on_save_error="panic"adapter 返回错误触发 on_panic
LAPI-011-12persistence 字段含 functionsetupnil, setup_invalid
LAPI-011-13PlayerRef LuaPack 编码encode独立 type tag,字段完整
LAPI-011-14shield.player.resolve 本地在线玩家解析 ref返回 PlayerSession
LAPI-011-15shield.player.resolve 本地已下线玩家解析 refnil, player_not_found
LAPI-011-16shield.player.resolve 远端 ref(P0)解析 refnil, remote_resolve_unimplemented
LAPI-011-17shield.player.resolve 字段非法解析 refnil, invalid_player_ref
LAPI-011-18cross-service 传 PlayerRefsend payloadreceiver 拿到等价 ref
LAPI-011-19cross-service 传 SessionHandlesend payloadruntime 拒绝并返回错误
LAPI-011-20cross-service 传完整 PlayerSessionsend payloadruntime 拒绝并返回错误

验收要求

  • 当前 CTest 已有 shield_runtime_lua_smoke 覆盖 YAML actors 启动、 shield.self/now/spawn/send/call/sender/names/exit/on_exit 的单节点同步路径; shield_runtime_registry_smoke 覆盖 query/register/unregister/names 的本地 registry 路径; shield_runtime_data_smoke 覆盖启用 DB/Redis mock pool 后的 Lua data API 返回形态。 它们不是完整 LAPI 矩阵的替代品。
  • Lua API 契约变更必须先更新本文。
  • 每个新增 API 至少补充一个成功用例和一个失败用例。
  • 每个错误码必须在测试中至少出现一次。
  • examples/hello_world/ 可以更贴近用户体验,但不能替代上述测试。

Apache License 2.0