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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
package statsengine
import "testing"
func TestNewSnapshotDefensivelyCopiesSlices(t *testing.T) {
latency := []float64{1, 2, 3}
gap := []float64{4, 5, 6}
throughput := []float64{7, 8, 9}
syscalls := []SyscallSnapshot{{Name: "read", Count: 1}}
files := []FileSnapshot{{Path: "/tmp/a", Accesses: 2}}
processes := []ProcessSnapshot{{PID: 10, Comm: "cmd"}}
latencyBuckets := []HistogramBucketSnapshot{{Label: "[0,1)", Count: 3}}
gapBuckets := []HistogramBucketSnapshot{{Label: "[1,10)", Count: 4}}
s := NewSnapshot(
latency,
gap,
throughput,
syscalls,
files,
processes,
NewHistogramSnapshot(3, latencyBuckets),
NewHistogramSnapshot(4, gapBuckets),
)
latency[0] = 99
gap[0] = 99
throughput[0] = 99
syscalls[0].Name = "write"
files[0].Path = "/tmp/b"
processes[0].Comm = "mutated"
latencyBuckets[0].Count = 99
gapBuckets[0].Count = 99
if got := s.LatencySeriesNs()[0]; got != 1 {
t.Fatalf("latency mutated through input slice: got %v", got)
}
if got := s.GapSeriesNs()[0]; got != 4 {
t.Fatalf("gap mutated through input slice: got %v", got)
}
if got := s.ThroughputSeriesB()[0]; got != 7 {
t.Fatalf("throughput mutated through input slice: got %v", got)
}
if got := s.Syscalls()[0].Name; got != "read" {
t.Fatalf("syscalls mutated through input slice: got %q", got)
}
if got := s.Files()[0].Path; got != "/tmp/a" {
t.Fatalf("files mutated through input slice: got %q", got)
}
if got := s.Processes()[0].Comm; got != "cmd" {
t.Fatalf("processes mutated through input slice: got %q", got)
}
if got := s.LatencyHistogram.Buckets()[0].Count; got != 3 {
t.Fatalf("latency histogram mutated through input slice: got %d", got)
}
if got := s.GapHistogram.Buckets()[0].Count; got != 4 {
t.Fatalf("gap histogram mutated through input slice: got %d", got)
}
}
func TestSnapshotAccessorsReturnReadOnlyViews(t *testing.T) {
s := NewSnapshot(
[]float64{1},
[]float64{2},
[]float64{3},
[]SyscallSnapshot{{Name: "read"}},
[]FileSnapshot{{Path: "/tmp/a"}},
[]ProcessSnapshot{{Comm: "cmd"}},
NewHistogramSnapshot(1, []HistogramBucketSnapshot{{Label: "a", Count: 1}}),
NewHistogramSnapshot(1, []HistogramBucketSnapshot{{Label: "b", Count: 1}}),
)
lat := s.LatencySeriesNs()
lat[0] = 100
if got := s.LatencySeriesNs()[0]; got != 100 {
t.Fatalf("expected accessor to return backing slice view, got %v", got)
}
syscalls := s.Syscalls()
syscalls[0].Name = "write"
if got := s.Syscalls()[0].Name; got != "write" {
t.Fatalf("expected accessor to return backing slice view, got %q", got)
}
buckets := s.LatencyHistogram.Buckets()
buckets[0].Count = 99
if got := s.LatencyHistogram.Buckets()[0].Count; got != 99 {
t.Fatalf("expected accessor to return backing slice view, got %d", got)
}
}
func TestNilAccessorsRemainNil(t *testing.T) {
s := Snapshot{}
if got := s.LatencySeriesNs(); got != nil {
t.Fatalf("expected nil latency series, got %#v", got)
}
if got := s.Syscalls(); got != nil {
t.Fatalf("expected nil syscalls, got %#v", got)
}
h := HistogramSnapshot{}
if got := h.Buckets(); got != nil {
t.Fatalf("expected nil buckets, got %#v", got)
}
}
func TestTopNAccessors(t *testing.T) {
s := NewSnapshot(
nil,
nil,
nil,
[]SyscallSnapshot{{Name: "a"}, {Name: "b"}, {Name: "c"}},
[]FileSnapshot{{Path: "/a"}, {Path: "/b"}},
[]ProcessSnapshot{{PID: 1}, {PID: 2}, {PID: 3}},
HistogramSnapshot{},
HistogramSnapshot{},
)
if got := s.TopNSyscalls(2); len(got) != 2 {
t.Fatalf("expected 2 top syscalls, got %d", len(got))
}
if got := s.TopNFiles(10); len(got) != 2 {
t.Fatalf("expected all files when n exceeds len, got %d", len(got))
}
if got := s.TopNProcesses(0); got != nil {
t.Fatalf("expected nil when n<=0, got %#v", got)
}
}
|