330 lines
11 KiB
Go
330 lines
11 KiB
Go
|
|
package notify
|
||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestClientTransferMonitorTracksSendLifecycle(t *testing.T) {
|
||
|
|
client := NewClient().(*ClientCommon)
|
||
|
|
monitor := client.getFileTransferState().monitorView()
|
||
|
|
now := time.Unix(100, 0)
|
||
|
|
|
||
|
|
client.publishSendFileEvent(FileEvent{
|
||
|
|
NetType: NET_CLIENT,
|
||
|
|
Kind: EnvelopeFileMeta,
|
||
|
|
Packet: FilePacket{FileID: "send-1", Size: 100},
|
||
|
|
Path: "/tmp/send-1.bin",
|
||
|
|
Total: 100,
|
||
|
|
Time: now,
|
||
|
|
})
|
||
|
|
client.publishSendFileEvent(FileEvent{
|
||
|
|
NetType: NET_CLIENT,
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "send-1", Size: 100},
|
||
|
|
Path: "/tmp/send-1.bin",
|
||
|
|
Received: 40,
|
||
|
|
Total: 100,
|
||
|
|
Percent: 40,
|
||
|
|
StartedAt: now,
|
||
|
|
UpdatedAt: now.Add(2 * time.Second),
|
||
|
|
Duration: 2 * time.Second,
|
||
|
|
RateBPS: 20,
|
||
|
|
Time: now.Add(2 * time.Second),
|
||
|
|
StepDuration: 2 * time.Second,
|
||
|
|
})
|
||
|
|
|
||
|
|
active := monitor.activeSnapshots()
|
||
|
|
if got, want := len(active), 1; got != want {
|
||
|
|
t.Fatalf("active count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].Direction, fileTransferDirectionSend; got != want {
|
||
|
|
t.Fatalf("direction mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].Scope, clientFileScope(); got != want {
|
||
|
|
t.Fatalf("scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].Received, int64(40); got != want {
|
||
|
|
t.Fatalf("received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
snapshot, ok := monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "send-1")
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("latest snapshot should exist while active")
|
||
|
|
}
|
||
|
|
if got, want := snapshot.Kind, EnvelopeFileChunk; got != want {
|
||
|
|
t.Fatalf("latest active kind mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := snapshot.Received, int64(40); got != want {
|
||
|
|
t.Fatalf("latest active received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
client.publishSendFileEvent(FileEvent{
|
||
|
|
NetType: NET_CLIENT,
|
||
|
|
Kind: EnvelopeFileEnd,
|
||
|
|
Packet: FilePacket{FileID: "send-1", Size: 100},
|
||
|
|
Path: "/tmp/send-1.bin",
|
||
|
|
Received: 100,
|
||
|
|
Total: 100,
|
||
|
|
Percent: 100,
|
||
|
|
Done: true,
|
||
|
|
StartedAt: now,
|
||
|
|
UpdatedAt: now.Add(4 * time.Second),
|
||
|
|
Duration: 4 * time.Second,
|
||
|
|
RateBPS: 25,
|
||
|
|
Time: now.Add(4 * time.Second),
|
||
|
|
})
|
||
|
|
|
||
|
|
active = monitor.activeSnapshots()
|
||
|
|
if got, want := len(active), 0; got != want {
|
||
|
|
t.Fatalf("active count after end mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
completed := monitor.completedSnapshots()
|
||
|
|
if got, want := len(completed), 1; got != want {
|
||
|
|
t.Fatalf("completed count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := completed[0].Done, true; got != want {
|
||
|
|
t.Fatalf("done mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := completed[0].Received, int64(100); got != want {
|
||
|
|
t.Fatalf("completed received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
snapshot, ok = monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "send-1")
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("latest snapshot should exist after completion")
|
||
|
|
}
|
||
|
|
if got, want := snapshot.Kind, EnvelopeFileEnd; got != want {
|
||
|
|
t.Fatalf("latest completed kind mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := snapshot.Done, true; got != want {
|
||
|
|
t.Fatalf("latest completed done mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestServerTransferMonitorUsesClientScope(t *testing.T) {
|
||
|
|
server := NewServer().(*ServerCommon)
|
||
|
|
monitor := server.getFileTransferState().monitorView()
|
||
|
|
client := &ClientConn{ClientID: "client-1"}
|
||
|
|
now := time.Unix(200, 0)
|
||
|
|
|
||
|
|
server.publishReceivedFileEvent(FileEvent{
|
||
|
|
NetType: NET_SERVER,
|
||
|
|
ClientConn: client,
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "recv-1", Size: 50},
|
||
|
|
Path: "/tmp/recv-1.part",
|
||
|
|
Received: 20,
|
||
|
|
Total: 50,
|
||
|
|
Percent: 40,
|
||
|
|
StartedAt: now,
|
||
|
|
UpdatedAt: now.Add(time.Second),
|
||
|
|
Duration: time.Second,
|
||
|
|
RateBPS: 20,
|
||
|
|
Time: now.Add(time.Second),
|
||
|
|
})
|
||
|
|
|
||
|
|
active := monitor.activeSnapshots()
|
||
|
|
if got, want := len(active), 1; got != want {
|
||
|
|
t.Fatalf("active count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].Direction, fileTransferDirectionReceive; got != want {
|
||
|
|
t.Fatalf("direction mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].Scope, serverFileScope(client); got != want {
|
||
|
|
t.Fatalf("scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].FileID, "recv-1"; got != want {
|
||
|
|
t.Fatalf("fileID mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTransferMonitorDirectionQueries(t *testing.T) {
|
||
|
|
monitor := newFileTransferMonitor()
|
||
|
|
now := time.Unix(300, 0)
|
||
|
|
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "shared", Size: 10},
|
||
|
|
Received: 4,
|
||
|
|
Total: 10,
|
||
|
|
Time: now,
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "shared", Size: 10},
|
||
|
|
Received: 7,
|
||
|
|
Total: 10,
|
||
|
|
Time: now.Add(time.Second),
|
||
|
|
})
|
||
|
|
|
||
|
|
sendSnapshots := monitor.activeSnapshotsByDirection(fileTransferDirectionSend)
|
||
|
|
if got, want := len(sendSnapshots), 1; got != want {
|
||
|
|
t.Fatalf("send snapshots count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := sendSnapshots[0].Received, int64(4); got != want {
|
||
|
|
t.Fatalf("send snapshot received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
recvSnapshots := monitor.activeSnapshotsByDirection(fileTransferDirectionReceive)
|
||
|
|
if got, want := len(recvSnapshots), 1; got != want {
|
||
|
|
t.Fatalf("recv snapshots count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := recvSnapshots[0].Received, int64(7); got != want {
|
||
|
|
t.Fatalf("recv snapshot received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
sendSnapshot, ok := monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "shared")
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("send latest snapshot should exist")
|
||
|
|
}
|
||
|
|
if got, want := sendSnapshot.Received, int64(4); got != want {
|
||
|
|
t.Fatalf("send latest received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
recvSnapshot, ok := monitor.latestSnapshot(fileTransferDirectionReceive, clientFileScope(), "shared")
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("recv latest snapshot should exist")
|
||
|
|
}
|
||
|
|
if got, want := recvSnapshot.Received, int64(7); got != want {
|
||
|
|
t.Fatalf("recv latest received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTransferMonitorSnapshotsByFileID(t *testing.T) {
|
||
|
|
monitor := newFileTransferMonitor()
|
||
|
|
now := time.Unix(400, 0)
|
||
|
|
serverClientA := &ClientConn{ClientID: "client-a"}
|
||
|
|
serverClientB := &ClientConn{ClientID: "client-b"}
|
||
|
|
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "shared", Size: 20},
|
||
|
|
Received: 8,
|
||
|
|
Total: 20,
|
||
|
|
Time: now,
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||
|
|
ClientConn: serverClientA,
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "shared", Size: 20},
|
||
|
|
Received: 12,
|
||
|
|
Total: 20,
|
||
|
|
Time: now.Add(time.Second),
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionReceive, FileEvent{
|
||
|
|
ClientConn: serverClientB,
|
||
|
|
Kind: EnvelopeFileEnd,
|
||
|
|
Packet: FilePacket{FileID: "shared", Size: 20},
|
||
|
|
Received: 20,
|
||
|
|
Total: 20,
|
||
|
|
Done: true,
|
||
|
|
Time: now.Add(2 * time.Second),
|
||
|
|
})
|
||
|
|
|
||
|
|
allSnapshots := monitor.snapshotsByFileID("shared")
|
||
|
|
if got, want := len(allSnapshots), 3; got != want {
|
||
|
|
t.Fatalf("all snapshots count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := allSnapshots[0].Direction, fileTransferDirectionReceive; got != want {
|
||
|
|
t.Fatalf("first snapshot direction mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
if got, want := allSnapshots[0].Scope, serverFileScope(serverClientA); got != want {
|
||
|
|
t.Fatalf("first snapshot scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := allSnapshots[1].Scope, serverFileScope(serverClientB); got != want {
|
||
|
|
t.Fatalf("second snapshot scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := allSnapshots[2].Direction, fileTransferDirectionSend; got != want {
|
||
|
|
t.Fatalf("third snapshot direction mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
recvSnapshots := monitor.snapshotsByDirectionAndFileID(fileTransferDirectionReceive, "shared")
|
||
|
|
if got, want := len(recvSnapshots), 2; got != want {
|
||
|
|
t.Fatalf("recv snapshots count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := recvSnapshots[0].Scope, serverFileScope(serverClientA); got != want {
|
||
|
|
t.Fatalf("recv first scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := recvSnapshots[1].Scope, serverFileScope(serverClientB); got != want {
|
||
|
|
t.Fatalf("recv second scope mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := recvSnapshots[1].Done, true; got != want {
|
||
|
|
t.Fatalf("recv completed snapshot mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
sendSnapshots := monitor.snapshotsByDirectionAndFileID(fileTransferDirectionSend, "shared")
|
||
|
|
if got, want := len(sendSnapshots), 1; got != want {
|
||
|
|
t.Fatalf("send snapshots count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := sendSnapshots[0].Received, int64(8); got != want {
|
||
|
|
t.Fatalf("send snapshot received mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestTransferMonitorCompletedRetentionEvictsOldest(t *testing.T) {
|
||
|
|
monitor := newFileTransferMonitorWithCompletedLimit(2)
|
||
|
|
now := time.Unix(500, 0)
|
||
|
|
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileChunk,
|
||
|
|
Packet: FilePacket{FileID: "active-1", Size: 10},
|
||
|
|
Received: 3,
|
||
|
|
Total: 10,
|
||
|
|
Time: now,
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileEnd,
|
||
|
|
Packet: FilePacket{FileID: "done-1", Size: 10},
|
||
|
|
Received: 10,
|
||
|
|
Total: 10,
|
||
|
|
Done: true,
|
||
|
|
Time: now.Add(time.Second),
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileEnd,
|
||
|
|
Packet: FilePacket{FileID: "done-2", Size: 10},
|
||
|
|
Received: 10,
|
||
|
|
Total: 10,
|
||
|
|
Done: true,
|
||
|
|
Time: now.Add(2 * time.Second),
|
||
|
|
})
|
||
|
|
monitor.observe(fileTransferDirectionSend, FileEvent{
|
||
|
|
Kind: EnvelopeFileEnd,
|
||
|
|
Packet: FilePacket{FileID: "done-3", Size: 10},
|
||
|
|
Received: 10,
|
||
|
|
Total: 10,
|
||
|
|
Done: true,
|
||
|
|
Time: now.Add(3 * time.Second),
|
||
|
|
})
|
||
|
|
|
||
|
|
active := monitor.activeSnapshots()
|
||
|
|
if got, want := len(active), 1; got != want {
|
||
|
|
t.Fatalf("active count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := active[0].FileID, "active-1"; got != want {
|
||
|
|
t.Fatalf("active fileID mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
completed := monitor.completedSnapshots()
|
||
|
|
if got, want := len(completed), 2; got != want {
|
||
|
|
t.Fatalf("completed count mismatch: got %d want %d", got, want)
|
||
|
|
}
|
||
|
|
if got, want := completed[0].FileID, "done-2"; got != want {
|
||
|
|
t.Fatalf("first completed fileID mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
if got, want := completed[1].FileID, "done-3"; got != want {
|
||
|
|
t.Fatalf("second completed fileID mismatch: got %q want %q", got, want)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, ok := monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "done-1"); ok {
|
||
|
|
t.Fatal("oldest completed snapshot should be evicted")
|
||
|
|
}
|
||
|
|
if _, ok := monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "done-3"); !ok {
|
||
|
|
t.Fatal("latest completed snapshot should be retained")
|
||
|
|
}
|
||
|
|
if snapshot, ok := monitor.latestSnapshot(fileTransferDirectionSend, clientFileScope(), "active-1"); !ok {
|
||
|
|
t.Fatal("active snapshot should remain available")
|
||
|
|
} else if got, want := snapshot.Kind, EnvelopeFileChunk; got != want {
|
||
|
|
t.Fatalf("active latest kind mismatch: got %v want %v", got, want)
|
||
|
|
}
|
||
|
|
}
|