86 lines
2.4 KiB
Go
86 lines
2.4 KiB
Go
|
|
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("未收到方块变更")
|
|||
|
|
}
|
|||
|
|
}
|