1
2
3
4
5 package pprof
6
7 import (
8 "context"
9 "fmt"
10 "internal/runtime/pprof/label"
11 "reflect"
12 "slices"
13 "strings"
14 "testing"
15 )
16
17 func labelsSorted(ctx context.Context) []label.Label {
18 ls := []label.Label{}
19 ForLabels(ctx, func(key, value string) bool {
20 ls = append(ls, label.Label{Key: key, Value: value})
21 return true
22 })
23 slices.SortFunc(ls, func(a, b label.Label) int { return strings.Compare(a.Key, b.Key) })
24 return ls
25 }
26
27 func TestContextLabels(t *testing.T) {
28
29 ctx := context.Background()
30 labels := labelsSorted(ctx)
31 if len(labels) != 0 {
32 t.Errorf("labels on background context: want [], got %v ", labels)
33 }
34
35
36 ctx = WithLabels(ctx, Labels("key", "value"))
37
38 v, ok := Label(ctx, "key")
39 if !ok || v != "value" {
40 t.Errorf(`Label(ctx, "key"): got %v, %v; want "value", ok`, v, ok)
41 }
42 gotLabels := labelsSorted(ctx)
43 wantLabels := []label.Label{{Key: "key", Value: "value"}}
44 if !reflect.DeepEqual(gotLabels, wantLabels) {
45 t.Errorf("(sorted) labels on context: got %v, want %v", gotLabels, wantLabels)
46 }
47
48
49 ctx = WithLabels(ctx, Labels("key2", "value2"))
50 v, ok = Label(ctx, "key2")
51 if !ok || v != "value2" {
52 t.Errorf(`Label(ctx, "key2"): got %v, %v; want "value2", ok`, v, ok)
53 }
54 gotLabels = labelsSorted(ctx)
55 wantLabels = []label.Label{{Key: "key", Value: "value"}, {Key: "key2", Value: "value2"}}
56 if !reflect.DeepEqual(gotLabels, wantLabels) {
57 t.Errorf("(sorted) labels on context: got %v, want %v", gotLabels, wantLabels)
58 }
59
60
61 ctx = WithLabels(ctx, Labels("key", "value3"))
62 v, ok = Label(ctx, "key")
63 if !ok || v != "value3" {
64 t.Errorf(`Label(ctx, "key3"): got %v, %v; want "value3", ok`, v, ok)
65 }
66 gotLabels = labelsSorted(ctx)
67 wantLabels = []label.Label{{Key: "key", Value: "value3"}, {Key: "key2", Value: "value2"}}
68 if !reflect.DeepEqual(gotLabels, wantLabels) {
69 t.Errorf("(sorted) labels on context: got %v, want %v", gotLabels, wantLabels)
70 }
71
72
73 ctx = WithLabels(ctx, Labels("key4", "value4a", "key4", "value4b"))
74 v, ok = Label(ctx, "key4")
75 if !ok || v != "value4b" {
76 t.Errorf(`Label(ctx, "key4"): got %v, %v; want "value4b", ok`, v, ok)
77 }
78 gotLabels = labelsSorted(ctx)
79 wantLabels = []label.Label{{Key: "key", Value: "value3"}, {Key: "key2", Value: "value2"}, {Key: "key4", Value: "value4b"}}
80 if !reflect.DeepEqual(gotLabels, wantLabels) {
81 t.Errorf("(sorted) labels on context: got %v, want %v", gotLabels, wantLabels)
82 }
83 }
84
85 func TestLabelMapStringer(t *testing.T) {
86 for _, tbl := range []struct {
87 m labelMap
88 expected string
89 }{
90 {
91 m: labelMap{
92
93 },
94 expected: "{}",
95 }, {
96 m: labelMap{
97 label.NewSet(Labels("foo", "bar").list),
98 },
99 expected: `{"foo":"bar"}`,
100 }, {
101 m: labelMap{
102 label.NewSet(Labels(
103 "foo", "bar",
104 "key1", "value1",
105 "key2", "value2",
106 "key3", "value3",
107 "key4WithNewline", "\nvalue4",
108 ).list),
109 },
110 expected: `{"foo":"bar", "key1":"value1", "key2":"value2", "key3":"value3", "key4WithNewline":"\nvalue4"}`,
111 },
112 } {
113 if got := tbl.m.String(); tbl.expected != got {
114 t.Errorf("%#v.String() = %q; want %q", tbl.m, got, tbl.expected)
115 }
116 }
117 }
118
119 func BenchmarkLabels(b *testing.B) {
120 b.Run("set-one", func(b *testing.B) {
121 b.ReportAllocs()
122 b.ResetTimer()
123 for i := 0; i < b.N; i++ {
124 Do(context.Background(), Labels("key", "value"), func(context.Context) {})
125 }
126 })
127
128 b.Run("merge-one", func(b *testing.B) {
129 ctx := WithLabels(context.Background(), Labels("key1", "val1"))
130
131 b.ReportAllocs()
132 b.ResetTimer()
133 for i := 0; i < b.N; i++ {
134 Do(ctx, Labels("key2", "value2"), func(context.Context) {})
135 }
136 })
137
138 b.Run("overwrite-one", func(b *testing.B) {
139 ctx := WithLabels(context.Background(), Labels("key", "val"))
140
141 b.ReportAllocs()
142 b.ResetTimer()
143 for i := 0; i < b.N; i++ {
144 Do(ctx, Labels("key", "value"), func(context.Context) {})
145 }
146 })
147
148 for _, scenario := range []string{"ordered", "unordered"} {
149 var labels []string
150 for i := 0; i < 10; i++ {
151 labels = append(labels, fmt.Sprintf("key%03d", i), fmt.Sprintf("value%03d", i))
152 }
153 if scenario == "unordered" {
154 labels[0], labels[len(labels)-1] = labels[len(labels)-1], labels[0]
155 }
156
157 b.Run(scenario, func(b *testing.B) {
158 b.Run("set-many", func(b *testing.B) {
159 b.ReportAllocs()
160 b.ResetTimer()
161 for i := 0; i < b.N; i++ {
162 Do(context.Background(), Labels(labels...), func(context.Context) {})
163 }
164 })
165
166 b.Run("merge-many", func(b *testing.B) {
167 ctx := WithLabels(context.Background(), Labels(labels[:len(labels)/2]...))
168
169 b.ResetTimer()
170 b.ReportAllocs()
171 for i := 0; i < b.N; i++ {
172 Do(ctx, Labels(labels[len(labels)/2:]...), func(context.Context) {})
173 }
174 })
175
176 b.Run("overwrite-many", func(b *testing.B) {
177 ctx := WithLabels(context.Background(), Labels(labels...))
178
179 b.ReportAllocs()
180 b.ResetTimer()
181 for i := 0; i < b.N; i++ {
182 Do(ctx, Labels(labels...), func(context.Context) {})
183 }
184 })
185 })
186 }
187
188
189 }
190
View as plain text