notify/bulk_dedicated_record_test.go
starainrt 4f760f2807
fix: 修复 dedicated bulk attach 竞态并优化 short write 补写路径
- 客户端 dedicated attach 回复改为精确读取单帧,避免 attach reply 与后续 NBR1 数据粘连后被误解析
  - 服务端 accepted attach 改为先 detach transport,再直接回 attach reply,随后立即切入 dedicated bulk read loop
  - transport 读循环在 stop 或 transport ownership 失效后不再继续上推已读数据,避免 handoff 后首包被旧 reader 吃掉
  - dedicated bulk record 写路径改为 full-write,消除 short write 导致的 invalid bulk fast payload
  - 优化 vectored write 补写策略:先尝试一次 writev,未写完时直接顺序补完剩余 buffers,减少重复 WriteTo 开销
  - 放宽 vectored write 能力识别,支持通过 UnwrapConn/WriteBuffers 命中 fast path
  - 修复 dedicated batch 排队路径 payload 复用问题,改为深拷贝 queued items
  - 补齐 dedicated attach、short write、payload clone、transport stop/handoff 等回归测试
2026-04-16 17:27:48 +08:00

67 lines
2.1 KiB
Go

package notify
import (
"bytes"
"encoding/binary"
"io"
"net"
"testing"
"time"
)
type shortWriteBulkRecordConn struct {
maxPerWrite int
buf bytes.Buffer
}
func (c *shortWriteBulkRecordConn) Read([]byte) (int, error) { return 0, io.EOF }
func (c *shortWriteBulkRecordConn) Write(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
n := c.maxPerWrite
if n <= 0 || n > len(p) {
n = len(p)
}
_, _ = c.buf.Write(p[:n])
return n, nil
}
func (c *shortWriteBulkRecordConn) Close() error { return nil }
func (c *shortWriteBulkRecordConn) LocalAddr() net.Addr { return shortWriteBulkRecordAddr("local") }
func (c *shortWriteBulkRecordConn) RemoteAddr() net.Addr { return shortWriteBulkRecordAddr("remote") }
func (c *shortWriteBulkRecordConn) SetDeadline(time.Time) error { return nil }
func (c *shortWriteBulkRecordConn) SetReadDeadline(time.Time) error {
return nil
}
func (c *shortWriteBulkRecordConn) SetWriteDeadline(time.Time) error {
return nil
}
type shortWriteBulkRecordAddr string
func (a shortWriteBulkRecordAddr) Network() string { return "tcp" }
func (a shortWriteBulkRecordAddr) String() string { return string(a) }
func TestWriteBulkDedicatedRecordWithDeadlineHandlesShortWrite(t *testing.T) {
conn := &shortWriteBulkRecordConn{maxPerWrite: 3}
payload := []byte("abcdefghijklmnopqrstuvwxyz")
if err := writeBulkDedicatedRecordWithDeadline(conn, payload, time.Time{}); err != nil {
t.Fatalf("writeBulkDedicatedRecordWithDeadline failed: %v", err)
}
raw := conn.buf.Bytes()
if got, want := len(raw), bulkDedicatedRecordHeaderLen+len(payload); got != want {
t.Fatalf("record length = %d, want %d", got, want)
}
if got := string(raw[:4]); got != bulkDedicatedRecordMagic {
t.Fatalf("record magic = %q, want %q", got, bulkDedicatedRecordMagic)
}
if got, want := int(binary.BigEndian.Uint32(raw[4:8])), len(payload); got != want {
t.Fatalf("record payload length = %d, want %d", got, want)
}
if got := raw[bulkDedicatedRecordHeaderLen:]; !bytes.Equal(got, payload) {
t.Fatalf("record payload mismatch")
}
}