package netclient import ( "context" "testing" "time" "mc/internal/logx" "mc/internal/netproto" "mc/internal/netserver" ) // testServer 测试服务器:登录后发一个方块变更。 type testServer struct { t *testing.T sent chan struct{} } func (s *testServer) OnConnect(c *netserver.Conn) {} func (s *testServer) OnHandshake(c *netserver.Conn, hs netproto.Handshake) uint8 { if hs.ProtocolVersion != 1 { return 1 } return 0 } func (s *testServer) OnMove(c *netserver.Conn, m netproto.PlayerMove) { // 收到移动后回发一个方块变更(验证客户端接收链路) c.Send(netproto.Frame{MsgID: netproto.MsgBlockChange, Payload: netproto.BlockChange{ X: 1, Y: 2, Z: 3, BlockID: 5, Meta: 0, }.Encode()}) s.sent <- struct{}{} } func (s *testServer) OnDisconnect(c *netserver.Conn) {} // testHandler 客户端回调记录。 type testHandler struct { login chan uint8 blocks chan netproto.BlockChange } func newTestHandler() *testHandler { return &testHandler{login: make(chan uint8, 1), blocks: make(chan netproto.BlockChange, 4)} } func (h *testHandler) OnLogin(code uint8) { h.login <- code } func (h *testHandler) OnChunk(data []byte) {} func (h *testHandler) OnBlockChange(m netproto.BlockChange) { h.blocks <- m } // TestClientRoundtrip 客户端登录 → 发移动 → 收方块变更全链路(多人同步.md §2)。 func TestClientRoundtrip(t *testing.T) { log, _ := logx.New("", logx.LevelError) sh := &testServer{t: t, sent: make(chan struct{}, 1)} srv := netserver.New("127.0.0.1:0", log, sh) ctx, cancel := context.WithCancel(context.Background()) defer cancel() if err := srv.Listen(ctx); err != nil { t.Fatalf("监听失败: %v", err) } h := newTestHandler() c, err := Dial(srv.Addr(), netproto.Handshake{ProtocolVersion: 1, ClientID: "测试"}, h) if err != nil { t.Fatalf("拨号失败: %v", err) } defer c.Close() select { case code := <-h.login: if code != 0 { t.Fatalf("登录结果期望 0,实际 %d", code) } case <-time.After(3 * time.Second): t.Fatal("未收到登录结果") } // 发送移动 → 服务器回方块变更 c.SendMove(netproto.PlayerMove{X: 1, Y: 64, Z: 2}) select { case m := <-h.blocks: if m.X != 1 || m.Y != 2 || m.Z != 3 || m.BlockID != 5 { t.Fatalf("方块变更内容异常: %+v", m) } case <-time.After(3 * time.Second): t.Fatal("未收到方块变更") } }