@@ -2,9 +2,11 @@ package remotewrite
22
33import (
44 "math/rand"
5+ "sort"
56 "testing"
67 "time"
78
9+ "github.com/prometheus/prometheus/prompb"
810 "github.com/stretchr/testify/assert"
911 "go.k6.io/k6/metrics"
1012)
@@ -108,3 +110,115 @@ func BenchmarkTrendAdd(b *testing.B) {
108110 benchF [1 ](b , start )
109111 })
110112}
113+
114+ // buildTimeSeries creates a TimSeries with the given name, value and timestamp
115+ func buildTimeSeries (name string , value float64 , timestamp time.Time ) prompb.TimeSeries {
116+ return prompb.TimeSeries {
117+ Labels : []prompb.Label {
118+ {
119+ Name : "__name__" ,
120+ Value : name ,
121+ },
122+ },
123+ Samples : []prompb.Sample {
124+ {
125+ Value : value ,
126+ Timestamp : timestamp .Unix (),
127+ },
128+ },
129+ }
130+ }
131+
132+ // getTimeSeriesName returs the name of the timeseries defined in the '__name__' label
133+ func getTimeSeriesName (ts prompb.TimeSeries ) string {
134+ for _ , l := range ts .Labels {
135+ if l .Name == "__name__" {
136+ return l .Value
137+ }
138+ }
139+ return ""
140+ }
141+
142+ // assertTimeSeriesEqual compares if two TimeSeries has the same name and value.
143+ // Assumes only one sample per TimeSeries
144+ func assertTimeSeriesEqual (t * testing.T , expected prompb.TimeSeries , actual prompb.TimeSeries ) {
145+ expectedName := getTimeSeriesName (expected )
146+ actualName := getTimeSeriesName (actual )
147+ if expectedName != actualName {
148+ t .Errorf ("names do not match expected: %s actual: %s" , expectedName , actualName )
149+ }
150+
151+ expectedValue := expected .Samples [0 ].Value
152+ actualValue := actual .Samples [0 ].Value
153+ if expectedValue != actualValue {
154+ t .Errorf ("values do not match expected: %f actual: %f" , expectedValue , actualValue )
155+ }
156+ }
157+
158+ // sortTimeSeries sorts an array of TimeSeries by name
159+ func sortTimeSeries (ts []prompb.TimeSeries ) []prompb.TimeSeries {
160+ sorted := make ([]prompb.TimeSeries , len (ts ))
161+ copy (sorted , ts )
162+ sort .Slice (sorted , func (i int , j int ) bool {
163+ return getTimeSeriesName (sorted [i ]) < getTimeSeriesName (sorted [j ])
164+ })
165+
166+ return sorted
167+ }
168+
169+ // assertTimeSeriesMatch asserts if the elements of two arrays of TimeSeries match not considering order
170+ func assertTimeSeriesMatch (t * testing.T , expected []prompb.TimeSeries , actual []prompb.TimeSeries ) {
171+ if len (expected ) != len (actual ) {
172+ t .Errorf ("timeseries length does not match. expected %d actual: %d" , len (expected ), len (actual ))
173+ }
174+
175+ //sort arrays
176+ se := sortTimeSeries (expected )
177+ sa := sortTimeSeries (actual )
178+
179+ //return false if any element does not match
180+ for i := 0 ; i < len (se ); i ++ {
181+ assertTimeSeriesEqual (t , se [i ], sa [i ])
182+ }
183+
184+ }
185+
186+ func TestMapTrend (t * testing.T ) {
187+ t .Parallel ()
188+
189+ now := time .Now ()
190+ testCases := []struct {
191+ storage * metricsStorage
192+ sample metrics.Sample
193+ labels []prompb.Label
194+ expected []prompb.TimeSeries
195+ }{
196+ {
197+ storage : newMetricsStorage (),
198+ sample : metrics.Sample {
199+ Metric : & metrics.Metric {
200+ Name : "test" ,
201+ Type : metrics .Trend ,
202+ },
203+ Value : 1.0 ,
204+ Time : now ,
205+ },
206+ expected : []prompb.TimeSeries {
207+ buildTimeSeries ("k6_test_count" , 1.0 , now ),
208+ buildTimeSeries ("k6_test_sum" , 1.0 , now ),
209+ buildTimeSeries ("k6_test_min" , 1.0 , now ),
210+ buildTimeSeries ("k6_test_max" , 1.0 , now ),
211+ buildTimeSeries ("k6_test_avg" , 1.0 , now ),
212+ buildTimeSeries ("k6_test_med" , 1.0 , now ),
213+ buildTimeSeries ("k6_test_p90" , 1.0 , now ),
214+ buildTimeSeries ("k6_test_p95" , 1.0 , now ),
215+ },
216+ },
217+ }
218+
219+ for _ , tc := range testCases {
220+ m := & PrometheusMapping {}
221+ ts := m .MapTrend (tc .storage , tc .sample , tc .labels )
222+ assertTimeSeriesMatch (t , tc .expected , ts )
223+ }
224+ }
0 commit comments