master
go 340 lines 8.03 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux || freebsd || openbsd || netbsd || dragonfly || darwin
4
5 package nsd
6
7 import (
8 "context"
9 "errors"
10 "os"
11 "testing"
12
13 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
14
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
17 )
18
19 var (
20 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
21 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
22
23 dataStats, _ = os.ReadFile("testdata/stats.txt")
24 )
25
26 func Test_testDataIsValid(t *testing.T) {
27 for name, data := range map[string][]byte{
28 "dataConfigJSON": dataConfigJSON,
29 "dataConfigYAML": dataConfigYAML,
30 "dataStats": dataStats,
31 } {
32 require.NotNil(t, data, name)
33
34 }
35 }
36
37 func TestCollector_Configuration(t *testing.T) {
38 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
39 }
40
41 func TestCollector_Init(t *testing.T) {
42 tests := map[string]struct {
43 config Config
44 wantFail bool
45 }{
46 "success with default config": {
47 wantFail: false,
48 config: New().Config,
49 },
50 }
51
52 for name, test := range tests {
53 t.Run(name, func(t *testing.T) {
54 collr := New()
55 collr.Config = test.config
56
57 if test.wantFail {
58 assert.Error(t, collr.Init(context.Background()))
59 } else {
60 assert.NoError(t, collr.Init(context.Background()))
61 }
62 })
63 }
64 }
65
66 func TestCollector_Cleanup(t *testing.T) {
67 tests := map[string]struct {
68 prepare func() *Collector
69 }{
70 "not initialized exec": {
71 prepare: func() *Collector {
72 return New()
73 },
74 },
75 "after check": {
76 prepare: func() *Collector {
77 collr := New()
78 collr.exec = prepareMockOK()
79 _ = collr.Check(context.Background())
80 return collr
81 },
82 },
83 "after collect": {
84 prepare: func() *Collector {
85 collr := New()
86 collr.exec = prepareMockOK()
87 _ = collr.Collect(context.Background())
88 return collr
89 },
90 },
91 }
92
93 for name, test := range tests {
94 t.Run(name, func(t *testing.T) {
95 collr := test.prepare()
96
97 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
98 })
99 }
100 }
101
102 func TestCollector_Charts(t *testing.T) {
103 assert.NotNil(t, New().Charts())
104 }
105
106 func TestCollector_Check(t *testing.T) {
107 tests := map[string]struct {
108 prepareMock func() *mockNsdControl
109 wantFail bool
110 }{
111 "success case": {
112 prepareMock: prepareMockOK,
113 wantFail: false,
114 },
115 "error on stats call": {
116 prepareMock: prepareMockErrOnStats,
117 wantFail: true,
118 },
119 "empty response": {
120 prepareMock: prepareMockEmptyResponse,
121 wantFail: true,
122 },
123 "unexpected response": {
124 prepareMock: prepareMockUnexpectedResponse,
125 wantFail: true,
126 },
127 }
128
129 for name, test := range tests {
130 t.Run(name, func(t *testing.T) {
131 collr := New()
132 mock := test.prepareMock()
133 collr.exec = mock
134
135 if test.wantFail {
136 assert.Error(t, collr.Check(context.Background()))
137 } else {
138 assert.NoError(t, collr.Check(context.Background()))
139 }
140 })
141 }
142 }
143
144 func TestCollector_Collect(t *testing.T) {
145 tests := map[string]struct {
146 prepareMock func() *mockNsdControl
147 wantMetrics map[string]int64
148 }{
149 "success case": {
150 prepareMock: prepareMockOK,
151 wantMetrics: map[string]int64{
152 "num.answer_wo_aa": 1,
153 "num.class.CH": 0,
154 "num.class.CS": 0,
155 "num.class.HS": 0,
156 "num.class.IN": 1,
157 "num.dropped": 1,
158 "num.edns": 1,
159 "num.ednserr": 1,
160 "num.opcode.IQUERY": 0,
161 "num.opcode.NOTIFY": 0,
162 "num.opcode.OTHER": 0,
163 "num.opcode.QUERY": 1,
164 "num.opcode.STATUS": 0,
165 "num.opcode.UPDATE": 0,
166 "num.queries": 1,
167 "num.raxfr": 1,
168 "num.rcode.BADVERS": 0,
169 "num.rcode.FORMERR": 1,
170 "num.rcode.NOERROR": 1,
171 "num.rcode.NOTAUTH": 0,
172 "num.rcode.NOTIMP": 1,
173 "num.rcode.NOTZONE": 0,
174 "num.rcode.NXDOMAIN": 1,
175 "num.rcode.NXRRSET": 0,
176 "num.rcode.RCODE11": 0,
177 "num.rcode.RCODE12": 0,
178 "num.rcode.RCODE13": 0,
179 "num.rcode.RCODE14": 0,
180 "num.rcode.RCODE15": 0,
181 "num.rcode.REFUSED": 1,
182 "num.rcode.SERVFAIL": 1,
183 "num.rcode.YXDOMAIN": 1,
184 "num.rcode.YXRRSET": 0,
185 "num.rixfr": 1,
186 "num.rxerr": 1,
187 "num.tcp": 1,
188 "num.tcp6": 1,
189 "num.tls": 1,
190 "num.tls6": 1,
191 "num.truncated": 1,
192 "num.txerr": 1,
193 "num.type.A": 1,
194 "num.type.AAAA": 1,
195 "num.type.AFSDB": 1,
196 "num.type.APL": 1,
197 "num.type.AVC": 0,
198 "num.type.CAA": 0,
199 "num.type.CDNSKEY": 1,
200 "num.type.CDS": 1,
201 "num.type.CERT": 1,
202 "num.type.CNAME": 1,
203 "num.type.CSYNC": 1,
204 "num.type.DHCID": 1,
205 "num.type.DLV": 0,
206 "num.type.DNAME": 1,
207 "num.type.DNSKEY": 1,
208 "num.type.DS": 1,
209 "num.type.EUI48": 1,
210 "num.type.EUI64": 1,
211 "num.type.HINFO": 1,
212 "num.type.HTTPS": 1,
213 "num.type.IPSECKEY": 1,
214 "num.type.ISDN": 1,
215 "num.type.KEY": 1,
216 "num.type.KX": 1,
217 "num.type.L32": 1,
218 "num.type.L64": 1,
219 "num.type.LOC": 1,
220 "num.type.LP": 1,
221 "num.type.MB": 1,
222 "num.type.MD": 1,
223 "num.type.MF": 1,
224 "num.type.MG": 1,
225 "num.type.MINFO": 1,
226 "num.type.MR": 1,
227 "num.type.MX": 1,
228 "num.type.NAPTR": 1,
229 "num.type.NID": 1,
230 "num.type.NS": 1,
231 "num.type.NSAP": 1,
232 "num.type.NSEC": 1,
233 "num.type.NSEC3": 1,
234 "num.type.NSEC3PARAM": 1,
235 "num.type.NULL": 1,
236 "num.type.NXT": 1,
237 "num.type.OPENPGPKEY": 1,
238 "num.type.OPT": 1,
239 "num.type.PTR": 1,
240 "num.type.PX": 1,
241 "num.type.RP": 1,
242 "num.type.RRSIG": 1,
243 "num.type.RT": 1,
244 "num.type.SIG": 1,
245 "num.type.SMIMEA": 1,
246 "num.type.SOA": 1,
247 "num.type.SPF": 1,
248 "num.type.SRV": 1,
249 "num.type.SSHFP": 1,
250 "num.type.SVCB": 1,
251 "num.type.TLSA": 1,
252 "num.type.TXT": 1,
253 "num.type.TYPE252": 0,
254 "num.type.TYPE255": 0,
255 "num.type.URI": 0,
256 "num.type.WKS": 1,
257 "num.type.X25": 1,
258 "num.type.ZONEMD": 1,
259 "num.udp": 1,
260 "num.udp6": 1,
261 "server0.queries": 1,
262 "size.config.disk": 1,
263 "size.config.mem": 1064,
264 "size.db.disk": 576,
265 "size.db.mem": 920,
266 "size.xfrd.mem": 1160464,
267 "time.boot": 556,
268 "zone.master": 1,
269 "zone.slave": 1,
270 },
271 },
272 "error on lvs report call": {
273 prepareMock: prepareMockErrOnStats,
274 wantMetrics: nil,
275 },
276 "empty response": {
277 prepareMock: prepareMockEmptyResponse,
278 wantMetrics: nil,
279 },
280 "unexpected response": {
281 prepareMock: prepareMockUnexpectedResponse,
282 wantMetrics: nil,
283 },
284 }
285
286 for name, test := range tests {
287 t.Run(name, func(t *testing.T) {
288 collr := New()
289 mock := test.prepareMock()
290 collr.exec = mock
291
292 mx := collr.Collect(context.Background())
293
294 assert.Equal(t, test.wantMetrics, mx)
295
296 if len(test.wantMetrics) > 0 {
297 assert.Len(t, *collr.Charts(), len(charts))
298 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
299 }
300 })
301 }
302 }
303
304 func prepareMockOK() *mockNsdControl {
305 return &mockNsdControl{
306 dataStats: dataStats,
307 }
308 }
309
310 func prepareMockErrOnStats() *mockNsdControl {
311 return &mockNsdControl{
312 errOnStatus: true,
313 }
314 }
315
316 func prepareMockEmptyResponse() *mockNsdControl {
317 return &mockNsdControl{}
318 }
319
320 func prepareMockUnexpectedResponse() *mockNsdControl {
321 return &mockNsdControl{
322 dataStats: []byte(`
323 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
324 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
325 Fusce et felis pulvinar, posuere sem non, porttitor eros.
326 `),
327 }
328 }
329
330 type mockNsdControl struct {
331 errOnStatus bool
332 dataStats []byte
333 }
334
335 func (m *mockNsdControl) stats() ([]byte, error) {
336 if m.errOnStatus {
337 return nil, errors.New("mock.status() error")
338 }
339 return m.dataStats, nil
340 }