Files
ngzz-mc/internal/netproto/protocol_test.go

88 lines
2.5 KiB
Go
Raw Permalink Normal View History

package netproto
import (
"bytes"
"math"
"testing"
)
// TestVarint 变长整数边界(网络协议.md §2)。
func TestVarint(t *testing.T) {
cases := []uint32{0, 1, 127, 128, 300, 16383, 16384, 1<<21 - 1, math.MaxUint32}
for _, want := range cases {
w := &Writer{}
w.Varint(want)
r := NewReader(w.B)
if got := r.Varint(); got != want || r.Err != nil {
t.Fatalf("varint %d 往返失败: got=%d err=%v", want, got, r.Err)
}
}
}
// TestFrame 帧编解码往返(网络协议.md §1)。
func TestFrame(t *testing.T) {
f := Frame{MsgID: MsgBlockChange, Flags: 0, Payload: BlockChange{X: 1, Y: 64, Z: -2, BlockID: 5, Meta: 0}.Encode()}
enc := EncodeFrame(f)
got, rest, err := DecodeFrame(enc)
if err != nil {
t.Fatalf("解码失败: %v", err)
}
if len(rest) != 0 {
t.Fatalf("应无剩余字节,实际 %d", len(rest))
}
if got.MsgID != f.MsgID || !bytes.Equal(got.Payload, f.Payload) {
t.Fatalf("帧往返不一致: %+v", got)
}
// 流式粘包:两帧连续
enc2 := EncodeFrame(Frame{MsgID: MsgHeartbeat, Payload: []byte{9, 9}})
stream := append(append([]byte{}, enc...), enc2...)
g1, rest, err := DecodeFrame(stream)
if err != nil || g1.MsgID != MsgBlockChange {
t.Fatalf("粘包第一帧解析失败: %v", err)
}
g2, rest2, err := DecodeFrame(rest)
if err != nil || g2.MsgID != MsgHeartbeat || len(rest2) != 0 {
t.Fatalf("粘包第二帧解析失败: %v", err)
}
}
// TestBlockChange 方块变更消息往返。
func TestBlockChangeMsg(t *testing.T) {
in := BlockChange{X: -17, Y: 63, Z: 42, BlockID: 7, Meta: 3}
out, err := DecodeBlockChange(in.Encode())
if err != nil {
t.Fatalf("解码失败: %v", err)
}
if out != in {
t.Fatalf("往返不一致: %+v != %+v", out, in)
}
}
// TestPlayerMove 玩家移动消息往返。
func TestPlayerMoveMsg(t *testing.T) {
in := PlayerMove{X: 8.5, Y: 64.0, Z: -3.25, Yaw: 1.57, Pitch: -0.5, OnGround: true}
out, err := DecodePlayerMove(in.Encode())
if err != nil {
t.Fatalf("解码失败: %v", err)
}
if out != in {
t.Fatalf("往返不一致: %+v != %+v", out, in)
}
}
// TestTruncated 截断数据必须报错(防崩溃,网络协议.md §8)。
func TestTruncated(t *testing.T) {
f := Frame{MsgID: MsgHandshake, Payload: []byte{1, 2, 3, 4}}
enc := EncodeFrame(f)
if _, _, err := DecodeFrame(enc[:len(enc)-2]); err == nil {
t.Fatal("截断帧应报错")
}
// 超长帧头应报错
bad := make([]byte, 8)
bad[0] = 0xFF
bad[1] = 0xFF
if _, _, err := DecodeFrame(bad); err == nil {
t.Fatal("超长帧头应报错")
}
}