github.com/netdata/go.d.plugin@v0.58.1/modules/nginxplus/nginxplus_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package nginxplus
     4  
     5  import (
     6  	"fmt"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"testing"
    11  
    12  	"github.com/netdata/go.d.plugin/pkg/web"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  var (
    19  	dataAPI8APIVersions, _       = os.ReadFile("testdata/api-8/api_versions.json")
    20  	dataAPI8Connections, _       = os.ReadFile("testdata/api-8/connections.json")
    21  	dataAPI8EndpointsHTTP, _     = os.ReadFile("testdata/api-8/endpoints_http.json")
    22  	dataAPI8EndpointsRoot, _     = os.ReadFile("testdata/api-8/endpoints_root.json")
    23  	dataAPI8EndpointsStream, _   = os.ReadFile("testdata/api-8/endpoints_stream.json")
    24  	dataAPI8HTTPCaches, _        = os.ReadFile("testdata/api-8/http_caches.json")
    25  	dataAPI8HTTPLocationZones, _ = os.ReadFile("testdata/api-8/http_location_zones.json")
    26  	dataAPI8HTTPRequests, _      = os.ReadFile("testdata/api-8/http_requests.json")
    27  	dataAPI8HTTPServerZones, _   = os.ReadFile("testdata/api-8/http_server_zones.json")
    28  	dataAPI8HTTPUpstreams, _     = os.ReadFile("testdata/api-8/http_upstreams.json")
    29  	dataAPI8SSL, _               = os.ReadFile("testdata/api-8/ssl.json")
    30  	dataAPI8StreamServerZones, _ = os.ReadFile("testdata/api-8/stream_server_zones.json")
    31  	dataAPI8StreamUpstreams, _   = os.ReadFile("testdata/api-8/stream_upstreams.json")
    32  	dataAPI8Resolvers, _         = os.ReadFile("testdata/api-8/resolvers.json")
    33  	data404, _                   = os.ReadFile("testdata/404.json")
    34  )
    35  
    36  func Test_testDataIsValid(t *testing.T) {
    37  	for name, data := range map[string][]byte{
    38  		"dataAPI8APIVersions":       dataAPI8APIVersions,
    39  		"dataAPI8Connections":       dataAPI8Connections,
    40  		"dataAPI8EndpointsHTTP":     dataAPI8EndpointsHTTP,
    41  		"dataAPI8EndpointsRoot":     dataAPI8EndpointsRoot,
    42  		"dataAPI8EndpointsStream":   dataAPI8EndpointsStream,
    43  		"dataAPI8HTTPCaches":        dataAPI8HTTPCaches,
    44  		"dataAPI8HTTPLocationZones": dataAPI8HTTPLocationZones,
    45  		"dataAPI8HTTPRequests":      dataAPI8HTTPRequests,
    46  		"dataAPI8HTTPServerZones":   dataAPI8HTTPServerZones,
    47  		"dataAPI8HTTPUpstreams":     dataAPI8HTTPUpstreams,
    48  		"dataAPI8SSL":               dataAPI8SSL,
    49  		"dataAPI8StreamServerZones": dataAPI8StreamServerZones,
    50  		"dataAPI8StreamUpstreams":   dataAPI8StreamUpstreams,
    51  		"dataAPI8Resolvers":         dataAPI8Resolvers,
    52  		"data404":                   data404,
    53  	} {
    54  		require.NotNilf(t, data, name)
    55  	}
    56  }
    57  
    58  func TestNginxPlus_Init(t *testing.T) {
    59  	tests := map[string]struct {
    60  		wantFail bool
    61  		config   Config
    62  	}{
    63  		"success with default": {
    64  			wantFail: false,
    65  			config:   New().Config,
    66  		},
    67  		"fail when URL not set": {
    68  			wantFail: true,
    69  			config: Config{
    70  				HTTP: web.HTTP{
    71  					Request: web.Request{URL: ""},
    72  				},
    73  			},
    74  		},
    75  	}
    76  
    77  	for name, test := range tests {
    78  		t.Run(name, func(t *testing.T) {
    79  			nginx := New()
    80  			nginx.Config = test.config
    81  
    82  			if test.wantFail {
    83  				assert.False(t, nginx.Init())
    84  			} else {
    85  				assert.True(t, nginx.Init())
    86  			}
    87  		})
    88  	}
    89  }
    90  
    91  func TestNginxPlus_Check(t *testing.T) {
    92  	tests := map[string]struct {
    93  		wantFail bool
    94  		prepare  func(t *testing.T) (nginx *NginxPlus, cleanup func())
    95  	}{
    96  		"success when all requests OK": {
    97  			wantFail: false,
    98  			prepare:  caseAPI8AllRequestsOK,
    99  		},
   100  		"success when all requests except stream OK": {
   101  			wantFail: false,
   102  			prepare:  caseAPI8AllRequestsExceptStreamOK,
   103  		},
   104  		"fail on invalid data response": {
   105  			wantFail: true,
   106  			prepare:  caseInvalidDataResponse,
   107  		},
   108  		"fail on connection refused": {
   109  			wantFail: true,
   110  			prepare:  caseConnectionRefused,
   111  		},
   112  	}
   113  
   114  	for name, test := range tests {
   115  		t.Run(name, func(t *testing.T) {
   116  			nginx, cleanup := test.prepare(t)
   117  			defer cleanup()
   118  
   119  			if test.wantFail {
   120  				assert.False(t, nginx.Check())
   121  			} else {
   122  				assert.True(t, nginx.Check())
   123  			}
   124  		})
   125  	}
   126  }
   127  
   128  func TestNginxPlus_Collect(t *testing.T) {
   129  	tests := map[string]struct {
   130  		prepare         func(t *testing.T) (nginx *NginxPlus, cleanup func())
   131  		wantNumOfCharts int
   132  		wantMetrics     map[string]int64
   133  	}{
   134  		"success when all requests OK": {
   135  			prepare: caseAPI8AllRequestsOK,
   136  			wantNumOfCharts: len(baseCharts) +
   137  				len(httpCacheChartsTmpl) +
   138  				len(httpServerZoneChartsTmpl) +
   139  				len(httpLocationZoneChartsTmpl)*2 +
   140  				len(httpUpstreamChartsTmpl) +
   141  				len(httpUpstreamServerChartsTmpl)*2 +
   142  				len(streamServerZoneChartsTmpl) +
   143  				len(streamUpstreamChartsTmpl) +
   144  				len(streamUpstreamServerChartsTmpl)*2 +
   145  				len(resolverZoneChartsTmpl)*2,
   146  			wantMetrics: map[string]int64{
   147  				"connections_accepted":                                                                   6079,
   148  				"connections_active":                                                                     1,
   149  				"connections_dropped":                                                                    0,
   150  				"connections_idle":                                                                       8,
   151  				"http_cache_cache_backend_bypassed_bytes":                                                67035,
   152  				"http_cache_cache_backend_bypassed_responses":                                            109,
   153  				"http_cache_cache_backend_served_bytes":                                                  0,
   154  				"http_cache_cache_backend_served_responses":                                              0,
   155  				"http_cache_cache_backend_size":                                                          0,
   156  				"http_cache_cache_backend_state_cold":                                                    0,
   157  				"http_cache_cache_backend_state_warm":                                                    1,
   158  				"http_cache_cache_backend_written_bytes":                                                 0,
   159  				"http_cache_cache_backend_written_responses":                                             0,
   160  				"http_location_zone_server_api_bytes_received":                                           1854427,
   161  				"http_location_zone_server_api_bytes_sent":                                               4668778,
   162  				"http_location_zone_server_api_requests":                                                 9188,
   163  				"http_location_zone_server_api_requests_discarded":                                       0,
   164  				"http_location_zone_server_api_responses":                                                9188,
   165  				"http_location_zone_server_api_responses_1xx":                                            0,
   166  				"http_location_zone_server_api_responses_2xx":                                            9187,
   167  				"http_location_zone_server_api_responses_3xx":                                            0,
   168  				"http_location_zone_server_api_responses_4xx":                                            1,
   169  				"http_location_zone_server_api_responses_5xx":                                            0,
   170  				"http_location_zone_server_dashboard_bytes_received":                                     0,
   171  				"http_location_zone_server_dashboard_bytes_sent":                                         0,
   172  				"http_location_zone_server_dashboard_requests":                                           0,
   173  				"http_location_zone_server_dashboard_requests_discarded":                                 0,
   174  				"http_location_zone_server_dashboard_responses":                                          0,
   175  				"http_location_zone_server_dashboard_responses_1xx":                                      0,
   176  				"http_location_zone_server_dashboard_responses_2xx":                                      0,
   177  				"http_location_zone_server_dashboard_responses_3xx":                                      0,
   178  				"http_location_zone_server_dashboard_responses_4xx":                                      0,
   179  				"http_location_zone_server_dashboard_responses_5xx":                                      0,
   180  				"http_requests_current":                                                                  1,
   181  				"http_requests_total":                                                                    8363,
   182  				"http_server_zone_server_backend_bytes_received":                                         1773834,
   183  				"http_server_zone_server_backend_bytes_sent":                                             4585734,
   184  				"http_server_zone_server_backend_requests":                                               8962,
   185  				"http_server_zone_server_backend_requests_discarded":                                     0,
   186  				"http_server_zone_server_backend_requests_processing":                                    1,
   187  				"http_server_zone_server_backend_responses":                                              8961,
   188  				"http_server_zone_server_backend_responses_1xx":                                          0,
   189  				"http_server_zone_server_backend_responses_2xx":                                          8960,
   190  				"http_server_zone_server_backend_responses_3xx":                                          0,
   191  				"http_server_zone_server_backend_responses_4xx":                                          1,
   192  				"http_server_zone_server_backend_responses_5xx":                                          0,
   193  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_active":                     0,
   194  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_received":             0,
   195  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_sent":                 0,
   196  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_downtime":                   1020,
   197  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_header_time":                0,
   198  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_requests":                   26,
   199  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_response_time":              0,
   200  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses":                  0,
   201  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_1xx":              0,
   202  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_2xx":              0,
   203  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_3xx":              0,
   204  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_4xx":              0,
   205  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_5xx":              0,
   206  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_checking":             0,
   207  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_down":                 0,
   208  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_draining":             0,
   209  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unavail":              1,
   210  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unhealthy":            0,
   211  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_up":                   0,
   212  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_active":                     0,
   213  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_received":             86496,
   214  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_sent":                 9180,
   215  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_downtime":                   0,
   216  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_header_time":                1,
   217  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_requests":                   102,
   218  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_response_time":              1,
   219  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses":                  102,
   220  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_1xx":              0,
   221  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_2xx":              102,
   222  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_3xx":              0,
   223  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_4xx":              0,
   224  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_5xx":              0,
   225  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_checking":             0,
   226  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_down":                 0,
   227  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_draining":             0,
   228  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unavail":              0,
   229  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unhealthy":            0,
   230  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_up":                   1,
   231  				"http_upstream_backend_zone_http_backend_keepalive":                                      0,
   232  				"http_upstream_backend_zone_http_backend_peers":                                          2,
   233  				"http_upstream_backend_zone_http_backend_zombies":                                        0,
   234  				"resolver_zone_resolver-http_requests_addr":                                              0,
   235  				"resolver_zone_resolver-http_requests_name":                                              0,
   236  				"resolver_zone_resolver-http_requests_srv":                                               2939408,
   237  				"resolver_zone_resolver-http_responses_formerr":                                          0,
   238  				"resolver_zone_resolver-http_responses_noerror":                                          0,
   239  				"resolver_zone_resolver-http_responses_notimp":                                           0,
   240  				"resolver_zone_resolver-http_responses_nxdomain":                                         2939404,
   241  				"resolver_zone_resolver-http_responses_refused":                                          0,
   242  				"resolver_zone_resolver-http_responses_servfail":                                         0,
   243  				"resolver_zone_resolver-http_responses_timedout":                                         4,
   244  				"resolver_zone_resolver-http_responses_unknown":                                          0,
   245  				"resolver_zone_resolver-stream_requests_addr":                                            0,
   246  				"resolver_zone_resolver-stream_requests_name":                                            638797,
   247  				"resolver_zone_resolver-stream_requests_srv":                                             0,
   248  				"resolver_zone_resolver-stream_responses_formerr":                                        0,
   249  				"resolver_zone_resolver-stream_responses_noerror":                                        433136,
   250  				"resolver_zone_resolver-stream_responses_notimp":                                         0,
   251  				"resolver_zone_resolver-stream_responses_nxdomain":                                       40022,
   252  				"resolver_zone_resolver-stream_responses_refused":                                        165639,
   253  				"resolver_zone_resolver-stream_responses_servfail":                                       0,
   254  				"resolver_zone_resolver-stream_responses_timedout":                                       0,
   255  				"resolver_zone_resolver-stream_responses_unknown":                                        0,
   256  				"ssl_handshake_timeout":                                                                  4,
   257  				"ssl_handshakes":                                                                         15804607,
   258  				"ssl_handshakes_failed":                                                                  37862,
   259  				"ssl_no_common_cipher":                                                                   24,
   260  				"ssl_no_common_protocol":                                                                 16648,
   261  				"ssl_peer_rejected_cert":                                                                 0,
   262  				"ssl_session_reuses":                                                                     13096060,
   263  				"ssl_verify_failures_expired_cert":                                                       0,
   264  				"ssl_verify_failures_hostname_mismatch":                                                  0,
   265  				"ssl_verify_failures_other":                                                              0,
   266  				"ssl_verify_failures_no_cert":                                                            0,
   267  				"ssl_verify_failures_revoked_cert":                                                       0,
   268  				"stream_server_zone_tcp_server_bytes_received":                                           0,
   269  				"stream_server_zone_tcp_server_bytes_sent":                                               0,
   270  				"stream_server_zone_tcp_server_connections":                                              0,
   271  				"stream_server_zone_tcp_server_connections_discarded":                                    0,
   272  				"stream_server_zone_tcp_server_connections_processing":                                   0,
   273  				"stream_server_zone_tcp_server_sessions":                                                 0,
   274  				"stream_server_zone_tcp_server_sessions_2xx":                                             0,
   275  				"stream_server_zone_tcp_server_sessions_4xx":                                             0,
   276  				"stream_server_zone_tcp_server_sessions_5xx":                                             0,
   277  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_active":          0,
   278  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_bytes_received":  0,
   279  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_bytes_sent":      0,
   280  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_connections":     0,
   281  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_downtime":        0,
   282  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_checking":  0,
   283  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_down":      0,
   284  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_unavail":   0,
   285  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_unhealthy": 0,
   286  				"stream_upstream_stream_backend_server_127.0.0.1:12346_zone_tcp_servers_state_up":        1,
   287  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_active":          0,
   288  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_bytes_received":  0,
   289  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_bytes_sent":      0,
   290  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_connections":     0,
   291  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_downtime":        0,
   292  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_checking":  0,
   293  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_down":      0,
   294  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_unavail":   0,
   295  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_unhealthy": 0,
   296  				"stream_upstream_stream_backend_server_127.0.0.1:12347_zone_tcp_servers_state_up":        1,
   297  				"stream_upstream_stream_backend_zone_tcp_servers_peers":                                  2,
   298  				"stream_upstream_stream_backend_zone_tcp_servers_zombies":                                0,
   299  			},
   300  		},
   301  		"success when all requests except stream OK": {
   302  			prepare: caseAPI8AllRequestsExceptStreamOK,
   303  			wantNumOfCharts: len(baseCharts) +
   304  				len(httpCacheChartsTmpl) +
   305  				len(httpServerZoneChartsTmpl) +
   306  				len(httpLocationZoneChartsTmpl)*2 +
   307  				len(httpUpstreamChartsTmpl) +
   308  				len(httpUpstreamServerChartsTmpl)*2 +
   309  				len(resolverZoneChartsTmpl)*2,
   310  			wantMetrics: map[string]int64{
   311  				"connections_accepted":                                                        6079,
   312  				"connections_active":                                                          1,
   313  				"connections_dropped":                                                         0,
   314  				"connections_idle":                                                            8,
   315  				"http_cache_cache_backend_bypassed_bytes":                                     67035,
   316  				"http_cache_cache_backend_bypassed_responses":                                 109,
   317  				"http_cache_cache_backend_served_bytes":                                       0,
   318  				"http_cache_cache_backend_served_responses":                                   0,
   319  				"http_cache_cache_backend_size":                                               0,
   320  				"http_cache_cache_backend_state_cold":                                         0,
   321  				"http_cache_cache_backend_state_warm":                                         1,
   322  				"http_cache_cache_backend_written_bytes":                                      0,
   323  				"http_cache_cache_backend_written_responses":                                  0,
   324  				"http_location_zone_server_api_bytes_received":                                1854427,
   325  				"http_location_zone_server_api_bytes_sent":                                    4668778,
   326  				"http_location_zone_server_api_requests":                                      9188,
   327  				"http_location_zone_server_api_requests_discarded":                            0,
   328  				"http_location_zone_server_api_responses":                                     9188,
   329  				"http_location_zone_server_api_responses_1xx":                                 0,
   330  				"http_location_zone_server_api_responses_2xx":                                 9187,
   331  				"http_location_zone_server_api_responses_3xx":                                 0,
   332  				"http_location_zone_server_api_responses_4xx":                                 1,
   333  				"http_location_zone_server_api_responses_5xx":                                 0,
   334  				"http_location_zone_server_dashboard_bytes_received":                          0,
   335  				"http_location_zone_server_dashboard_bytes_sent":                              0,
   336  				"http_location_zone_server_dashboard_requests":                                0,
   337  				"http_location_zone_server_dashboard_requests_discarded":                      0,
   338  				"http_location_zone_server_dashboard_responses":                               0,
   339  				"http_location_zone_server_dashboard_responses_1xx":                           0,
   340  				"http_location_zone_server_dashboard_responses_2xx":                           0,
   341  				"http_location_zone_server_dashboard_responses_3xx":                           0,
   342  				"http_location_zone_server_dashboard_responses_4xx":                           0,
   343  				"http_location_zone_server_dashboard_responses_5xx":                           0,
   344  				"http_requests_current":                                                       1,
   345  				"http_requests_total":                                                         8363,
   346  				"http_server_zone_server_backend_bytes_received":                              1773834,
   347  				"http_server_zone_server_backend_bytes_sent":                                  4585734,
   348  				"http_server_zone_server_backend_requests":                                    8962,
   349  				"http_server_zone_server_backend_requests_discarded":                          0,
   350  				"http_server_zone_server_backend_requests_processing":                         1,
   351  				"http_server_zone_server_backend_responses":                                   8961,
   352  				"http_server_zone_server_backend_responses_1xx":                               0,
   353  				"http_server_zone_server_backend_responses_2xx":                               8960,
   354  				"http_server_zone_server_backend_responses_3xx":                               0,
   355  				"http_server_zone_server_backend_responses_4xx":                               1,
   356  				"http_server_zone_server_backend_responses_5xx":                               0,
   357  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_active":          0,
   358  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_received":  0,
   359  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_bytes_sent":      0,
   360  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_downtime":        1020,
   361  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_header_time":     0,
   362  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_requests":        26,
   363  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_response_time":   0,
   364  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses":       0,
   365  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_1xx":   0,
   366  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_2xx":   0,
   367  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_3xx":   0,
   368  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_4xx":   0,
   369  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_responses_5xx":   0,
   370  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_checking":  0,
   371  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_down":      0,
   372  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_draining":  0,
   373  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unavail":   1,
   374  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_unhealthy": 0,
   375  				"http_upstream_backend_server_127.0.0.1:81_zone_http_backend_state_up":        0,
   376  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_active":          0,
   377  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_received":  86496,
   378  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_bytes_sent":      9180,
   379  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_downtime":        0,
   380  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_header_time":     1,
   381  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_requests":        102,
   382  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_response_time":   1,
   383  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses":       102,
   384  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_1xx":   0,
   385  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_2xx":   102,
   386  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_3xx":   0,
   387  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_4xx":   0,
   388  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_responses_5xx":   0,
   389  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_checking":  0,
   390  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_down":      0,
   391  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_draining":  0,
   392  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unavail":   0,
   393  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_unhealthy": 0,
   394  				"http_upstream_backend_server_127.0.0.1:82_zone_http_backend_state_up":        1,
   395  				"http_upstream_backend_zone_http_backend_keepalive":                           0,
   396  				"http_upstream_backend_zone_http_backend_peers":                               2,
   397  				"http_upstream_backend_zone_http_backend_zombies":                             0,
   398  				"resolver_zone_resolver-http_requests_addr":                                   0,
   399  				"resolver_zone_resolver-http_requests_name":                                   0,
   400  				"resolver_zone_resolver-http_requests_srv":                                    2939408,
   401  				"resolver_zone_resolver-http_responses_formerr":                               0,
   402  				"resolver_zone_resolver-http_responses_noerror":                               0,
   403  				"resolver_zone_resolver-http_responses_notimp":                                0,
   404  				"resolver_zone_resolver-http_responses_nxdomain":                              2939404,
   405  				"resolver_zone_resolver-http_responses_refused":                               0,
   406  				"resolver_zone_resolver-http_responses_servfail":                              0,
   407  				"resolver_zone_resolver-http_responses_timedout":                              4,
   408  				"resolver_zone_resolver-http_responses_unknown":                               0,
   409  				"resolver_zone_resolver-stream_requests_addr":                                 0,
   410  				"resolver_zone_resolver-stream_requests_name":                                 638797,
   411  				"resolver_zone_resolver-stream_requests_srv":                                  0,
   412  				"resolver_zone_resolver-stream_responses_formerr":                             0,
   413  				"resolver_zone_resolver-stream_responses_noerror":                             433136,
   414  				"resolver_zone_resolver-stream_responses_notimp":                              0,
   415  				"resolver_zone_resolver-stream_responses_nxdomain":                            40022,
   416  				"resolver_zone_resolver-stream_responses_refused":                             165639,
   417  				"resolver_zone_resolver-stream_responses_servfail":                            0,
   418  				"resolver_zone_resolver-stream_responses_timedout":                            0,
   419  				"resolver_zone_resolver-stream_responses_unknown":                             0,
   420  				"ssl_handshake_timeout":                                                       4,
   421  				"ssl_handshakes":                                                              15804607,
   422  				"ssl_handshakes_failed":                                                       37862,
   423  				"ssl_no_common_cipher":                                                        24,
   424  				"ssl_no_common_protocol":                                                      16648,
   425  				"ssl_peer_rejected_cert":                                                      0,
   426  				"ssl_session_reuses":                                                          13096060,
   427  				"ssl_verify_failures_expired_cert":                                            0,
   428  				"ssl_verify_failures_hostname_mismatch":                                       0,
   429  				"ssl_verify_failures_other":                                                   0,
   430  				"ssl_verify_failures_no_cert":                                                 0,
   431  				"ssl_verify_failures_revoked_cert":                                            0,
   432  			},
   433  		},
   434  		"fail on invalid data response": {
   435  			prepare:         caseInvalidDataResponse,
   436  			wantNumOfCharts: 0,
   437  			wantMetrics:     nil,
   438  		},
   439  		"fail on connection refused": {
   440  			prepare:         caseConnectionRefused,
   441  			wantNumOfCharts: 0,
   442  			wantMetrics:     nil,
   443  		},
   444  	}
   445  
   446  	for name, test := range tests {
   447  		t.Run(name, func(t *testing.T) {
   448  			nginx, cleanup := test.prepare(t)
   449  			defer cleanup()
   450  
   451  			mx := nginx.Collect()
   452  
   453  			require.Equal(t, test.wantMetrics, mx)
   454  			if len(test.wantMetrics) > 0 {
   455  				assert.Equalf(t, test.wantNumOfCharts, len(*nginx.Charts()), "number of charts")
   456  				ensureCollectedHasAllChartsDimsVarsIDs(t, nginx, mx)
   457  			}
   458  		})
   459  	}
   460  }
   461  
   462  func caseAPI8AllRequestsOK(t *testing.T) (*NginxPlus, func()) {
   463  	t.Helper()
   464  	srv := httptest.NewServer(http.HandlerFunc(
   465  		func(w http.ResponseWriter, r *http.Request) {
   466  			switch r.URL.Path {
   467  			case urlPathAPIVersions:
   468  				_, _ = w.Write(dataAPI8APIVersions)
   469  			case fmt.Sprintf(urlPathAPIEndpointsRoot, 8):
   470  				_, _ = w.Write(dataAPI8EndpointsRoot)
   471  			case fmt.Sprintf(urlPathAPIEndpointsHTTP, 8):
   472  				_, _ = w.Write(dataAPI8EndpointsHTTP)
   473  			case fmt.Sprintf(urlPathAPIEndpointsStream, 8):
   474  				_, _ = w.Write(dataAPI8EndpointsStream)
   475  			case fmt.Sprintf(urlPathAPIConnections, 8):
   476  				_, _ = w.Write(dataAPI8Connections)
   477  			case fmt.Sprintf(urlPathAPISSL, 8):
   478  				_, _ = w.Write(dataAPI8SSL)
   479  			case fmt.Sprintf(urlPathAPIHTTPRequests, 8):
   480  				_, _ = w.Write(dataAPI8HTTPRequests)
   481  			case fmt.Sprintf(urlPathAPIHTTPServerZones, 8):
   482  				_, _ = w.Write(dataAPI8HTTPServerZones)
   483  			case fmt.Sprintf(urlPathAPIHTTPLocationZones, 8):
   484  				_, _ = w.Write(dataAPI8HTTPLocationZones)
   485  			case fmt.Sprintf(urlPathAPIHTTPUpstreams, 8):
   486  				_, _ = w.Write(dataAPI8HTTPUpstreams)
   487  			case fmt.Sprintf(urlPathAPIHTTPCaches, 8):
   488  				_, _ = w.Write(dataAPI8HTTPCaches)
   489  			case fmt.Sprintf(urlPathAPIStreamServerZones, 8):
   490  				_, _ = w.Write(dataAPI8StreamServerZones)
   491  			case fmt.Sprintf(urlPathAPIStreamUpstreams, 8):
   492  				_, _ = w.Write(dataAPI8StreamUpstreams)
   493  			case fmt.Sprintf(urlPathAPIResolvers, 8):
   494  				_, _ = w.Write(dataAPI8Resolvers)
   495  			default:
   496  				w.WriteHeader(http.StatusNotFound)
   497  				_, _ = w.Write(data404)
   498  
   499  			}
   500  		}))
   501  	nginx := New()
   502  	nginx.URL = srv.URL
   503  	require.True(t, nginx.Init())
   504  
   505  	return nginx, srv.Close
   506  }
   507  
   508  func caseAPI8AllRequestsExceptStreamOK(t *testing.T) (*NginxPlus, func()) {
   509  	t.Helper()
   510  	srv := httptest.NewServer(http.HandlerFunc(
   511  		func(w http.ResponseWriter, r *http.Request) {
   512  			switch r.URL.Path {
   513  			case urlPathAPIVersions:
   514  				_, _ = w.Write(dataAPI8APIVersions)
   515  			case fmt.Sprintf(urlPathAPIEndpointsRoot, 8):
   516  				_, _ = w.Write(dataAPI8EndpointsRoot)
   517  			case fmt.Sprintf(urlPathAPIEndpointsHTTP, 8):
   518  				_, _ = w.Write(dataAPI8EndpointsHTTP)
   519  			case fmt.Sprintf(urlPathAPIEndpointsStream, 8):
   520  				_, _ = w.Write(dataAPI8EndpointsStream)
   521  			case fmt.Sprintf(urlPathAPIConnections, 8):
   522  				_, _ = w.Write(dataAPI8Connections)
   523  			case fmt.Sprintf(urlPathAPISSL, 8):
   524  				_, _ = w.Write(dataAPI8SSL)
   525  			case fmt.Sprintf(urlPathAPIHTTPRequests, 8):
   526  				_, _ = w.Write(dataAPI8HTTPRequests)
   527  			case fmt.Sprintf(urlPathAPIHTTPServerZones, 8):
   528  				_, _ = w.Write(dataAPI8HTTPServerZones)
   529  			case fmt.Sprintf(urlPathAPIHTTPLocationZones, 8):
   530  				_, _ = w.Write(dataAPI8HTTPLocationZones)
   531  			case fmt.Sprintf(urlPathAPIHTTPUpstreams, 8):
   532  				_, _ = w.Write(dataAPI8HTTPUpstreams)
   533  			case fmt.Sprintf(urlPathAPIHTTPCaches, 8):
   534  				_, _ = w.Write(dataAPI8HTTPCaches)
   535  			case fmt.Sprintf(urlPathAPIResolvers, 8):
   536  				_, _ = w.Write(dataAPI8Resolvers)
   537  			default:
   538  				w.WriteHeader(http.StatusNotFound)
   539  				_, _ = w.Write(data404)
   540  
   541  			}
   542  		}))
   543  	nginx := New()
   544  	nginx.URL = srv.URL
   545  	require.True(t, nginx.Init())
   546  
   547  	return nginx, srv.Close
   548  }
   549  
   550  func caseInvalidDataResponse(t *testing.T) (*NginxPlus, func()) {
   551  	t.Helper()
   552  	srv := httptest.NewServer(http.HandlerFunc(
   553  		func(w http.ResponseWriter, r *http.Request) {
   554  			_, _ = w.Write([]byte("hello and\n goodbye"))
   555  		}))
   556  	nginx := New()
   557  	nginx.URL = srv.URL
   558  	require.True(t, nginx.Init())
   559  
   560  	return nginx, srv.Close
   561  }
   562  
   563  func caseConnectionRefused(t *testing.T) (*NginxPlus, func()) {
   564  	t.Helper()
   565  	nginx := New()
   566  	nginx.URL = "http://127.0.0.1:65001"
   567  	require.True(t, nginx.Init())
   568  
   569  	return nginx, func() {}
   570  }
   571  
   572  func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, n *NginxPlus, mx map[string]int64) {
   573  	for _, chart := range *n.Charts() {
   574  		if chart.ID == uptimeChart.ID {
   575  			continue
   576  		}
   577  		for _, dim := range chart.Dims {
   578  			_, ok := mx[dim.ID]
   579  			assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
   580  		}
   581  		for _, v := range chart.Vars {
   582  			_, ok := mx[v.ID]
   583  			assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
   584  		}
   585  	}
   586  }