- SetData 超长时 fmt.Errorf 结果未 return,超 65535 字节静默放行 → 改为返回错误 - ReadFrame 原实现 conn.Read 直读帧头(短读错位)且一次性 bufio.Reader 会丢弃 缓冲中的后续帧字节 → 统一改 io.ReadFull 精确读取,新增连续两帧回归测试 - 补齐单元测试(往返/流水线/超长/Marshal/RawHeader)、examples/frame 例程与 README
111 lines
2.6 KiB
Go
111 lines
2.6 KiB
Go
package frame
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net"
|
|
"testing"
|
|
)
|
|
|
|
func TestFrameRoundtrip(t *testing.T) {
|
|
c1, c2 := net.Pipe()
|
|
defer c1.Close()
|
|
defer c2.Close()
|
|
|
|
f := NewFrame(FrameVersion, 0x10, 42)
|
|
if err := f.SetData([]byte("hello frame")); err != nil {
|
|
t.Fatalf("SetData: %v", err)
|
|
}
|
|
|
|
go func() {
|
|
if err := WriteFrame(c1, f); err != nil {
|
|
t.Errorf("WriteFrame: %v", err)
|
|
}
|
|
}()
|
|
|
|
got, err := ReadFrame(c2)
|
|
if err != nil {
|
|
t.Fatalf("ReadFrame: %v", err)
|
|
}
|
|
if got.Version() != FrameVersion || got.Cmd() != 0x10 || got.StreamID() != 42 {
|
|
t.Errorf("帧头不符: %s", got.String())
|
|
}
|
|
if string(got.Data()) != "hello frame" {
|
|
t.Errorf("Data = %q, want hello frame", got.Data())
|
|
}
|
|
}
|
|
|
|
func TestFramePipelineRead(t *testing.T) {
|
|
// 连续两帧不丢数据(回归:旧实现用临时 bufio.Reader 会吞掉后续帧字节)
|
|
c1, c2 := net.Pipe()
|
|
defer c1.Close()
|
|
defer c2.Close()
|
|
|
|
go func() {
|
|
a := NewFrame(1, 1, 1)
|
|
if err := a.SetData([]byte("first")); err != nil {
|
|
t.Errorf("SetData: %v", err)
|
|
}
|
|
b := NewFrame(1, 2, 2)
|
|
if err := b.SetData([]byte("second")); err != nil {
|
|
t.Errorf("SetData: %v", err)
|
|
}
|
|
if err := WriteFrame(c1, a); err != nil {
|
|
t.Errorf("WriteFrame: %v", err)
|
|
}
|
|
if err := WriteFrame(c1, b); err != nil {
|
|
t.Errorf("WriteFrame: %v", err)
|
|
}
|
|
}()
|
|
|
|
got1, err := ReadFrame(c2)
|
|
if err != nil || string(got1.Data()) != "first" {
|
|
t.Fatalf("第一帧 = %q, %v", got1.Data(), err)
|
|
}
|
|
got2, err := ReadFrame(c2)
|
|
if err != nil || string(got2.Data()) != "second" {
|
|
t.Fatalf("第二帧 = %q, %v", got2.Data(), err)
|
|
}
|
|
}
|
|
|
|
func TestSetDataOverflow(t *testing.T) {
|
|
f := NewFrame(1, 0, 0)
|
|
if err := f.SetData(make([]byte, 65536)); err == nil {
|
|
t.Error("超过 65535 字节应返回错误")
|
|
}
|
|
if err := f.SetData(make([]byte, 65535)); err != nil {
|
|
t.Errorf("65535 字节应成功: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMarshalUnmarshal(t *testing.T) {
|
|
f := NewFrame(1, 3, 9)
|
|
type payload struct {
|
|
Name string
|
|
N int
|
|
}
|
|
if err := f.Marshal(payload{Name: "a", N: 1}); err != nil {
|
|
t.Fatalf("Marshal: %v", err)
|
|
}
|
|
var got payload
|
|
if err := f.Unmarshal(&got); err != nil {
|
|
t.Fatalf("Unmarshal: %v", err)
|
|
}
|
|
if got.Name != "a" || got.N != 1 {
|
|
t.Errorf("Unmarshal 结果 = %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestRawHeader(t *testing.T) {
|
|
h := RawHeader{}
|
|
h[0] = 2
|
|
h[1] = 7
|
|
binary.LittleEndian.PutUint16(h[2:], 300)
|
|
binary.LittleEndian.PutUint32(h[4:], 100000)
|
|
if h.Version() != 2 || h.Cmd() != 7 || h.Length() != 300 || h.StreamID() != 100000 {
|
|
t.Errorf("RawHeader 解析不符: %v %v %v %v", h.Version(), h.Cmd(), h.Length(), h.StreamID())
|
|
}
|
|
if len(h.Bytes()) != 8 {
|
|
t.Errorf("Bytes 长度 = %d, want 8", len(h.Bytes()))
|
|
}
|
|
}
|