summaryrefslogtreecommitdiff
path: root/internal/statsengine/snapshot_test.go
blob: 065edede8ed276177d8c9ee308fecd56e90778d6 (plain)
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
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 TestSnapshotAccessorsReturnCopies(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 != 1 {
		t.Fatalf("latency accessor leaked mutability: got %v", got)
	}

	syscalls := s.Syscalls()
	syscalls[0].Name = "write"
	if got := s.Syscalls()[0].Name; got != "read" {
		t.Fatalf("syscalls accessor leaked mutability: got %q", got)
	}

	buckets := s.LatencyHistogram.Buckets()
	buckets[0].Count = 99
	if got := s.LatencyHistogram.Buckets()[0].Count; got != 1 {
		t.Fatalf("bucket accessor leaked mutability: 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)
	}
}