github.com/netdata/go.d.plugin@v0.58.1/modules/nginxvts/nginxvts_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package nginxvts 4 5 import ( 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "testing" 10 11 "github.com/netdata/go.d.plugin/agent/module" 12 "github.com/netdata/go.d.plugin/pkg/tlscfg" 13 "github.com/netdata/go.d.plugin/pkg/web" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 var ( 20 v0118Response, _ = os.ReadFile("testdata/vts-v0.1.18.json") 21 ) 22 23 func Test_testDataIsCorrectlyReadAndValid(t *testing.T) { 24 for name, data := range map[string][]byte{ 25 "v0118Response": v0118Response, 26 } { 27 require.NotNilf(t, data, name) 28 } 29 } 30 31 func TestNew(t *testing.T) { 32 assert.Implements(t, (*module.Module)(nil), New()) 33 } 34 35 func TestNginxVTS_Init(t *testing.T) { 36 tests := map[string]struct { 37 config Config 38 wantNumOfCharts int 39 wantFail bool 40 }{ 41 "default": { 42 wantNumOfCharts: numOfCharts( 43 mainCharts, 44 sharedZonesCharts, 45 serverZonesCharts, 46 ), 47 config: New().Config, 48 }, 49 "URL not set": { 50 wantFail: true, 51 config: Config{ 52 HTTP: web.HTTP{ 53 Request: web.Request{URL: ""}, 54 }}, 55 }, 56 "invalid TLSCA": { 57 wantFail: true, 58 config: Config{ 59 HTTP: web.HTTP{ 60 Client: web.Client{ 61 TLSConfig: tlscfg.TLSConfig{TLSCA: "testdata/tls"}, 62 }, 63 }}, 64 }, 65 } 66 67 for name, test := range tests { 68 t.Run(name, func(t *testing.T) { 69 es := New() 70 es.Config = test.config 71 72 if test.wantFail { 73 assert.False(t, es.Init()) 74 } else { 75 assert.True(t, es.Init()) 76 assert.Equal(t, test.wantNumOfCharts, len(*es.Charts())) 77 } 78 }) 79 } 80 } 81 82 func TestNginxVTS_Check(t *testing.T) { 83 tests := map[string]struct { 84 prepare func(*testing.T) (vts *NginxVTS, cleanup func()) 85 wantFail bool 86 }{ 87 "valid data": {prepare: prepareNginxVTSValidData}, 88 "invalid data": {prepare: prepareNginxVTSInvalidData, wantFail: true}, 89 "404": {prepare: prepareNginxVTS404, wantFail: true}, 90 "connection refused": {prepare: prepareNginxVTSConnectionRefused, wantFail: true}, 91 } 92 93 for name, test := range tests { 94 t.Run(name, func(t *testing.T) { 95 vts, cleanup := test.prepare(t) 96 defer cleanup() 97 98 if test.wantFail { 99 assert.False(t, vts.Check()) 100 } else { 101 assert.True(t, vts.Check()) 102 } 103 }) 104 } 105 } 106 107 func TestNginxVTS_Charts(t *testing.T) { 108 assert.Nil(t, New().Charts()) 109 } 110 111 func TestNginxVTS_Cleanup(t *testing.T) { 112 assert.NotPanics(t, New().Cleanup) 113 } 114 115 func TestNginxVTS_Collect(t *testing.T) { 116 tests := map[string]struct { 117 // prepare func() *NginxVTS 118 prepare func(t *testing.T) (vts *NginxVTS, cleanup func()) 119 wantCollected map[string]int64 120 checkCharts bool 121 }{ 122 "right metrics": { 123 prepare: prepareNginxVTSValidData, 124 wantCollected: map[string]int64{ 125 // Nginx running time 126 "uptime": 319, 127 // Nginx connections 128 "connections_active": 2, 129 "connections_reading": 0, 130 "connections_writing": 1, 131 "connections_waiting": 1, 132 "connections_accepted": 12, 133 "connections_handled": 12, 134 "connections_requests": 17, 135 // Nginx shared memory 136 "sharedzones_maxsize": 1048575, 137 "sharedzones_usedsize": 45799, 138 "sharedzones_usednode": 13, 139 // Nginx traffic 140 "total_requestcounter": 2, 141 "total_inbytes": 156, 142 "total_outbytes": 692, 143 // Nginx response code 144 "total_responses_1xx": 1, 145 "total_responses_2xx": 2, 146 "total_responses_3xx": 3, 147 "total_responses_4xx": 4, 148 "total_responses_5xx": 5, 149 // Nginx cache 150 "total_cache_miss": 2, 151 "total_cache_bypass": 4, 152 "total_cache_expired": 6, 153 "total_cache_stale": 8, 154 "total_cache_updating": 10, 155 "total_cache_revalidated": 12, 156 "total_cache_hit": 14, 157 "total_cache_scarce": 16, 158 }, 159 checkCharts: true, 160 }, 161 } 162 163 for name, test := range tests { 164 t.Run(name, func(t *testing.T) { 165 vts, cleanup := test.prepare(t) 166 defer cleanup() 167 168 collected := vts.Collect() 169 170 assert.Equal(t, test.wantCollected, collected) 171 if test.checkCharts { 172 ensureCollectedHasAllChartsDimsVarsIDs(t, vts, collected) 173 } 174 }) 175 } 176 } 177 178 func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, vts *NginxVTS, collected map[string]int64) { 179 for _, chart := range *vts.Charts() { 180 if chart.Obsolete { 181 continue 182 } 183 for _, dim := range chart.Dims { 184 _, ok := collected[dim.ID] 185 assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID) 186 } 187 for _, v := range chart.Vars { 188 _, ok := collected[v.ID] 189 assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID) 190 } 191 } 192 } 193 194 func prepareNginxVTS(t *testing.T, createNginxVTS func() *NginxVTS) (vts *NginxVTS, cleanup func()) { 195 t.Helper() 196 vts = createNginxVTS() 197 srv := prepareNginxVTSEndpoint() 198 vts.URL = srv.URL 199 200 require.True(t, vts.Init()) 201 202 return vts, srv.Close 203 } 204 205 func prepareNginxVTSValidData(t *testing.T) (vts *NginxVTS, cleanup func()) { 206 return prepareNginxVTS(t, New) 207 } 208 209 func prepareNginxVTSInvalidData(t *testing.T) (*NginxVTS, func()) { 210 t.Helper() 211 srv := httptest.NewServer(http.HandlerFunc( 212 func(w http.ResponseWriter, r *http.Request) { 213 _, _ = w.Write([]byte("hello and\n goodbye")) 214 })) 215 vts := New() 216 vts.URL = srv.URL 217 require.True(t, vts.Init()) 218 219 return vts, srv.Close 220 } 221 222 func prepareNginxVTS404(t *testing.T) (*NginxVTS, func()) { 223 t.Helper() 224 srv := httptest.NewServer(http.HandlerFunc( 225 func(w http.ResponseWriter, r *http.Request) { 226 w.WriteHeader(http.StatusNotFound) 227 })) 228 vts := New() 229 vts.URL = srv.URL 230 require.True(t, vts.Init()) 231 232 return vts, srv.Close 233 } 234 235 func prepareNginxVTSConnectionRefused(t *testing.T) (*NginxVTS, func()) { 236 t.Helper() 237 vts := New() 238 vts.URL = "http://127.0.0.1:18080" 239 require.True(t, vts.Init()) 240 241 return vts, func() {} 242 } 243 244 func prepareNginxVTSEndpoint() *httptest.Server { 245 return httptest.NewServer(http.HandlerFunc( 246 func(w http.ResponseWriter, r *http.Request) { 247 switch r.URL.Path { 248 case "/": 249 _, _ = w.Write(v0118Response) 250 default: 251 w.WriteHeader(http.StatusNotFound) 252 } 253 })) 254 } 255 256 func numOfCharts(charts ...module.Charts) (num int) { 257 for _, v := range charts { 258 num += len(v) 259 } 260 return num 261 }