test_env_stub.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # tests/test_env_stub.py
  2. """Task 5: EnvData + install_env (L_GameEnvManager/LuaBridgeCtl/FileUtils/gameEnviroment) + install_all 装配。"""
  3. import socket
  4. import threading
  5. import time
  6. import lupa.luajit21 as lj
  7. import pytest
  8. def test_env_manager_keys(tmp_path):
  9. from apilot.stubs.env import EnvData, install_env
  10. rt = lj.LuaRuntime()
  11. env = EnvData({
  12. "uid": "1186115037",
  13. "token": "jwt.x",
  14. "isBoxLogin": 1,
  15. "signkey": "k" * 32,
  16. })
  17. install_env(rt, env, str(tmp_path))
  18. assert rt.eval("L_GameEnvManager:GetEnvDataByKey('uid')") == "1186115037"
  19. assert rt.eval("L_GameEnvManager:GetEnvDataByKey('isBoxLogin')") == 1
  20. assert rt.eval("L_GameEnvManager:GetEnvDataByKey('missing')") is None
  21. rt.execute("global = global or {}; global.L_GameEnvManager = L_GameEnvManager")
  22. assert rt.eval("global.L_GameEnvManager:GetEnvDataByKey('token')") == "jwt.x"
  23. def test_bridge_ctl_and_fileutils(tmp_path):
  24. from apilot.stubs.env import EnvData, install_env
  25. rt = lj.LuaRuntime()
  26. install_env(rt, EnvData({}), str(tmp_path))
  27. # 心跳开关默认开
  28. assert rt.eval("LuaBridgeCtl:Inst():GetModulesSwitch(2)") == 1
  29. rt.execute("LuaBridgeCtl:Inst():SetModulesSwitch(2, 1)")
  30. assert rt.eval("LuaBridgeCtl:Inst():GetModulesSwitch(2)") == 1
  31. # FileUtils 写入相对路径
  32. rt.execute("cc.FileUtils:getInstance():writeStringToFile('hi', 'a.txt')")
  33. assert (tmp_path / "a.txt").read_text() == "hi"
  34. # GET_STRING 未命中返回空串
  35. assert rt.eval("GET_STRING(99999)") == ""
  36. def test_fileutils_path_safety(tmp_path):
  37. """writeStringToFile/isFileExist 拒绝逃逸 state_dir 的相对路径。"""
  38. from apilot.stubs.env import EnvData, install_env
  39. rt = lj.LuaRuntime()
  40. install_env(rt, EnvData({}), str(tmp_path))
  41. # 子目录写入 OK
  42. rt.execute("cc.FileUtils:getInstance():writeStringToFile('ok', 'sub/b.txt')")
  43. assert (tmp_path / "sub" / "b.txt").read_text() == "ok"
  44. # writeStringToFile 路径逃逸被拒
  45. with pytest.raises(Exception):
  46. rt.execute("cc.FileUtils:getInstance():writeStringToFile('x', '../escape.txt')")
  47. # isFileExist 逃逸路径返回 false
  48. assert rt.eval("cc.FileUtils:getInstance():isFileExist('../escape.txt')") is False
  49. def test_install_all_networkctl_roundtrip(tmp_path):
  50. """install_all 装配后 Lua 侧可经 global.networkCtl 走 netClient 抵达环回网关。"""
  51. from apilot.stubs import install_all
  52. from apilot.stubs.env import EnvData
  53. from apilot.stubs.netclient import NetClientStub
  54. from apilot.stubs.networkctl import NetworkCtlStub
  55. from apilot.stubs.scheduler import Scheduler
  56. received = bytearray()
  57. finished = threading.Event()
  58. def gateway(server_sock):
  59. conn, _ = server_sock.accept()
  60. try:
  61. conn.settimeout(2.0)
  62. while not finished.is_set():
  63. try:
  64. chunk = conn.recv(4096)
  65. except (socket.timeout, OSError):
  66. break
  67. if not chunk:
  68. break
  69. received.extend(chunk)
  70. finally:
  71. conn.close()
  72. server_sock.close()
  73. srv = socket.socket()
  74. srv.bind(("127.0.0.1", 0))
  75. srv.listen(1)
  76. port = srv.getsockname()[1]
  77. threading.Thread(target=gateway, args=(srv,), daemon=True).start()
  78. nc = NetClientStub()
  79. nc.connect("127.0.0.1", port)
  80. ctl = NetworkCtlStub(nc)
  81. sched = Scheduler()
  82. env = EnvData({"uid": "u1"})
  83. rt = lj.LuaRuntime()
  84. install_all(rt, nc, ctl, sched, env, str(tmp_path))
  85. rt.execute("global.networkCtl:SendMsg(529, 12345, 1, 2, 3, 'hi', 2)")
  86. time.sleep(0.2)
  87. finished.set()
  88. nc.disconnect()
  89. time.sleep(0.1)
  90. # 48 字节 encoded header + 2 字节 body
  91. assert len(received) >= 50, f"expected 50 bytes, got {len(received)}: {bytes(received)!r}"
  92. assert bytes(received[48:50]) == b"hi"