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