github.com/netdata/go.d.plugin@v0.58.1/modules/apache/apache_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package apache 4 5 import ( 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "testing" 10 11 "github.com/netdata/go.d.plugin/pkg/web" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 var ( 18 dataSimpleStatusMPMEvent, _ = os.ReadFile("testdata/simple-status-mpm-event.txt") 19 dataExtendedStatusMPMEvent, _ = os.ReadFile("testdata/extended-status-mpm-event.txt") 20 dataExtendedStatusMPMPrefork, _ = os.ReadFile("testdata/extended-status-mpm-prefork.txt") 21 dataLighttpdStatus, _ = os.ReadFile("testdata/lighttpd-status.txt") 22 ) 23 24 func Test_testDataIsValid(t *testing.T) { 25 for name, data := range map[string][]byte{ 26 "dataSimpleStatusMPMEvent": dataSimpleStatusMPMEvent, 27 "dataExtendedStatusMPMEvent": dataExtendedStatusMPMEvent, 28 "dataExtendedStatusMPMPrefork": dataExtendedStatusMPMPrefork, 29 "dataLighttpdStatus": dataLighttpdStatus, 30 } { 31 require.NotNilf(t, data, name) 32 33 } 34 } 35 36 func TestApache_Init(t *testing.T) { 37 tests := map[string]struct { 38 wantFail bool 39 config Config 40 }{ 41 "success with default": { 42 wantFail: false, 43 config: New().Config, 44 }, 45 "fail when URL not set": { 46 wantFail: true, 47 config: Config{ 48 HTTP: web.HTTP{ 49 Request: web.Request{URL: ""}, 50 }, 51 }, 52 }, 53 "fail when URL has no wantMetrics suffix": { 54 wantFail: true, 55 config: Config{ 56 HTTP: web.HTTP{ 57 Request: web.Request{URL: "http://127.0.0.1:38001"}, 58 }, 59 }, 60 }, 61 } 62 63 for name, test := range tests { 64 t.Run(name, func(t *testing.T) { 65 apache := New() 66 apache.Config = test.config 67 68 if test.wantFail { 69 assert.False(t, apache.Init()) 70 } else { 71 assert.True(t, apache.Init()) 72 } 73 }) 74 } 75 } 76 77 func TestApache_Check(t *testing.T) { 78 tests := map[string]struct { 79 wantFail bool 80 prepare func(t *testing.T) (apache *Apache, cleanup func()) 81 }{ 82 "success on simple status MPM Event": { 83 wantFail: false, 84 prepare: caseMPMEventSimpleStatus, 85 }, 86 "success on extended status MPM Event": { 87 wantFail: false, 88 prepare: caseMPMEventExtendedStatus, 89 }, 90 "success on extended status MPM Prefork": { 91 wantFail: false, 92 prepare: caseMPMPreforkExtendedStatus, 93 }, 94 "fail on Lighttpd response": { 95 wantFail: true, 96 prepare: caseLighttpdResponse, 97 }, 98 "fail on invalid data response": { 99 wantFail: true, 100 prepare: caseInvalidDataResponse, 101 }, 102 "fail on connection refused": { 103 wantFail: true, 104 prepare: caseConnectionRefused, 105 }, 106 "fail on 404 response": { 107 wantFail: true, 108 prepare: case404, 109 }, 110 } 111 112 for name, test := range tests { 113 t.Run(name, func(t *testing.T) { 114 apache, cleanup := test.prepare(t) 115 defer cleanup() 116 117 if test.wantFail { 118 assert.False(t, apache.Check()) 119 } else { 120 assert.True(t, apache.Check()) 121 } 122 }) 123 } 124 } 125 126 func TestApache_Charts(t *testing.T) { 127 assert.NotNil(t, New().Charts()) 128 } 129 130 func TestApache_Collect(t *testing.T) { 131 tests := map[string]struct { 132 prepare func(t *testing.T) (apache *Apache, cleanup func()) 133 wantNumOfCharts int 134 wantMetrics map[string]int64 135 }{ 136 "success on simple status MPM Event": { 137 prepare: caseMPMEventSimpleStatus, 138 wantNumOfCharts: len(baseCharts), 139 wantMetrics: map[string]int64{ 140 "busy_workers": 1, 141 "conns_async_closing": 0, 142 "conns_async_keep_alive": 0, 143 "conns_async_writing": 0, 144 "conns_total": 0, 145 "idle_workers": 74, 146 "scoreboard_closing": 0, 147 "scoreboard_dns_lookup": 0, 148 "scoreboard_finishing": 0, 149 "scoreboard_idle_cleanup": 0, 150 "scoreboard_keepalive": 0, 151 "scoreboard_logging": 0, 152 "scoreboard_open": 325, 153 "scoreboard_reading": 0, 154 "scoreboard_sending": 1, 155 "scoreboard_starting": 0, 156 "scoreboard_waiting": 74, 157 }, 158 }, 159 "success on extended status MPM Event": { 160 prepare: caseMPMEventExtendedStatus, 161 wantNumOfCharts: len(baseCharts) + len(extendedCharts), 162 wantMetrics: map[string]int64{ 163 "busy_workers": 1, 164 "bytes_per_req": 136533000, 165 "bytes_per_sec": 4800000, 166 "conns_async_closing": 0, 167 "conns_async_keep_alive": 0, 168 "conns_async_writing": 0, 169 "conns_total": 0, 170 "idle_workers": 99, 171 "req_per_sec": 3515, 172 "scoreboard_closing": 0, 173 "scoreboard_dns_lookup": 0, 174 "scoreboard_finishing": 0, 175 "scoreboard_idle_cleanup": 0, 176 "scoreboard_keepalive": 0, 177 "scoreboard_logging": 0, 178 "scoreboard_open": 300, 179 "scoreboard_reading": 0, 180 "scoreboard_sending": 1, 181 "scoreboard_starting": 0, 182 "scoreboard_waiting": 99, 183 "total_accesses": 9, 184 "total_kBytes": 12, 185 "uptime": 256, 186 }, 187 }, 188 "success on extended status MPM Prefork": { 189 prepare: caseMPMPreforkExtendedStatus, 190 wantNumOfCharts: len(baseCharts) + len(extendedCharts) - 2, 191 wantMetrics: map[string]int64{ 192 "busy_workers": 70, 193 "bytes_per_req": 3617880000, 194 "bytes_per_sec": 614250000000, 195 "idle_workers": 1037, 196 "req_per_sec": 16978100, 197 "scoreboard_closing": 0, 198 "scoreboard_dns_lookup": 0, 199 "scoreboard_finishing": 0, 200 "scoreboard_idle_cleanup": 0, 201 "scoreboard_keepalive": 0, 202 "scoreboard_logging": 0, 203 "scoreboard_open": 3, 204 "scoreboard_reading": 0, 205 "scoreboard_sending": 0, 206 "scoreboard_starting": 0, 207 "scoreboard_waiting": 3, 208 "total_accesses": 120358784, 209 "total_kBytes": 4252382776, 210 "uptime": 708904, 211 }, 212 }, 213 "fail on Lighttpd response": { 214 prepare: caseLighttpdResponse, 215 wantNumOfCharts: 0, 216 wantMetrics: nil, 217 }, 218 "fail on invalid data response": { 219 prepare: caseInvalidDataResponse, 220 wantNumOfCharts: 0, 221 wantMetrics: nil, 222 }, 223 "fail on connection refused": { 224 prepare: caseConnectionRefused, 225 wantNumOfCharts: 0, 226 wantMetrics: nil, 227 }, 228 "fail on 404 response": { 229 prepare: case404, 230 wantNumOfCharts: 0, 231 wantMetrics: nil, 232 }, 233 } 234 235 for name, test := range tests { 236 t.Run(name, func(t *testing.T) { 237 apache, cleanup := test.prepare(t) 238 defer cleanup() 239 240 _ = apache.Check() 241 242 collected := apache.Collect() 243 244 require.Equal(t, test.wantMetrics, collected) 245 assert.Equal(t, test.wantNumOfCharts, len(*apache.Charts())) 246 }) 247 } 248 } 249 250 func caseMPMEventSimpleStatus(t *testing.T) (*Apache, func()) { 251 t.Helper() 252 srv := httptest.NewServer(http.HandlerFunc( 253 func(w http.ResponseWriter, r *http.Request) { 254 _, _ = w.Write(dataSimpleStatusMPMEvent) 255 })) 256 apache := New() 257 apache.URL = srv.URL + "/server-status?auto" 258 require.True(t, apache.Init()) 259 260 return apache, srv.Close 261 } 262 263 func caseMPMEventExtendedStatus(t *testing.T) (*Apache, func()) { 264 t.Helper() 265 srv := httptest.NewServer(http.HandlerFunc( 266 func(w http.ResponseWriter, r *http.Request) { 267 _, _ = w.Write(dataExtendedStatusMPMEvent) 268 })) 269 apache := New() 270 apache.URL = srv.URL + "/server-status?auto" 271 require.True(t, apache.Init()) 272 273 return apache, srv.Close 274 } 275 276 func caseMPMPreforkExtendedStatus(t *testing.T) (*Apache, func()) { 277 t.Helper() 278 srv := httptest.NewServer(http.HandlerFunc( 279 func(w http.ResponseWriter, r *http.Request) { 280 _, _ = w.Write(dataExtendedStatusMPMPrefork) 281 })) 282 apache := New() 283 apache.URL = srv.URL + "/server-status?auto" 284 require.True(t, apache.Init()) 285 286 return apache, srv.Close 287 } 288 289 func caseLighttpdResponse(t *testing.T) (*Apache, func()) { 290 t.Helper() 291 srv := httptest.NewServer(http.HandlerFunc( 292 func(w http.ResponseWriter, r *http.Request) { 293 _, _ = w.Write(dataLighttpdStatus) 294 })) 295 apache := New() 296 apache.URL = srv.URL + "/server-status?auto" 297 require.True(t, apache.Init()) 298 299 return apache, srv.Close 300 } 301 302 func caseInvalidDataResponse(t *testing.T) (*Apache, func()) { 303 t.Helper() 304 srv := httptest.NewServer(http.HandlerFunc( 305 func(w http.ResponseWriter, r *http.Request) { 306 _, _ = w.Write([]byte("hello and\n goodbye")) 307 })) 308 apache := New() 309 apache.URL = srv.URL + "/server-status?auto" 310 require.True(t, apache.Init()) 311 312 return apache, srv.Close 313 } 314 315 func caseConnectionRefused(t *testing.T) (*Apache, func()) { 316 t.Helper() 317 apache := New() 318 apache.URL = "http://127.0.0.1:65001/server-status?auto" 319 require.True(t, apache.Init()) 320 321 return apache, func() {} 322 } 323 324 func case404(t *testing.T) (*Apache, func()) { 325 t.Helper() 326 srv := httptest.NewServer(http.HandlerFunc( 327 func(w http.ResponseWriter, r *http.Request) { 328 w.WriteHeader(http.StatusNotFound) 329 })) 330 apache := New() 331 apache.URL = srv.URL + "/server-status?auto" 332 require.True(t, apache.Init()) 333 334 return apache, srv.Close 335 }