summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/nginxplus/nginxplus_test.go
blob: 7c6f4fc765a44e3a015c5b3120b3634a8e6e8162 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
// SPDX-License-Identifier: GPL-3.0-or-later

package nginxplus

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/netdata/netdata/go/go.d.plugin/agent/module"
	"github.com/netdata/netdata/go/go.d.plugin/pkg/web"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

var (
	dataConfigJSON, _ = os.ReadFile("testdata/config.json")
	dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")

	dataAPI8APIVersions, _       = os.ReadFile("testdata/api-8/api_versions.json")
	dataAPI8Connections, _       = os.ReadFile("testdata/api-8/connections.json")
	dataAPI8EndpointsHTTP, _     = os.ReadFile("testdata/api-8/endpoints_http.json")
	dataAPI8EndpointsRoot, _     = os.ReadFile("testdata/api-8/endpoints_root.json")
	dataAPI8EndpointsStream, _   = os.ReadFile("testdata/api-8/endpoints_stream.json")
	dataAPI8HTTPCaches, _        = os.ReadFile("testdata/api-8/http_caches.json")
	dataAPI8HTTPLocationZones, _ = os.ReadFile("testdata/api-8/http_location_zones.json")
	dataAPI8HTTPRequests, _      = os.ReadFile("testdata/api-8/http_requests.json")
	dataAPI8HTTPServerZones, _   = os.ReadFile("testdata/api-8/http_server_zones.json")
	dataAPI8HTTPUpstreams, _     = os.ReadFile("testdata/api-8/http_upstreams.json")
	dataAPI8SSL, _               = os.ReadFile("testdata/api-8/ssl.json")
	dataAPI8StreamServerZones, _ = os.ReadFile("testdata/api-8/stream_server_zones.json")
	dataAPI8StreamUpstreams, _   = os.ReadFile("testdata/api-8/stream_upstreams.json")
	dataAPI8Resolvers, _         = os.ReadFile("testdata/api-8/resolvers.json")
	data404, _                   = os.ReadFile("testdata/404.json")
)

func Test_testDataIsValid(t *testing.T) {
	for name, data := range map[string][]byte{
		"dataConfigJSON":            dataConfigJSON,
		"dataConfigYAML":            dataConfigYAML,
		"dataAPI8APIVersions":       dataAPI8APIVersions,
		"dataAPI8Connections":       dataAPI8Connections,
		"dataAPI8EndpointsHTTP":     dataAPI8EndpointsHTTP,
		"dataAPI8EndpointsRoot":     dataAPI8EndpointsRoot,
		"dataAPI8EndpointsStream":   dataAPI8EndpointsStream,
		"dataAPI8HTTPCaches":        dataAPI8HTTPCaches,
		"dataAPI8HTTPLocationZones": dataAPI8HTTPLocationZones,
		"dataAPI8HTTPRequests":      dataAPI8HTTPRequests,
		"dataAPI8HTTPServerZones":   dataAPI8HTTPServerZones,
		"dataAPI8HTTPUpstreams":     dataAPI8HTTPUpstreams,
		"dataAPI8SSL":               dataAPI8SSL,
		"dataAPI8StreamServerZones": dataAPI8StreamServerZones,
		"dataAPI8StreamUpstreams":   dataAPI8StreamUpstreams,
		"dataAPI8Resolvers":         dataAPI8Resolvers,
		"data404":                   data404,
	} {
		require.NotNil(t, data, name)
	}
}

func TestNginxPlus_ConfigurationSerialize(t *testing.T) {
	module.TestConfigurationSerialize(t, &NginxPlus{}, dataConfigJSON, dataConfigYAML)
}

func TestNginxPlus_Init(t *testing.T) {
	tests := map[string]struct {
		wantFail bool
		config   Config
	}{
		"success with default": {
			wantFail: false,
			config:   New().Config,
		},
		"fail when URL not set": {
			wantFail: true,
			config: Config{
				HTTP: web.HTTP{
					Request: web.Request{URL: ""},
				},
			},
		},
	}

	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			nginx := New()
			nginx.Config = test.config

			if test.wantFail {
				assert.Error(t, nginx.Init())
			} else {
				assert.NoError(t, nginx.Init())
			}
		})
	}
}

func TestNginxPlus_Check(t *testing.T) {
	tests := map[string]struct {
		wantFail bool
		prepare  func(t *testing.T) (nginx *NginxPlus, cleanup func())
	}{
		"success when all requests OK": {
			wantFail: false,
			prepare:  caseAPI8AllRequestsOK,
		},
		"success when all requests except stream OK": {
			wantFail: false,
			prepare:  caseAPI8AllRequestsExceptStreamOK,
		},
		"fail on invalid data response": {
			wantFail: true,
			prepare:  caseInvalidDataResponse,
		},
		"fail on connection refused": {
			wantFail: true,
			prepare:  caseConnectionRefused,
		},
	}

	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			nginx, cleanup := test.prepare(t)
			defer cleanup()

			if test.wantFail {
				assert.Error(t, nginx.Check())
			} else {
				assert.NoError(t, nginx.Check())
			}
		})
	}
}

func TestNginxPlus_Collect(t *testing.T) {
	tests := map[string]struct {
		prepare         func(t *testing.T) (nginx *NginxPlus, cleanup func())
		wantNumOfCharts int
		wantMetrics     map[string]int64
	}{
		"success when all requests OK": {
			prepare: caseAPI8AllRequestsOK,
			wantNumOfCharts: len(baseCharts) +
				len(httpCacheChartsTmpl) +
				len(httpServerZoneChartsTmpl) +
				len(httpLocationZoneChartsTmpl)*2 +
				len(httpUpstreamChartsTmpl) +
				len(httpUpstreamServerChartsTmpl)*2 +
				len(streamServerZoneChartsTmpl) +
				len(streamUpstreamChartsTmpl) +
				len(streamUpstreamServerChartsTmpl)*2 +
				len(resolverZoneChartsTmpl)*2,
			wantMetrics: map[string]int64{
				"connections_accepted":                                                                   6079,
				"connections_active":                                                                     1,
				"connections_dropped":                                                                    0,
				"connections_idle":                                                                       8,
				"http_cache_cache_backend_bypassed_bytes":                                                67035,
				"http_cache_cache_backend_bypassed_responses":                                            109,
				"http_cache_cache_backend_served_bytes":                                                  0,
				"http_cache_cache_backend_served_responses":                                              0,
				"http_cache_cache_backend_size":                                                          0,
				"http_cache_cache_backend_state_cold":                                                    0,
				"http_cache_cache_backend_state_warm":                                                    1,
				"http_cache_cache_backend_written_bytes":                                                 0,
				"http_cache_cache_backend_written_responses":                                             0,
				"http_location_zone_server_api_bytes_received":                                           1854427,
				"http_location_zone_server_api_bytes_sent":                                               4668778,
				"http_location_zone_server_api_requests":                                                 9188,
				"http_location_zone_server_api_requests_discarded":                                       0,
				"http_location_zone_server_api_responses":                                                9188,
				"http_location_zone_server_api_responses_1xx":                                            0,
				"http_location_zone_server_api_responses_2xx":                                            9187,
				"http_location_zone_server_api_responses_3xx":                                            0,
				"http_location_zone_server_api_responses_4xx":                                            1,
				"http_location_zone_server_api_responses_5xx":                                            0,
				"http_location_zone_server_dashboard_bytes_received":                                     0,
				"http_location_zone_server_dashboard_bytes_sent":                                         0,
				"http_location_zone_server_dashboard_requests":                                           0,
				"http_location_zone_server_dashboard_requests_discarded":                                 0,
				"http_location_zone_server_dashboard_responses":                                          0,
				"http_location_zone_server_dashboard_responses_1xx":                                      0,
				"http_location_zone_server_dashboard_responses_2xx":                                      0,
				"http_location_zone_server_dashboard_responses_3xx":                                      0,
				"http_location_zone_server_dashboard_responses_4xx":                                      0,
				"http_location_zone_server_dashboard_responses_5xx":                                      0,
				"http_requests_current":                                                                  1,
				"http_requests_total":                                                                    8363,
				"http_server_zone_server_backend_bytes_received":                                         1773834,
				"http_server_zone_server_backend_bytes_sent":                                             4585734,
				"http_server_zone_server_backend_requests":                                               8962,
				"http_server_zone_server_backend_requests_discarded":                                     0,
				"http_server_zone_server_backend_requests_processing":                                    1,
				"http_server_zone_server_backend_responses":                                              8961,
				"http_server_zone_server_backend_responses_1xx":                                          0,
				"http_server_zone_server_backend_responses_2xx":                                          8960,
				"http_server_zone_server_backend_responses_3xx":                                          0,
				"http_server_zone_server_backend_responses_4xx":                                          1,
				"http_server_zone_server_backend_responses_5xx":                                          0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_active":                     0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_received":             0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_sent":                 0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_downtime":                   1020,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_header_time":                0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_requests":                   26,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_response_time":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses":                  0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_1xx":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_2xx":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_3xx":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_4xx":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_5xx":              0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_checking":             0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_down":                 0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_draining":             0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unavail":              1,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unhealthy":            0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_up":                   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_active":                     0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_received":             86496,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_sent":                 9180,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_downtime":                   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_header_time":                1,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_requests":                   102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_response_time":              1,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses":                  102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_1xx":              0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_2xx":              102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_3xx":              0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_4xx":              0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_5xx":              0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_checking":             0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_down":                 0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_draining":             0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unavail":              0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unhealthy":            0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_up":                   1,
				"http_upstream_backend_zone_http_backend_keepalive":                                      0,
				"http_upstream_backend_zone_http_backend_peers":                                          2,
				"http_upstream_backend_zone_http_backend_zombies":                                        0,
				"resolver_zone_resolver-http_requests_addr":                                              0,
				"resolver_zone_resolver-http_requests_name":                                              0,
				"resolver_zone_resolver-http_requests_srv":                                               2939408,
				"resolver_zone_resolver-http_responses_formerr":                                          0,
				"resolver_zone_resolver-http_responses_noerror":                                          0,
				"resolver_zone_resolver-http_responses_notimp":                                           0,
				"resolver_zone_resolver-http_responses_nxdomain":                                         2939404,
				"resolver_zone_resolver-http_responses_refused":                                          0,
				"resolver_zone_resolver-http_responses_servfail":                                         0,
				"resolver_zone_resolver-http_responses_timedout":                                         4,
				"resolver_zone_resolver-http_responses_unknown":                                          0,
				"resolver_zone_resolver-stream_requests_addr":                                            0,
				"resolver_zone_resolver-stream_requests_name":                                            638797,
				"resolver_zone_resolver-stream_requests_srv":                                             0,
				"resolver_zone_resolver-stream_responses_formerr":                                        0,
				"resolver_zone_resolver-stream_responses_noerror":                                        433136,
				"resolver_zone_resolver-stream_responses_notimp":                                         0,
				"resolver_zone_resolver-stream_responses_nxdomain":                                       40022,
				"resolver_zone_resolver-stream_responses_refused":                                        165639,
				"resolver_zone_resolver-stream_responses_servfail":                                       0,
				"resolver_zone_resolver-stream_responses_timedout":                                       0,
				"resolver_zone_resolver-stream_responses_unknown":                                        0,
				"ssl_handshake_timeout":                                                                  4,
				"ssl_handshakes":                                                                         15804607,
				"ssl_handshakes_failed":                                                                  37862,
				"ssl_no_common_cipher":                                                                   24,
				"ssl_no_common_protocol":                                                                 16648,
				"ssl_peer_rejected_cert":                                                                 0,
				"ssl_session_reuses":                                                                     13096060,
				"ssl_verify_failures_expired_cert":                                                       0,
				"ssl_verify_failures_hostname_mismatch":                                                  0,
				"ssl_verify_failures_other":                                                              0,
				"ssl_verify_failures_no_cert":                                                            0,
				"ssl_verify_failures_revoked_cert":                                                       0,
				"stream_server_zone_tcp_server_bytes_received":                                           0,
				"stream_server_zone_tcp_server_bytes_sent":                                               0,
				"stream_server_zone_tcp_server_connections":                                              0,
				"stream_server_zone_tcp_server_connections_discarded":                                    0,
				"stream_server_zone_tcp_server_connections_processing":                                   0,
				"stream_server_zone_tcp_server_sessions":                                                 0,
				"stream_server_zone_tcp_server_sessions_2xx":                                             0,
				"stream_server_zone_tcp_server_sessions_4xx":                                             0,
				"stream_server_zone_tcp_server_sessions_5xx":                                             0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_active":          0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_bytes_received":  0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_bytes_sent":      0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_connections":     0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_downtime":        0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_checking":  0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_down":      0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_unavail":   0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_unhealthy": 0,
				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_up":        1,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_active":          0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_bytes_received":  0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_bytes_sent":      0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_connections":     0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_downtime":        0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_checking":  0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_down":      0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_unavail":   0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_unhealthy": 0,
				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_up":        1,
				"stream_upstream_stream_backend_zone_tcp_servers_peers":                                  2,
				"stream_upstream_stream_backend_zone_tcp_servers_zombies":                                0,
			},
		},
		"success when all requests except stream OK": {
			prepare: caseAPI8AllRequestsExceptStreamOK,
			wantNumOfCharts: len(baseCharts) +
				len(httpCacheChartsTmpl) +
				len(httpServerZoneChartsTmpl) +
				len(httpLocationZoneChartsTmpl)*2 +
				len(httpUpstreamChartsTmpl) +
				len(httpUpstreamServerChartsTmpl)*2 +
				len(resolverZoneChartsTmpl)*2,
			wantMetrics: map[string]int64{
				"connections_accepted":                                                        6079,
				"connections_active":                                                          1,
				"connections_dropped":                                                         0,
				"connections_idle":                                                            8,
				"http_cache_cache_backend_bypassed_bytes":                                     67035,
				"http_cache_cache_backend_bypassed_responses":                                 109,
				"http_cache_cache_backend_served_bytes":                                       0,
				"http_cache_cache_backend_served_responses":                                   0,
				"http_cache_cache_backend_size":                                               0,
				"http_cache_cache_backend_state_cold":                                         0,
				"http_cache_cache_backend_state_warm":                                         1,
				"http_cache_cache_backend_written_bytes":                                      0,
				"http_cache_cache_backend_written_responses":                                  0,
				"http_location_zone_server_api_bytes_received":                                1854427,
				"http_location_zone_server_api_bytes_sent":                                    4668778,
				"http_location_zone_server_api_requests":                                      9188,
				"http_location_zone_server_api_requests_discarded":                            0,
				"http_location_zone_server_api_responses":                                     9188,
				"http_location_zone_server_api_responses_1xx":                                 0,
				"http_location_zone_server_api_responses_2xx":                                 9187,
				"http_location_zone_server_api_responses_3xx":                                 0,
				"http_location_zone_server_api_responses_4xx":                                 1,
				"http_location_zone_server_api_responses_5xx":                                 0,
				"http_location_zone_server_dashboard_bytes_received":                          0,
				"http_location_zone_server_dashboard_bytes_sent":                              0,
				"http_location_zone_server_dashboard_requests":                                0,
				"http_location_zone_server_dashboard_requests_discarded":                      0,
				"http_location_zone_server_dashboard_responses":                               0,
				"http_location_zone_server_dashboard_responses_1xx":                           0,
				"http_location_zone_server_dashboard_responses_2xx":                           0,
				"http_location_zone_server_dashboard_responses_3xx":                           0,
				"http_location_zone_server_dashboard_responses_4xx":                           0,
				"http_location_zone_server_dashboard_responses_5xx":                           0,
				"http_requests_current":                                                       1,
				"http_requests_total":                                                         8363,
				"http_server_zone_server_backend_bytes_received":                              1773834,
				"http_server_zone_server_backend_bytes_sent":                                  4585734,
				"http_server_zone_server_backend_requests":                                    8962,
				"http_server_zone_server_backend_requests_discarded":                          0,
				"http_server_zone_server_backend_requests_processing":                         1,
				"http_server_zone_server_backend_responses":                                   8961,
				"http_server_zone_server_backend_responses_1xx":                               0,
				"http_server_zone_server_backend_responses_2xx":                               8960,
				"http_server_zone_server_backend_responses_3xx":                               0,
				"http_server_zone_server_backend_responses_4xx":                               1,
				"http_server_zone_server_backend_responses_5xx":                               0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_active":          0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_received":  0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_sent":      0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_downtime":        1020,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_header_time":     0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_requests":        26,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_response_time":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses":       0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_1xx":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_2xx":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_3xx":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_4xx":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_5xx":   0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_checking":  0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_down":      0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_draining":  0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unavail":   1,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unhealthy": 0,
				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_up":        0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_active":          0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_received":  86496,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_sent":      9180,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_downtime":        0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_header_time":     1,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_requests":        102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_response_time":   1,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses":       102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_1xx":   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_2xx":   102,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_3xx":   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_4xx":   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_5xx":   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_checking":  0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_down":      0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_draining":  0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unavail":   0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unhealthy": 0,
				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_up":        1,
				"http_upstream_backend_zone_http_backend_keepalive":                           0,
				"http_upstream_backend_zone_http_backend_peers":                               2,
				"http_upstream_backend_zone_http_backend_zombies":                             0,
				"resolver_zone_resolver-http_requests_addr":                                   0,
				"resolver_zone_resolver-http_requests_name":                                   0,
				"resolver_zone_resolver-http_requests_srv":                                    2939408,
				"resolver_zone_resolver-http_responses_formerr":                               0,
				"resolver_zone_resolver-http_responses_noerror":                               0,
				"resolver_zone_resolver-http_responses_notimp":                                0,
				"resolver_zone_resolver-http_responses_nxdomain":                              2939404,
				"resolver_zone_resolver-http_responses_refused":                               0,
				"resolver_zone_resolver-http_responses_servfail":                              0,
				"resolver_zone_resolver-http_responses_timedout":                              4,
				"resolver_zone_resolver-http_responses_unknown":                               0,
				"resolver_zone_resolver-stream_requests_addr":                                 0,
				"resolver_zone_resolver-stream_requests_name":                                 638797,
				"resolver_zone_resolver-stream_requests_srv":                                  0,
				"resolver_zone_resolver-stream_responses_formerr":                             0,
				"resolver_zone_resolver-stream_responses_noerror":                             433136,
				"resolver_zone_resolver-stream_responses_notimp":                              0,
				"resolver_zone_resolver-stream_responses_nxdomain":                            40022,
				"resolver_zone_resolver-stream_responses_refused":                             165639,
				"resolver_zone_resolver-stream_responses_servfail":                            0,
				"resolver_zone_resolver-stream_responses_timedout":                            0,
				"resolver_zone_resolver-stream_responses_unknown":                             0,
				"ssl_handshake_timeout":                                                       4,
				"ssl_handshakes":                                                              15804607,
				"ssl_handshakes_failed":                                                       37862,
				"ssl_no_common_cipher":                                                        24,
				"ssl_no_common_protocol":                                                      16648,
				"ssl_peer_rejected_cert":                                                      0,
				"ssl_session_reuses":                                                          13096060,
				"ssl_verify_failures_expired_cert":                                            0,
				"ssl_verify_failures_hostname_mismatch":                                       0,
				"ssl_verify_failures_other":                                                   0,
				"ssl_verify_failures_no_cert":                                                 0,
				"ssl_verify_failures_revoked_cert":                                            0,
			},
		},
		"fail on invalid data response": {
			prepare:         caseInvalidDataResponse,
			wantNumOfCharts: 0,
			wantMetrics:     nil,
		},
		"fail on connection refused": {
			prepare:         caseConnectionRefused,
			wantNumOfCharts: 0,
			wantMetrics:     nil,
		},
	}

	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			nginx, cleanup := test.prepare(t)
			defer cleanup()

			mx := nginx.Collect()

			require.Equal(t, test.wantMetrics, mx)
			if len(test.wantMetrics) > 0 {
				assert.Equalf(t, test.wantNumOfCharts, len(*nginx.Charts()), "number of charts")
				ensureCollectedHasAllChartsDimsVarsIDs(t, nginx, mx)
			}
		})
	}
}

func caseAPI8AllRequestsOK(t *testing.T) (*NginxPlus, func()) {
	t.Helper()
	srv := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			switch r.URL.Path {
			case urlPathAPIVersions:
				_, _ = w.Write(dataAPI8APIVersions)
			case fmt.Sprintf(urlPathAPIEndpointsRoot, 8):
				_, _ = w.Write(dataAPI8EndpointsRoot)
			case fmt.Sprintf(urlPathAPIEndpointsHTTP, 8):
				_, _ = w.Write(dataAPI8EndpointsHTTP)
			case fmt.Sprintf(urlPathAPIEndpointsStream, 8):
				_, _ = w.Write(dataAPI8EndpointsStream)
			case fmt.Sprintf(urlPathAPIConnections, 8):
				_, _ = w.Write(dataAPI8Connections)
			case fmt.Sprintf(urlPathAPISSL, 8):
				_, _ = w.Write(dataAPI8SSL)
			case fmt.Sprintf(urlPathAPIHTTPRequests, 8):
				_, _ = w.Write(dataAPI8HTTPRequests)
			case fmt.Sprintf(urlPathAPIHTTPServerZones, 8):
				_, _ = w.Write(dataAPI8HTTPServerZones)
			case fmt.Sprintf(urlPathAPIHTTPLocationZones, 8):
				_, _ = w.Write(dataAPI8HTTPLocationZones)
			case fmt.Sprintf(urlPathAPIHTTPUpstreams, 8):
				_, _ = w.Write(dataAPI8HTTPUpstreams)
			case fmt.Sprintf(urlPathAPIHTTPCaches, 8):
				_, _ = w.Write(dataAPI8HTTPCaches)
			case fmt.Sprintf(urlPathAPIStreamServerZones, 8):
				_, _ = w.Write(dataAPI8StreamServerZones)
			case fmt.Sprintf(urlPathAPIStreamUpstreams, 8):
				_, _ = w.Write(dataAPI8StreamUpstreams)
			case fmt.Sprintf(urlPathAPIResolvers, 8):
				_, _ = w.Write(dataAPI8Resolvers)
			default:
				w.WriteHeader(http.StatusNotFound)
				_, _ = w.Write(data404)

			}
		}))
	nginx := New()
	nginx.URL = srv.URL
	require.NoError(t, nginx.Init())

	return nginx, srv.Close
}

func caseAPI8AllRequestsExceptStreamOK(t *testing.T) (*NginxPlus, func()) {
	t.Helper()
	srv := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			switch r.URL.Path {
			case urlPathAPIVersions:
				_, _ = w.Write(dataAPI8APIVersions)
			case fmt.Sprintf(urlPathAPIEndpointsRoot, 8):
				_, _ = w.Write(dataAPI8EndpointsRoot)
			case fmt.Sprintf(urlPathAPIEndpointsHTTP, 8):
				_, _ = w.Write(dataAPI8EndpointsHTTP)
			case fmt.Sprintf(urlPathAPIEndpointsStream, 8):
				_, _ = w.Write(dataAPI8EndpointsStream)
			case fmt.Sprintf(urlPathAPIConnections, 8):
				_, _ = w.Write(dataAPI8Connections)
			case fmt.Sprintf(urlPathAPISSL, 8):
				_, _ = w.Write(dataAPI8SSL)
			case fmt.Sprintf(urlPathAPIHTTPRequests, 8):
				_, _ = w.Write(dataAPI8HTTPRequests)
			case fmt.Sprintf(urlPathAPIHTTPServerZones, 8):
				_, _ = w.Write(dataAPI8HTTPServerZones)
			case fmt.Sprintf(urlPathAPIHTTPLocationZones, 8):
				_, _ = w.Write(dataAPI8HTTPLocationZones)
			case fmt.Sprintf(urlPathAPIHTTPUpstreams, 8):
				_, _ = w.Write(dataAPI8HTTPUpstreams)
			case fmt.Sprintf(urlPathAPIHTTPCaches, 8):
				_, _ = w.Write(dataAPI8HTTPCaches)
			case fmt.Sprintf(urlPathAPIResolvers, 8):
				_, _ = w.Write(dataAPI8Resolvers)
			default:
				w.WriteHeader(http.StatusNotFound)
				_, _ = w.Write(data404)

			}
		}))
	nginx := New()
	nginx.URL = srv.URL
	require.NoError(t, nginx.Init())

	return nginx, srv.Close
}

func caseInvalidDataResponse(t *testing.T) (*NginxPlus, func()) {
	t.Helper()
	srv := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			_, _ = w.Write([]byte("hello and\n goodbye"))
		}))
	nginx := New()
	nginx.URL = srv.URL
	require.NoError(t, nginx.Init())

	return nginx, srv.Close
}

func caseConnectionRefused(t *testing.T) (*NginxPlus, func()) {
	t.Helper()
	nginx := New()
	nginx.URL = "http://127.0.0.1:65001"
	require.NoError(t, nginx.Init())

	return nginx, func() {}
}

func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, n *NginxPlus, mx map[string]int64) {
	for _, chart := range *n.Charts() {
		if chart.ID == uptimeChart.ID {
			continue
		}
		for _, dim := range chart.Dims {
			_, ok := mx[dim.ID]
			assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
		}
		for _, v := range chart.Vars {
			_, ok := mx[v.ID]
			assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
		}
	}
}