@@ -173,4 +173,150 @@ func TestSMK6(t *testing.T) {
173
173
}
174
174
}
175
175
})
176
+
177
+ t .Run ("metrics have expected values" , func (t * testing.T ) {
178
+ t .Parallel ()
179
+
180
+ type testCase struct {
181
+ name string
182
+ metricName string // Metric name to assert.
183
+ metricLabels map [string ]string
184
+ assertValue func (float64 ) bool
185
+ }
186
+
187
+ for _ , tc := range []testCase {
188
+ // Some global metrics.
189
+ {
190
+ name : "Script duration seconds" ,
191
+ metricName : "probe_script_duration_seconds" ,
192
+ assertValue : nonZero ,
193
+ },
194
+ {
195
+ name : "Sent bytes" ,
196
+ metricName : "probe_data_sent_bytes" ,
197
+ assertValue : nonZero ,
198
+ },
199
+ {
200
+ name : "Received bytes" ,
201
+ metricName : "probe_data_received_bytes" ,
202
+ assertValue : nonZero ,
203
+ },
204
+ // Check-related metrics.
205
+ {
206
+ name : "Passed checks metric" ,
207
+ metricName : "probe_checks_total" ,
208
+ metricLabels : map [string ]string {"result" : "pass" },
209
+ assertValue : equals (1 ),
210
+ },
211
+ {
212
+ name : "Failed checks metric" ,
213
+ metricName : "probe_checks_total" ,
214
+ metricLabels : map [string ]string {"result" : "fail" },
215
+ assertValue : equals (2 ),
216
+ },
217
+ // Misc http metrics.
218
+ {
219
+ name : "HTTP duration second has a duration-ish value" ,
220
+ metricName : "probe_http_duration_seconds" ,
221
+ metricLabels : map [string ]string {"phase" : "processing" , "url" : "https://test-api.k6.io/public/crocodiles/" },
222
+ assertValue : nonZero ,
223
+ },
224
+ {
225
+ name : "HTTP duration seconds has custom 'resolve' phase" ,
226
+ metricName : "probe_http_duration_seconds" ,
227
+ metricLabels : map [string ]string {"phase" : "resolve" , "url" : "https://test-api.k6.io/public/crocodiles/" },
228
+ assertValue : any , // Just fail if not present.
229
+ },
230
+ {
231
+ name : "Error code for request that should succeed" ,
232
+ metricName : "probe_http_error_code" ,
233
+ metricLabels : map [string ]string {"url" : "https://test-api.k6.io/public/crocodiles/" },
234
+ assertValue : equals (0 ),
235
+ },
236
+ {
237
+ name : "Error code for request that should fail" ,
238
+ metricName : "probe_http_error_code" ,
239
+ metricLabels : map [string ]string {"url" : "http://fail.internal/public/crocodiles4/" },
240
+ assertValue : equals (1101 ),
241
+ },
242
+ {
243
+ name : "HTTP status code for a request that should succeed" ,
244
+ metricName : "probe_http_status_code" ,
245
+ metricLabels : map [string ]string {"url" : "https://test-api.k6.io/public/crocodiles/" },
246
+ assertValue : equals (200 ),
247
+ },
248
+ {
249
+ name : "Expected response for a request that should succeed" ,
250
+ metricName : "probe_http_got_expected_response" ,
251
+ metricLabels : map [string ]string {"url" : "https://test-api.k6.io/public/crocodiles/" },
252
+ assertValue : equals (1 ),
253
+ },
254
+ {
255
+ name : "Expected response for a request that should fail" ,
256
+ metricName : "probe_http_got_expected_response" ,
257
+ metricLabels : map [string ]string {"url" : "https://test-api.k6.io/public/crocodiles2/" },
258
+ assertValue : equals (0 ),
259
+ },
260
+ {
261
+ name : "Total requests for each url" ,
262
+ metricName : "probe_http_requests_total" ,
263
+ assertValue : equals (1 ),
264
+ },
265
+ {
266
+ name : "HTTP version" ,
267
+ metricName : "probe_http_version" ,
268
+ metricLabels : map [string ]string {"url" : "https://test-api.k6.io/public/crocodiles/" },
269
+ assertValue : func (f float64 ) bool { return f >= 1.1 },
270
+ },
271
+ } {
272
+ tc := tc
273
+ t .Run (tc .name , func (t * testing.T ) {
274
+ matchedMetrics := 0
275
+ for _ , mf := range mfs {
276
+ if * mf .Name != tc .metricName {
277
+ // This is not the metric we are asserting on
278
+ continue
279
+ }
280
+
281
+ metric:
282
+ for _ , m := range mf .Metric {
283
+ for _ , labelPair := range m .Label {
284
+ // Check each label of this particular metric against the test case labels.
285
+ // If the metric has a label we're not matching for, that's okay, but it we are matching
286
+ // it then the value should match as well.
287
+ if actual , present := tc .metricLabels [* labelPair .Name ]; present && actual != * labelPair .Value {
288
+ continue metric
289
+ }
290
+ }
291
+
292
+ matchedMetrics ++
293
+ // Hack. Instead of check which type this metric has, and then use that one, rely on GetValue
294
+ // that does this check for us and return 0 if the type is not correct.
295
+ metricValue := m .Gauge .GetValue () + m .Counter .GetValue () + m .Untyped .GetValue ()
296
+ if ! tc .assertValue (metricValue ) {
297
+ t .Fatalf ("Metric value for %q got unexpected value %v (did not satisfy assert function)" , * mf .Name , metricValue )
298
+ }
299
+ }
300
+ }
301
+
302
+ if matchedMetrics == 0 {
303
+ t .Fatalf ("Test case for %q with specified labels matched no metric in extension output" , tc .metricName )
304
+ }
305
+ })
306
+ }
307
+ })
308
+ }
309
+
310
+ func equals (expected float64 ) func (float64 ) bool {
311
+ return func (v float64 ) bool {
312
+ return v == expected
313
+ }
314
+ }
315
+
316
+ func nonZero (v float64 ) bool {
317
+ return v > 0
318
+ }
319
+
320
+ func any (float64 ) bool {
321
+ return true
176
322
}
0 commit comments