feat(notify): 重构通信内核并补齐 stream/bulk/record/transfer 能力
- 引入 LogicalConn/TransportConn 分层,ClientConn 保留兼容适配层 - 新增 Stream、Bulk、RecordStream 三条数据面能力及对应控制路径 - 完成 transfer/file 传输内核与状态快照、诊断能力 - 补齐 reconnect、inbound dispatcher、modern psk 等基础模块 - 增加大规模回归、并发与基准测试覆盖 - 更新依赖库
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTransferMonitorLatestSummaryPrefersActive(t *testing.T) {
|
||||
monitor := newFileTransferMonitor()
|
||||
now := time.Unix(500, 0)
|
||||
|
||||
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||||
Kind: EnvelopeFileChunk,
|
||||
Packet: FilePacket{FileID: "summary-1", Size: 30},
|
||||
Received: 12,
|
||||
Total: 30,
|
||||
Percent: 40,
|
||||
StartedAt: now,
|
||||
UpdatedAt: now.Add(time.Second),
|
||||
Time: now.Add(time.Second),
|
||||
})
|
||||
|
||||
summary, ok := monitor.latestSummary(fileTransferDirectionSend, clientFileScope(), "summary-1")
|
||||
if !ok {
|
||||
t.Fatal("latest summary should exist while active")
|
||||
}
|
||||
if got, want := summary.Active, true; got != want {
|
||||
t.Fatalf("active summary mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summary.Terminal, false; got != want {
|
||||
t.Fatalf("terminal summary mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summary.Received, int64(12); got != want {
|
||||
t.Fatalf("active summary received mismatch: got %d want %d", got, want)
|
||||
}
|
||||
|
||||
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||||
Kind: EnvelopeFileEnd,
|
||||
Packet: FilePacket{FileID: "summary-1", Size: 30},
|
||||
Received: 30,
|
||||
Total: 30,
|
||||
Percent: 100,
|
||||
Done: true,
|
||||
StartedAt: now,
|
||||
UpdatedAt: now.Add(2 * time.Second),
|
||||
Time: now.Add(2 * time.Second),
|
||||
})
|
||||
|
||||
summary, ok = monitor.latestSummary(fileTransferDirectionSend, clientFileScope(), "summary-1")
|
||||
if !ok {
|
||||
t.Fatal("latest summary should exist after completion")
|
||||
}
|
||||
if got, want := summary.Active, false; got != want {
|
||||
t.Fatalf("completed summary active mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summary.Terminal, true; got != want {
|
||||
t.Fatalf("completed summary terminal mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summary.Done, true; got != want {
|
||||
t.Fatalf("completed summary done mismatch: got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferMonitorSummariesByFileID(t *testing.T) {
|
||||
monitor := newFileTransferMonitor()
|
||||
now := time.Unix(600, 0)
|
||||
serverClientA := &ClientConn{ClientID: "client-a"}
|
||||
serverClientB := &ClientConn{ClientID: "client-b"}
|
||||
|
||||
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||||
Kind: EnvelopeFileChunk,
|
||||
Packet: FilePacket{FileID: "summary-shared", Size: 20},
|
||||
Received: 8,
|
||||
Total: 20,
|
||||
Time: now,
|
||||
})
|
||||
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||||
ClientConn: serverClientA,
|
||||
Kind: EnvelopeFileChunk,
|
||||
Packet: FilePacket{FileID: "summary-shared", Size: 20},
|
||||
Received: 12,
|
||||
Total: 20,
|
||||
Time: now.Add(time.Second),
|
||||
})
|
||||
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||||
ClientConn: serverClientB,
|
||||
Kind: EnvelopeFileAbort,
|
||||
Packet: FilePacket{FileID: "summary-shared", Size: 20, Stage: "chunk"},
|
||||
Received: 14,
|
||||
Total: 20,
|
||||
Time: now.Add(2 * time.Second),
|
||||
Err: errString("recv failed"),
|
||||
})
|
||||
|
||||
summaries := monitor.summariesByFileID("summary-shared")
|
||||
if got, want := len(summaries), 3; got != want {
|
||||
t.Fatalf("summaries count mismatch: got %d want %d", got, want)
|
||||
}
|
||||
if got, want := summaries[0].Scope, serverFileScope(serverClientA); got != want {
|
||||
t.Fatalf("first summary scope mismatch: got %q want %q", got, want)
|
||||
}
|
||||
if got, want := summaries[0].Active, true; got != want {
|
||||
t.Fatalf("first summary active mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summaries[1].Scope, serverFileScope(serverClientB); got != want {
|
||||
t.Fatalf("second summary scope mismatch: got %q want %q", got, want)
|
||||
}
|
||||
if got, want := summaries[1].Failed, true; got != want {
|
||||
t.Fatalf("second summary failed mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summaries[1].Terminal, true; got != want {
|
||||
t.Fatalf("second summary terminal mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := summaries[2].Direction, fileTransferDirectionSend; got != want {
|
||||
t.Fatalf("third summary direction mismatch: got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferMonitorActiveAndCompletedSummaries(t *testing.T) {
|
||||
monitor := newFileTransferMonitor()
|
||||
now := time.Unix(700, 0)
|
||||
|
||||
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||||
Kind: EnvelopeFileChunk,
|
||||
Packet: FilePacket{FileID: "active-1", Size: 10},
|
||||
Received: 3,
|
||||
Total: 10,
|
||||
Time: now,
|
||||
})
|
||||
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||||
Kind: EnvelopeFileEnd,
|
||||
Packet: FilePacket{FileID: "done-1", Size: 10},
|
||||
Received: 10,
|
||||
Total: 10,
|
||||
Done: true,
|
||||
Time: now.Add(time.Second),
|
||||
})
|
||||
|
||||
active := monitor.activeSummaries()
|
||||
if got, want := len(active), 1; got != want {
|
||||
t.Fatalf("active summaries count mismatch: got %d want %d", got, want)
|
||||
}
|
||||
if got, want := active[0].Active, true; got != want {
|
||||
t.Fatalf("active summary state mismatch: got %v want %v", got, want)
|
||||
}
|
||||
|
||||
completed := monitor.completedSummaries()
|
||||
if got, want := len(completed), 1; got != want {
|
||||
t.Fatalf("completed summaries count mismatch: got %d want %d", got, want)
|
||||
}
|
||||
if got, want := completed[0].Active, false; got != want {
|
||||
t.Fatalf("completed summary state mismatch: got %v want %v", got, want)
|
||||
}
|
||||
if got, want := completed[0].Done, true; got != want {
|
||||
t.Fatalf("completed summary done mismatch: got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type errString string
|
||||
|
||||
func (e errString) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
Reference in New Issue
Block a user