test_host_unit.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. # tests/test_host_unit.py
  2. """Task 7: host.py — 登录链拼包纯函数(零真实网络)。"""
  3. import json
  4. import socket
  5. import time
  6. from types import SimpleNamespace
  7. from apilot.host import Host
  8. def test_login_2001_body_shape(tmp_path):
  9. """2001 body = b"uid/" + encode6(jwt) + b"/" + encode6(channel) + b"/1/0"。
  10. 与 cq2_pure_enter.login_gate() 第 124-125 行 逐字节一致。"""
  11. h = Host(14481607, "longwu988", "Longwu1988", state_dir=str(tmp_path))
  12. uid, jwt = "1186115037", "eyJfake.jwt.token"
  13. body = h.build_2001_body(uid, jwt)
  14. import sys
  15. sys.path.insert(0, "protocol_bot")
  16. from encode6bitbuf_final import encode6 # type: ignore
  17. assert body == f"{uid}/".encode() + encode6(jwt.encode()) + b"/" + encode6(b"110585") + b"/1/0"
  18. def test_create_role_101_body(tmp_path):
  19. """101 body = {"server_name":zone,"chr":name,"secsdk":"0","job":0,"sex":0,
  20. "account":uid,"sdkid":"110585"};中文/账号/区号全保留。"""
  21. h = Host(14481607, "u", "p", state_dir=str(tmp_path))
  22. body = json.loads(h.build_101_body("萌新1234", uid="u1", job=0, sex=0))
  23. assert body["chr"] == "萌新1234" and body["sdkid"] == "110585"
  24. assert body["server_name"] == 14481607
  25. assert body["account"] == "u1" and body["job"] == 0 and body["sex"] == 0
  26. assert body["secsdk"] == "0"
  27. def test_recv_with_pre_silent_server(tmp_path):
  28. """B-1 回归: 静默服务端 1s → _recv_with_pre 不抛 NameError,
  29. 超时后正常返回 (None, None)。"""
  30. h = Host(14481607, "u", "p", state_dir=str(tmp_path))
  31. a, b = socket.socketpair()
  32. fake = SimpleNamespace(sock=a, _buf=b"")
  33. h.nc.wire = fake
  34. a.settimeout(1.0)
  35. try:
  36. start = time.time()
  37. frame, pre = h._recv_with_pre(530, 1.0)
  38. assert frame is None and pre is None
  39. assert time.time() - start >= 0.9
  40. finally:
  41. b.close()
  42. a.close()
  43. def test_recv_with_pre_fragments_across_buf(tmp_path):
  44. """M-1 回归: 530 帧头 48 字节被 TCP 分片、前半留在 wire._buf,
  45. 下一轮 _buf+新数据重组后仍能命中; sid 取 m[0] 而非 recog。"""
  46. import struct
  47. import sys
  48. sys.path.insert(0, "protocol_bot")
  49. from encode6bitbuf_final import encode6 # type: ignore
  50. h = Host(14481607, "u", "p", state_dir=str(tmp_path))
  51. a, b = socket.socketpair()
  52. fake = SimpleNamespace(sock=a, _buf=b"")
  53. h.nc.wire = fake
  54. a.settimeout(1.0)
  55. m = (777, 530, 888, 0, 0, 0, 0, 0, 0)
  56. pkt = encode6(struct.pack("<9i", *m))
  57. assert len(pkt) == 48
  58. b.sendall(pkt[:20])
  59. time.sleep(0.15)
  60. frame, pre = h._recv_with_pre(530, 1.0)
  61. assert frame is None and pre is None
  62. assert fake._buf == pkt[:20]
  63. b.sendall(pkt[20:])
  64. try:
  65. frame, pre = h._recv_with_pre(530, 1.0)
  66. assert frame is not None and frame.msg_id == 530
  67. assert frame.recog == 888
  68. assert pre == 777
  69. assert fake._buf == b""
  70. finally:
  71. b.close()
  72. a.close()