test_wire.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. # tests/test_wire.py
  2. import pytest
  3. from apilot.wire import Frame, pack_frame, unpack_stream
  4. def test_frame_roundtrip():
  5. f = Frame(recog=900000, msg_id=20, p1=123, p2=14481607, p3=8043,
  6. tail=7, body=b"*#acct/role/12345/9/1/0/110585/0/1/1/1/1")
  7. packed = pack_frame(f)
  8. frames, rest = unpack_stream(packed)
  9. assert rest == b""
  10. assert len(frames) == 1
  11. g = frames[0]
  12. assert (g.recog, g.msg_id, g.p1, g.p2, g.p3, g.tail, g.body) == \
  13. (f.recog, f.msg_id, f.p1, f.p2, f.p3, f.tail, f.body)
  14. def test_unpack_partial_packet():
  15. f = Frame(recog=0, msg_id=529, p1=0, p2=0, p3=0, tail=1, body=b"key32abc")
  16. packed = pack_frame(f)
  17. frames, rest = unpack_stream(packed[:-10]) # 掐掉10字节
  18. assert frames == [] and len(rest) == len(packed) - 10
  19. def test_pack_matches_reference_impl():
  20. """与 cq2_pure_enter.send() 的原始拼包逐字节一致(防字段序回归)。"""
  21. import struct, random
  22. sys_path_hack = __import__("sys"); sys_path_hack.path.insert(0, "protocol_bot")
  23. from encode6bitbuf_final import encode6
  24. random.seed(42)
  25. body = b"*#1186115037/role/1/2/3/1/0/110585/0/1/1/1/1"
  26. ref = encode6(struct.pack("<9i", 0, 20, 900000, 111, 14481607, 8043, 0, len(body), 9)) + body
  27. mine = pack_frame(Frame(recog=900000, msg_id=20, p1=111, p2=14481607, p3=8043, tail=9, body=body))
  28. assert mine == ref
  29. def test_recv_buffered_across_calls():
  30. """帧跨两次 recv() 到达不能丢(Wire 自持 buffer,rest 留存到下次)。"""
  31. import socket, struct, threading, time
  32. sys_path_hack = __import__("sys"); sys_path_hack.path.insert(0, "protocol_bot")
  33. from encode6bitbuf_final import encode6
  34. from apilot.wire import Wire
  35. srv = socket.socket(); srv.bind(("127.0.0.1", 0)); srv.listen(1)
  36. port = srv.getsockname()[1]
  37. body = b"key32/session123"
  38. head = struct.pack("<9i", 0, 529, 1, 0, 0, 0, 0, len(body), 1)
  39. wire_bytes = encode6(head) + body
  40. mid = len(wire_bytes) // 2
  41. def gateway():
  42. conn, _ = srv.accept()
  43. try:
  44. conn.setblocking(False)
  45. try:
  46. conn.recv(65536)
  47. except (BlockingIOError, OSError):
  48. pass
  49. conn.setblocking(True)
  50. conn.sendall(wire_bytes[:mid]) # 第一半
  51. time.sleep(0.2)
  52. conn.sendall(wire_bytes[mid:]) # 第二半
  53. time.sleep(0.2)
  54. finally:
  55. conn.close()
  56. srv.close()
  57. threading.Thread(target=gateway, daemon=True).start()
  58. w = Wire("127.0.0.1", port, timeout=2.0)
  59. f1 = w.recv(0.3) # 只能拿到第一半
  60. f2 = w.recv(0.3) # 第二半在此次补齐
  61. w.close()
  62. all_frames = f1 + f2
  63. assert len([f for f in all_frames if f.msg_id == 529]) == 1, f"got {all_frames}"
  64. g = next(f for f in all_frames if f.msg_id == 529)
  65. assert g.body == body