Skip to content

Commit a4d14b3

Browse files
authored
Merge pull request #225 from prometheus/beorn7/testing
Add "real" collision to MetricVec tests
2 parents dadfef8 + 1f823ab commit a4d14b3

File tree

2 files changed

+117
-49
lines changed

2 files changed

+117
-49
lines changed

prometheus/vec.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,13 @@ func (m *MetricVec) Delete(labels Labels) bool {
201201
// that metric.
202202
//
203203
// lvs MUST be of type Labels or []string or this method will panic.
204-
func (m *MetricVec) deleteByHash(h uint64, values interface{}) bool {
204+
func (m *MetricVec) deleteByHash(h uint64, lvs interface{}) bool {
205205
metrics, ok := m.children[h]
206206
if !ok {
207207
return false
208208
}
209209

210-
i := m.findMetric(metrics, values)
210+
i := m.findMetric(metrics, lvs)
211211
if i >= len(metrics) {
212212
return false
213213
}

prometheus/vec_test.go

Lines changed: 115 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,30 @@ import (
2121
)
2222

2323
func TestDelete(t *testing.T) {
24-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
24+
vec := NewUntypedVec(
25+
UntypedOpts{
26+
Name: "test",
27+
Help: "helpless",
28+
},
29+
[]string{"l1", "l2"},
30+
)
2531
testDelete(t, vec)
2632
}
2733

2834
func TestDeleteWithCollisions(t *testing.T) {
29-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
35+
vec := NewUntypedVec(
36+
UntypedOpts{
37+
Name: "test",
38+
Help: "helpless",
39+
},
40+
[]string{"l1", "l2"},
41+
)
3042
vec.hashAdd = func(h uint64, s string) uint64 { return 1 }
3143
vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 }
3244
testDelete(t, vec)
3345
}
3446

35-
func testDelete(t *testing.T, vec *MetricVec) {
47+
func testDelete(t *testing.T, vec *UntypedVec) {
3648
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want {
3749
t.Errorf("got %v, want %v", got, want)
3850
}
@@ -63,24 +75,36 @@ func testDelete(t *testing.T, vec *MetricVec) {
6375
}
6476

6577
func TestDeleteLabelValues(t *testing.T) {
66-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
78+
vec := NewUntypedVec(
79+
UntypedOpts{
80+
Name: "test",
81+
Help: "helpless",
82+
},
83+
[]string{"l1", "l2"},
84+
)
6785
testDeleteLabelValues(t, vec)
6886
}
6987

7088
func TestDeleteLabelValuesWithCollisions(t *testing.T) {
71-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
89+
vec := NewUntypedVec(
90+
UntypedOpts{
91+
Name: "test",
92+
Help: "helpless",
93+
},
94+
[]string{"l1", "l2"},
95+
)
7296
vec.hashAdd = func(h uint64, s string) uint64 { return 1 }
7397
vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 }
7498
testDeleteLabelValues(t, vec)
7599
}
76100

77-
func testDeleteLabelValues(t *testing.T, vec *MetricVec) {
101+
func testDeleteLabelValues(t *testing.T, vec *UntypedVec) {
78102
if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want {
79103
t.Errorf("got %v, want %v", got, want)
80104
}
81105

82106
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
83-
vec.With(Labels{"l1": "v1", "l2": "v3"}).(Untyped).Set(42) // add junk data for collision
107+
vec.With(Labels{"l1": "v1", "l2": "v3"}).(Untyped).Set(42) // Add junk data for collision.
84108
if got, want := vec.DeleteLabelValues("v1", "v2"), true; got != want {
85109
t.Errorf("got %v, want %v", got, want)
86110
}
@@ -92,7 +116,7 @@ func testDeleteLabelValues(t *testing.T, vec *MetricVec) {
92116
}
93117

94118
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
95-
// delete out of order
119+
// Delete out of order.
96120
if got, want := vec.DeleteLabelValues("v2", "v1"), false; got != want {
97121
t.Errorf("got %v, want %v", got, want)
98122
}
@@ -102,28 +126,40 @@ func testDeleteLabelValues(t *testing.T, vec *MetricVec) {
102126
}
103127

104128
func TestMetricVec(t *testing.T) {
105-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
129+
vec := NewUntypedVec(
130+
UntypedOpts{
131+
Name: "test",
132+
Help: "helpless",
133+
},
134+
[]string{"l1", "l2"},
135+
)
106136
testMetricVec(t, vec)
107137
}
108138

109139
func TestMetricVecWithCollisions(t *testing.T) {
110-
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
140+
vec := NewUntypedVec(
141+
UntypedOpts{
142+
Name: "test",
143+
Help: "helpless",
144+
},
145+
[]string{"l1", "l2"},
146+
)
111147
vec.hashAdd = func(h uint64, s string) uint64 { return 1 }
112148
vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 }
113149
testMetricVec(t, vec)
114150
}
115151

116-
func testMetricVec(t *testing.T, vec *MetricVec) {
117-
vec.Reset() // actually test Reset now!
152+
func testMetricVec(t *testing.T, vec *UntypedVec) {
153+
vec.Reset() // Actually test Reset now!
118154

119155
var pair [2]string
120-
// keep track of metrics
156+
// Keep track of metrics.
121157
expected := map[[2]string]int{}
122158

123159
for i := 0; i < 1000; i++ {
124-
pair[0], pair[1] = fmt.Sprint(i%4), fmt.Sprint(i%5) // varying combinations multiples
160+
pair[0], pair[1] = fmt.Sprint(i%4), fmt.Sprint(i%5) // Varying combinations multiples.
125161
expected[pair]++
126-
vec.WithLabelValues(pair[0], pair[1]).(Untyped).Inc()
162+
vec.WithLabelValues(pair[0], pair[1]).Inc()
127163

128164
expected[[2]string{"v1", "v2"}]++
129165
vec.WithLabelValues("v1", "v2").(Untyped).Inc()
@@ -135,17 +171,18 @@ func testMetricVec(t *testing.T, vec *MetricVec) {
135171
total++
136172
copy(pair[:], metric.values)
137173

138-
// is there a better way to access the value of a metric?
139174
var metricOut dto.Metric
140-
metric.metric.Write(&metricOut)
175+
if err := metric.metric.Write(&metricOut); err != nil {
176+
t.Fatal(err)
177+
}
141178
actual := *metricOut.Untyped.Value
142179

143180
var actualPair [2]string
144181
for i, label := range metricOut.Label {
145182
actualPair[i] = *label.Value
146183
}
147184

148-
// test output pair against metric.values to ensure we've selected
185+
// Test output pair against metric.values to ensure we've selected
149186
// the right one. We check this to ensure the below check means
150187
// anything at all.
151188
if actualPair != pair {
@@ -169,42 +206,67 @@ func testMetricVec(t *testing.T, vec *MetricVec) {
169206
}
170207
}
171208

172-
func newUntypedMetricVec(name, help string, labels []string) *MetricVec {
173-
desc := NewDesc("test", "helpless", labels, nil)
174-
vec := newMetricVec(desc, func(lvs ...string) Metric {
175-
return newValue(desc, UntypedValue, 0, lvs...)
176-
})
177-
return &vec
209+
func TestCounterVecEndToEndWithCollision(t *testing.T) {
210+
vec := NewCounterVec(
211+
CounterOpts{
212+
Name: "test",
213+
Help: "helpless",
214+
},
215+
[]string{"labelname"},
216+
)
217+
vec.WithLabelValues("77kepQFQ8Kl").Inc()
218+
vec.WithLabelValues("!0IC=VloaY").Add(2)
219+
220+
m := &dto.Metric{}
221+
if err := vec.WithLabelValues("77kepQFQ8Kl").Write(m); err != nil {
222+
t.Fatal(err)
223+
}
224+
if got, want := m.GetLabel()[0].GetValue(), "77kepQFQ8Kl"; got != want {
225+
t.Errorf("got label value %q, want %q", got, want)
226+
}
227+
if got, want := m.GetCounter().GetValue(), 1.; got != want {
228+
t.Errorf("got value %d, want %d", got, want)
229+
}
230+
m.Reset()
231+
if err := vec.WithLabelValues("!0IC=VloaY").Write(m); err != nil {
232+
t.Fatal(err)
233+
}
234+
if got, want := m.GetLabel()[0].GetValue(), "!0IC=VloaY"; got != want {
235+
t.Errorf("got label value %q, want %q", got, want)
236+
}
237+
if got, want := m.GetCounter().GetValue(), 2.; got != want {
238+
t.Errorf("got value %d, want %d", got, want)
239+
}
178240
}
179241

180-
func BenchmarkMetricVecWithLabelValuesBasic(B *testing.B) {
181-
benchmarkMetricVecWithLabelValues(B, map[string][]string{
242+
func BenchmarkMetricVecWithLabelValuesBasic(b *testing.B) {
243+
benchmarkMetricVecWithLabelValues(b, map[string][]string{
182244
"l1": []string{"onevalue"},
183245
"l2": []string{"twovalue"},
184246
})
185247
}
186248

187-
func BenchmarkMetricVecWithLabelValues2Keys10ValueCardinality(B *testing.B) {
188-
benchmarkMetricVecWithLabelValuesCardinality(B, 2, 10)
249+
func BenchmarkMetricVecWithLabelValues2Keys10ValueCardinality(b *testing.B) {
250+
benchmarkMetricVecWithLabelValuesCardinality(b, 2, 10)
189251
}
190252

191-
func BenchmarkMetricVecWithLabelValues4Keys10ValueCardinality(B *testing.B) {
192-
benchmarkMetricVecWithLabelValuesCardinality(B, 4, 10)
253+
func BenchmarkMetricVecWithLabelValues4Keys10ValueCardinality(b *testing.B) {
254+
benchmarkMetricVecWithLabelValuesCardinality(b, 4, 10)
193255
}
194256

195-
func BenchmarkMetricVecWithLabelValues2Keys100ValueCardinality(B *testing.B) {
196-
benchmarkMetricVecWithLabelValuesCardinality(B, 2, 100)
257+
func BenchmarkMetricVecWithLabelValues2Keys100ValueCardinality(b *testing.B) {
258+
benchmarkMetricVecWithLabelValuesCardinality(b, 2, 100)
197259
}
198260

199-
func BenchmarkMetricVecWithLabelValues10Keys100ValueCardinality(B *testing.B) {
200-
benchmarkMetricVecWithLabelValuesCardinality(B, 10, 100)
261+
func BenchmarkMetricVecWithLabelValues10Keys100ValueCardinality(b *testing.B) {
262+
benchmarkMetricVecWithLabelValuesCardinality(b, 10, 100)
201263
}
202264

203-
func BenchmarkMetricVecWithLabelValues10Keys1000ValueCardinality(B *testing.B) {
204-
benchmarkMetricVecWithLabelValuesCardinality(B, 10, 1000)
265+
func BenchmarkMetricVecWithLabelValues10Keys1000ValueCardinality(b *testing.B) {
266+
benchmarkMetricVecWithLabelValuesCardinality(b, 10, 1000)
205267
}
206268

207-
func benchmarkMetricVecWithLabelValuesCardinality(B *testing.B, nkeys, nvalues int) {
269+
func benchmarkMetricVecWithLabelValuesCardinality(b *testing.B, nkeys, nvalues int) {
208270
labels := map[string][]string{}
209271

210272
for i := 0; i < nkeys; i++ {
@@ -218,22 +280,28 @@ func benchmarkMetricVecWithLabelValuesCardinality(B *testing.B, nkeys, nvalues i
218280
labels[k] = vs
219281
}
220282

221-
benchmarkMetricVecWithLabelValues(B, labels)
283+
benchmarkMetricVecWithLabelValues(b, labels)
222284
}
223285

224-
func benchmarkMetricVecWithLabelValues(B *testing.B, labels map[string][]string) {
286+
func benchmarkMetricVecWithLabelValues(b *testing.B, labels map[string][]string) {
225287
var keys []string
226-
for k := range labels { // map order dependent, who cares though
288+
for k := range labels { // Map order dependent, who cares though.
227289
keys = append(keys, k)
228290
}
229291

230-
values := make([]string, len(labels)) // value cache for permutations
231-
vec := newUntypedMetricVec("test", "helpless", keys)
232-
233-
B.ReportAllocs()
234-
B.ResetTimer()
235-
for i := 0; i < B.N; i++ {
236-
// varies input across provide map entries based on key size.
292+
values := make([]string, len(labels)) // Value cache for permutations.
293+
vec := NewUntypedVec(
294+
UntypedOpts{
295+
Name: "test",
296+
Help: "helpless",
297+
},
298+
keys,
299+
)
300+
301+
b.ReportAllocs()
302+
b.ResetTimer()
303+
for i := 0; i < b.N; i++ {
304+
// Varies input across provide map entries based on key size.
237305
for j, k := range keys {
238306
candidates := labels[k]
239307
values[j] = candidates[i%len(candidates)]

0 commit comments

Comments
 (0)