Skip to content

Commit 63658c2

Browse files
Add unit tests for histogram proto conversions (#7354)
* Add unit tests for histogram proto conversions Signed-off-by: Artem Muterko <artem@sopho.tech> * Update pkg/cortexpb/histograms_test.go Co-authored-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> Signed-off-by: Archy <6429715+archy-rock3t-cloud@users.noreply.github.com> * Update pkg/cortexpb/histograms_test.go Co-authored-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> Signed-off-by: Archy <6429715+archy-rock3t-cloud@users.noreply.github.com> --------- Signed-off-by: Artem Muterko <artem@sopho.tech> Signed-off-by: Archy <6429715+archy-rock3t-cloud@users.noreply.github.com> Co-authored-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com>
1 parent 5082ead commit 63658c2

1 file changed

Lines changed: 213 additions & 0 deletions

File tree

pkg/cortexpb/histograms_test.go

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package cortexpb
2+
3+
import (
4+
"testing"
5+
6+
"github.com/prometheus/prometheus/model/histogram"
7+
"github.com/prometheus/prometheus/prompb"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestIsFloatHistogram(t *testing.T) {
13+
t.Run("integer histogram", func(t *testing.T) {
14+
h := Histogram{
15+
Count: &Histogram_CountInt{CountInt: 10},
16+
ZeroCount: &Histogram_ZeroCountInt{ZeroCountInt: 1},
17+
}
18+
assert.False(t, h.IsFloatHistogram())
19+
})
20+
21+
t.Run("float histogram", func(t *testing.T) {
22+
h := Histogram{
23+
Count: &Histogram_CountFloat{CountFloat: 10.5},
24+
ZeroCount: &Histogram_ZeroCountFloat{ZeroCountFloat: 1.5},
25+
}
26+
assert.True(t, h.IsFloatHistogram())
27+
})
28+
29+
t.Run("zero value histogram", func(t *testing.T) {
30+
h := Histogram{}
31+
assert.False(t, h.IsFloatHistogram())
32+
})
33+
}
34+
35+
func TestHistogramToHistogramProtoRoundTrip(t *testing.T) {
36+
original := &histogram.Histogram{
37+
CounterResetHint: histogram.GaugeType,
38+
Schema: 3,
39+
ZeroThreshold: 0.001,
40+
ZeroCount: 5,
41+
Count: 30,
42+
Sum: 19.4,
43+
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 1}},
44+
PositiveBuckets: []int64{1, 2, -1},
45+
NegativeSpans: []histogram.Span{{Offset: 1, Length: 1}},
46+
NegativeBuckets: []int64{3},
47+
CustomValues: []float64{1.0, 2.0},
48+
}
49+
50+
timestamp := int64(1234567890)
51+
proto := HistogramToHistogramProto(timestamp, original)
52+
result := HistogramProtoToHistogram(proto)
53+
54+
assert.Equal(t, original.CounterResetHint, result.CounterResetHint)
55+
assert.Equal(t, original.Schema, result.Schema)
56+
assert.Equal(t, original.ZeroThreshold, result.ZeroThreshold)
57+
assert.Equal(t, original.ZeroCount, result.ZeroCount)
58+
assert.Equal(t, original.Count, result.Count)
59+
assert.Equal(t, original.Sum, result.Sum)
60+
assert.Equal(t, original.PositiveSpans, result.PositiveSpans)
61+
assert.Equal(t, original.PositiveBuckets, result.PositiveBuckets)
62+
assert.Equal(t, original.NegativeSpans, result.NegativeSpans)
63+
assert.Equal(t, original.NegativeBuckets, result.NegativeBuckets)
64+
assert.Equal(t, original.CustomValues, result.CustomValues)
65+
assert.Equal(t, timestamp, proto.TimestampMs)
66+
// Catch-all: ensure no fields are missed if new fields are added to histogram.Histogram.
67+
assert.Equal(t, original, result)
68+
}
69+
70+
func TestFloatHistogramToHistogramProtoRoundTrip(t *testing.T) {
71+
original := &histogram.FloatHistogram{
72+
CounterResetHint: histogram.NotCounterReset,
73+
Schema: 5,
74+
ZeroThreshold: 0.01,
75+
ZeroCount: 2.5,
76+
Count: 20.5,
77+
Sum: 35.7,
78+
PositiveSpans: []histogram.Span{{Offset: 0, Length: 3}},
79+
PositiveBuckets: []float64{1.5, 2.5, 3.5},
80+
NegativeSpans: []histogram.Span{{Offset: 2, Length: 2}},
81+
NegativeBuckets: []float64{0.5, 1.5},
82+
CustomValues: []float64{10.0},
83+
}
84+
85+
timestamp := int64(9876543210)
86+
proto := FloatHistogramToHistogramProto(timestamp, original)
87+
result := FloatHistogramProtoToFloatHistogram(proto)
88+
89+
assert.Equal(t, original.CounterResetHint, result.CounterResetHint)
90+
assert.Equal(t, original.Schema, result.Schema)
91+
assert.Equal(t, original.ZeroThreshold, result.ZeroThreshold)
92+
assert.Equal(t, original.ZeroCount, result.ZeroCount)
93+
assert.Equal(t, original.Count, result.Count)
94+
assert.Equal(t, original.Sum, result.Sum)
95+
assert.Equal(t, original.PositiveSpans, result.PositiveSpans)
96+
assert.Equal(t, original.PositiveBuckets, result.PositiveBuckets)
97+
assert.Equal(t, original.NegativeSpans, result.NegativeSpans)
98+
assert.Equal(t, original.NegativeBuckets, result.NegativeBuckets)
99+
assert.Equal(t, original.CustomValues, result.CustomValues)
100+
assert.Equal(t, timestamp, proto.TimestampMs)
101+
// Catch-all: ensure no fields are missed if new fields are added to histogram.FloatHistogram.
102+
assert.Equal(t, original, result)
103+
}
104+
105+
func TestHistogramProtoToHistogramPanicsOnFloat(t *testing.T) {
106+
floatProto := FloatHistogramToHistogramProto(0, &histogram.FloatHistogram{
107+
Count: 10.5,
108+
ZeroCount: 1.5,
109+
})
110+
111+
assert.Panics(t, func() {
112+
HistogramProtoToHistogram(floatProto)
113+
})
114+
}
115+
116+
func TestFloatHistogramProtoToFloatHistogramPanicsOnInt(t *testing.T) {
117+
intProto := HistogramToHistogramProto(0, &histogram.Histogram{
118+
Count: 10,
119+
ZeroCount: 1,
120+
})
121+
122+
assert.Panics(t, func() {
123+
FloatHistogramProtoToFloatHistogram(intProto)
124+
})
125+
}
126+
127+
func TestHistogramPromProtoToHistogramProto(t *testing.T) {
128+
t.Run("integer histogram", func(t *testing.T) {
129+
promProto := prompb.Histogram{
130+
Count: &prompb.Histogram_CountInt{CountInt: 15},
131+
Sum: 42.5,
132+
Schema: 3,
133+
ZeroThreshold: 0.001,
134+
ZeroCount: &prompb.Histogram_ZeroCountInt{ZeroCountInt: 2},
135+
NegativeSpans: []prompb.BucketSpan{{Offset: 0, Length: 2}},
136+
NegativeDeltas: []int64{1, -1},
137+
PositiveSpans: []prompb.BucketSpan{{Offset: 1, Length: 3}},
138+
PositiveDeltas: []int64{1, 2, -2},
139+
ResetHint: prompb.Histogram_GAUGE,
140+
Timestamp: 1000,
141+
CustomValues: []float64{5.0},
142+
}
143+
144+
result := HistogramPromProtoToHistogramProto(promProto)
145+
146+
assert.Equal(t, uint64(15), result.GetCountInt())
147+
assert.Equal(t, 42.5, result.Sum)
148+
assert.Equal(t, int32(3), result.Schema)
149+
assert.Equal(t, 0.001, result.ZeroThreshold)
150+
assert.Equal(t, uint64(2), result.GetZeroCountInt())
151+
assert.Equal(t, []int64{1, -1}, result.NegativeDeltas)
152+
assert.Equal(t, []int64{1, 2, -2}, result.PositiveDeltas)
153+
assert.Equal(t, Histogram_GAUGE, result.ResetHint)
154+
assert.Equal(t, int64(1000), result.TimestampMs)
155+
assert.Equal(t, []float64{5.0}, result.CustomValues)
156+
require.Len(t, result.NegativeSpans, 1)
157+
assert.Equal(t, int32(0), result.NegativeSpans[0].Offset)
158+
assert.Equal(t, uint32(2), result.NegativeSpans[0].Length)
159+
require.Len(t, result.PositiveSpans, 1)
160+
assert.Equal(t, int32(1), result.PositiveSpans[0].Offset)
161+
assert.Equal(t, uint32(3), result.PositiveSpans[0].Length)
162+
assert.False(t, result.IsFloatHistogram())
163+
})
164+
165+
t.Run("float histogram", func(t *testing.T) {
166+
promProto := prompb.Histogram{
167+
Count: &prompb.Histogram_CountFloat{CountFloat: 20.5},
168+
Sum: 100.1,
169+
Schema: 5,
170+
ZeroThreshold: 0.01,
171+
ZeroCount: &prompb.Histogram_ZeroCountFloat{ZeroCountFloat: 3.5},
172+
PositiveSpans: []prompb.BucketSpan{{Offset: 0, Length: 1}},
173+
PositiveCounts: []float64{7.5},
174+
Timestamp: 2000,
175+
}
176+
177+
result := HistogramPromProtoToHistogramProto(promProto)
178+
179+
assert.Equal(t, 20.5, result.GetCountFloat())
180+
assert.Equal(t, 3.5, result.GetZeroCountFloat())
181+
assert.True(t, result.IsFloatHistogram())
182+
assert.Equal(t, []float64{7.5}, result.PositiveCounts)
183+
})
184+
}
185+
186+
func TestSpansConversions(t *testing.T) {
187+
t.Run("nil input", func(t *testing.T) {
188+
result := spansProtoToSpans(nil)
189+
assert.Empty(t, result)
190+
191+
result2 := spansToSpansProto(nil)
192+
assert.Empty(t, result2)
193+
194+
result3 := spansPromProtoToSpansProto(nil)
195+
assert.Empty(t, result3)
196+
})
197+
198+
t.Run("round trip", func(t *testing.T) {
199+
original := []histogram.Span{
200+
{Offset: 0, Length: 2},
201+
{Offset: 3, Length: 5},
202+
{Offset: -1, Length: 1},
203+
}
204+
205+
proto := spansToSpansProto(original)
206+
require.Len(t, proto, 3)
207+
assert.Equal(t, int32(0), proto[0].Offset)
208+
assert.Equal(t, uint32(2), proto[0].Length)
209+
210+
result := spansProtoToSpans(proto)
211+
assert.Equal(t, original, result)
212+
})
213+
}

0 commit comments

Comments
 (0)