1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
package dashboard
import (
"strings"
"testing"
"time"
"ior/internal/statsengine"
)
func TestRenderOverviewIncludesCoreMetrics(t *testing.T) {
snap := &statsengine.Snapshot{
Elapsed: 95 * time.Second,
TotalSyscalls: 1200,
SyscallRatePerSec: 12.5,
TotalBytes: 10 * 1024 * 1024,
ReadBytesPerSec: 4096,
WriteBytesPerSec: 8192,
TotalErrors: 12,
LatencyMeanNs: 5000,
LatencyTrend: statsengine.Trend{Direction: statsengine.TrendRising, DeltaPercent: 12.5},
GapTrend: statsengine.Trend{Direction: statsengine.TrendFalling, DeltaPercent: -7.4},
ThroughputTrend: statsengine.Trend{Direction: statsengine.TrendStable, DeltaPercent: 0},
}
out := renderOverview(snap, 120, 40)
for _, token := range []string{
"Elapsed:",
"Syscalls:",
"Read/s:",
"Errors:",
"Trends:",
"Latency:",
"Gap:",
"Throughput:",
"Top syscalls:",
"Top files:",
"Top processes:",
"Latency buckets:",
"Gap buckets:",
} {
if !strings.Contains(out, token) {
t.Fatalf("expected token %q in overview output", token)
}
}
}
func TestSummarizeTopSyscalls(t *testing.T) {
snap := statsengine.NewSnapshot(
nil, nil, nil,
[]statsengine.SyscallSnapshot{
{Name: "read", Count: 50},
{Name: "write", Count: 20},
{Name: "openat", Count: 10},
{Name: "close", Count: 5},
},
nil, nil,
statsengine.HistogramSnapshot{},
statsengine.HistogramSnapshot{},
)
got := summarizeTopSyscalls(&snap)
if got != "read(50), write(20), openat(10)" {
t.Fatalf("unexpected top syscall summary: %q", got)
}
}
func TestRenderOverviewWithoutSnapshot(t *testing.T) {
out := renderOverview(nil, 80, 24)
if !strings.Contains(out, "waiting for stats") {
t.Fatalf("expected waiting placeholder, got %q", out)
}
}
func TestOverviewSummariesIncludeFilesProcessesAndHistograms(t *testing.T) {
snap := statsengine.NewSnapshot(
nil, nil, nil,
[]statsengine.SyscallSnapshot{{Name: "read", Count: 2}},
[]statsengine.FileSnapshot{{Path: "/tmp/very/long/path/file.log", Accesses: 4}},
[]statsengine.ProcessSnapshot{{PID: 12, Comm: "proc", Syscalls: 7}},
statsengine.NewHistogramSnapshot(3, []statsengine.HistogramBucketSnapshot{
{Label: "[0,1us)", Count: 2},
{Label: "[1us,10us)", Count: 1},
}),
statsengine.NewHistogramSnapshot(1, []statsengine.HistogramBucketSnapshot{
{Label: "[10us,100us)", Count: 1},
}),
)
out := renderOverview(&snap, 120, 40)
for _, token := range []string{"Top files:", "Top processes:", "Latency buckets:", "Gap buckets:"} {
if !strings.Contains(out, token) {
t.Fatalf("expected %q in overview output", token)
}
}
}
|