github.com/netdata/go.d.plugin@v0.58.1/modules/powerdns/authoritativens_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package powerdns 4 5 import ( 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "testing" 10 11 "github.com/netdata/go.d.plugin/pkg/tlscfg" 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 v430statistics, _ = os.ReadFile("testdata/v4.3.0/statistics.json") 20 recursorStatistics, _ = os.ReadFile("testdata/recursor/statistics.json") 21 ) 22 23 func Test_testDataIsCorrectlyReadAndValid(t *testing.T) { 24 for name, data := range map[string][]byte{ 25 "v430statistics": v430statistics, 26 "recursorStatistics": recursorStatistics, 27 } { 28 require.NotNilf(t, data, name) 29 } 30 } 31 32 func TestNew(t *testing.T) { 33 assert.IsType(t, (*AuthoritativeNS)(nil), New()) 34 } 35 36 func TestRecursor_Init(t *testing.T) { 37 tests := map[string]struct { 38 config Config 39 wantFail bool 40 }{ 41 "success on default config": { 42 config: New().Config, 43 }, 44 "fails on unset URL": { 45 wantFail: true, 46 config: Config{ 47 HTTP: web.HTTP{ 48 Request: web.Request{URL: ""}, 49 }, 50 }, 51 }, 52 "fails on invalid TLSCA": { 53 wantFail: true, 54 config: Config{ 55 HTTP: web.HTTP{ 56 Request: web.Request{ 57 URL: "http://127.0.0.1:38001", 58 }, 59 Client: web.Client{ 60 TLSConfig: tlscfg.TLSConfig{TLSCA: "testdata/tls"}, 61 }, 62 }, 63 }, 64 }, 65 } 66 67 for name, test := range tests { 68 t.Run(name, func(t *testing.T) { 69 ns := New() 70 ns.Config = test.config 71 72 if test.wantFail { 73 assert.False(t, ns.Init()) 74 } else { 75 assert.True(t, ns.Init()) 76 } 77 }) 78 } 79 } 80 81 func TestRecursor_Check(t *testing.T) { 82 tests := map[string]struct { 83 prepare func() (p *AuthoritativeNS, cleanup func()) 84 wantFail bool 85 }{ 86 "success on valid response v4.3.0": { 87 prepare: preparePowerDNSAuthoritativeNSV430, 88 }, 89 "fails on response from PowerDNS Recursor": { 90 wantFail: true, 91 prepare: preparePowerDNSAuthoritativeNSRecursorData, 92 }, 93 "fails on 404 response": { 94 wantFail: true, 95 prepare: preparePowerDNSAuthoritativeNS404, 96 }, 97 "fails on connection refused": { 98 wantFail: true, 99 prepare: preparePowerDNSAuthoritativeNSConnectionRefused, 100 }, 101 "fails on response with invalid data": { 102 wantFail: true, 103 prepare: preparePowerDNSAuthoritativeNSInvalidData, 104 }, 105 } 106 107 for name, test := range tests { 108 t.Run(name, func(t *testing.T) { 109 recursor, cleanup := test.prepare() 110 defer cleanup() 111 require.True(t, recursor.Init()) 112 113 if test.wantFail { 114 assert.False(t, recursor.Check()) 115 } else { 116 assert.True(t, recursor.Check()) 117 } 118 }) 119 } 120 } 121 122 func TestRecursor_Charts(t *testing.T) { 123 recursor := New() 124 require.True(t, recursor.Init()) 125 assert.NotNil(t, recursor.Charts()) 126 } 127 128 func TestRecursor_Cleanup(t *testing.T) { 129 assert.NotPanics(t, New().Cleanup) 130 } 131 132 func TestRecursor_Collect(t *testing.T) { 133 tests := map[string]struct { 134 prepare func() (p *AuthoritativeNS, cleanup func()) 135 wantCollected map[string]int64 136 }{ 137 "success on valid response v4.3.0": { 138 prepare: preparePowerDNSAuthoritativeNSV430, 139 wantCollected: map[string]int64{ 140 "corrupt-packets": 1, 141 "cpu-iowait": 513, 142 "cpu-steal": 1, 143 "deferred-cache-inserts": 1, 144 "deferred-cache-lookup": 1, 145 "deferred-packetcache-inserts": 1, 146 "deferred-packetcache-lookup": 1, 147 "dnsupdate-answers": 1, 148 "dnsupdate-changes": 1, 149 "dnsupdate-queries": 1, 150 "dnsupdate-refused": 1, 151 "fd-usage": 23, 152 "incoming-notifications": 1, 153 "key-cache-size": 1, 154 "latency": 1, 155 "meta-cache-size": 1, 156 "open-tcp-connections": 1, 157 "overload-drops": 1, 158 "packetcache-hit": 1, 159 "packetcache-miss": 1, 160 "packetcache-size": 1, 161 "qsize-q": 1, 162 "query-cache-hit": 1, 163 "query-cache-miss": 1, 164 "query-cache-size": 1, 165 "rd-queries": 1, 166 "real-memory-usage": 164507648, 167 "recursing-answers": 1, 168 "recursing-questions": 1, 169 "recursion-unanswered": 1, 170 "ring-logmessages-capacity": 10000, 171 "ring-logmessages-size": 10, 172 "ring-noerror-queries-capacity": 10000, 173 "ring-noerror-queries-size": 1, 174 "ring-nxdomain-queries-capacity": 10000, 175 "ring-nxdomain-queries-size": 1, 176 "ring-queries-capacity": 10000, 177 "ring-queries-size": 1, 178 "ring-remotes-capacity": 10000, 179 "ring-remotes-corrupt-capacity": 10000, 180 "ring-remotes-corrupt-size": 1, 181 "ring-remotes-size": 1, 182 "ring-remotes-unauth-capacity": 10000, 183 "ring-remotes-unauth-size": 1, 184 "ring-servfail-queries-capacity": 10000, 185 "ring-servfail-queries-size": 1, 186 "ring-unauth-queries-capacity": 10000, 187 "ring-unauth-queries-size": 1, 188 "security-status": 1, 189 "servfail-packets": 1, 190 "signature-cache-size": 1, 191 "signatures": 1, 192 "sys-msec": 128, 193 "tcp-answers": 1, 194 "tcp-answers-bytes": 1, 195 "tcp-queries": 1, 196 "tcp4-answers": 1, 197 "tcp4-answers-bytes": 1, 198 "tcp4-queries": 1, 199 "tcp6-answers": 1, 200 "tcp6-answers-bytes": 1, 201 "tcp6-queries": 1, 202 "timedout-packets": 1, 203 "udp-answers": 1, 204 "udp-answers-bytes": 1, 205 "udp-do-queries": 1, 206 "udp-in-errors": 1, 207 "udp-noport-errors": 1, 208 "udp-queries": 1, 209 "udp-recvbuf-errors": 1, 210 "udp-sndbuf-errors": 1, 211 "udp4-answers": 1, 212 "udp4-answers-bytes": 1, 213 "udp4-queries": 1, 214 "udp6-answers": 1, 215 "udp6-answers-bytes": 1, 216 "udp6-queries": 1, 217 "uptime": 207, 218 "user-msec": 56, 219 }, 220 }, 221 "fails on response from PowerDNS Recursor": { 222 prepare: preparePowerDNSAuthoritativeNSRecursorData, 223 }, 224 "fails on 404 response": { 225 prepare: preparePowerDNSAuthoritativeNS404, 226 }, 227 "fails on connection refused": { 228 prepare: preparePowerDNSAuthoritativeNSConnectionRefused, 229 }, 230 "fails on response with invalid data": { 231 prepare: preparePowerDNSAuthoritativeNSInvalidData, 232 }, 233 } 234 235 for name, test := range tests { 236 t.Run(name, func(t *testing.T) { 237 ns, cleanup := test.prepare() 238 defer cleanup() 239 require.True(t, ns.Init()) 240 241 collected := ns.Collect() 242 243 assert.Equal(t, test.wantCollected, collected) 244 if len(test.wantCollected) > 0 { 245 ensureCollectedHasAllChartsDimsVarsIDs(t, ns, collected) 246 } 247 }) 248 } 249 } 250 251 func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, ns *AuthoritativeNS, collected map[string]int64) { 252 for _, chart := range *ns.Charts() { 253 if chart.Obsolete { 254 continue 255 } 256 for _, dim := range chart.Dims { 257 _, ok := collected[dim.ID] 258 assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", dim.ID, chart.ID) 259 } 260 for _, v := range chart.Vars { 261 _, ok := collected[v.ID] 262 assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", v.ID, chart.ID) 263 } 264 } 265 } 266 267 func preparePowerDNSAuthoritativeNSV430() (*AuthoritativeNS, func()) { 268 srv := preparePowerDNSAuthoritativeNSEndpoint() 269 ns := New() 270 ns.URL = srv.URL 271 272 return ns, srv.Close 273 } 274 275 func preparePowerDNSAuthoritativeNSRecursorData() (*AuthoritativeNS, func()) { 276 srv := preparePowerDNSRecursorEndpoint() 277 ns := New() 278 ns.URL = srv.URL 279 280 return ns, srv.Close 281 } 282 283 func preparePowerDNSAuthoritativeNSInvalidData() (*AuthoritativeNS, func()) { 284 srv := httptest.NewServer(http.HandlerFunc( 285 func(w http.ResponseWriter, r *http.Request) { 286 _, _ = w.Write([]byte("hello and\n goodbye")) 287 })) 288 ns := New() 289 ns.URL = srv.URL 290 291 return ns, srv.Close 292 } 293 294 func preparePowerDNSAuthoritativeNS404() (*AuthoritativeNS, func()) { 295 srv := httptest.NewServer(http.HandlerFunc( 296 func(w http.ResponseWriter, r *http.Request) { 297 w.WriteHeader(http.StatusNotFound) 298 })) 299 ns := New() 300 ns.URL = srv.URL 301 302 return ns, srv.Close 303 } 304 305 func preparePowerDNSAuthoritativeNSConnectionRefused() (*AuthoritativeNS, func()) { 306 ns := New() 307 ns.URL = "http://127.0.0.1:38001" 308 309 return ns, func() {} 310 } 311 312 func preparePowerDNSAuthoritativeNSEndpoint() *httptest.Server { 313 return httptest.NewServer(http.HandlerFunc( 314 func(w http.ResponseWriter, r *http.Request) { 315 switch r.URL.Path { 316 case urlPathLocalStatistics: 317 _, _ = w.Write(v430statistics) 318 default: 319 w.WriteHeader(http.StatusNotFound) 320 } 321 })) 322 } 323 324 func preparePowerDNSRecursorEndpoint() *httptest.Server { 325 return httptest.NewServer(http.HandlerFunc( 326 func(w http.ResponseWriter, r *http.Request) { 327 switch r.URL.Path { 328 case urlPathLocalStatistics: 329 _, _ = w.Write(recursorStatistics) 330 default: 331 w.WriteHeader(http.StatusNotFound) 332 } 333 })) 334 }