master
go 310 lines 7.52 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux
4
5 package ap
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 dataIwDevManaged, _ = os.ReadFile("testdata/iw_dev_managed.txt")
24
25 dataIwDevAP, _ = os.ReadFile("testdata/iw_dev_ap.txt")
26 dataIwDevAPSsidWithSpaces, _ = os.ReadFile("testdata/iw_dev_ap_ssid_with_spaces.txt")
27 dataIwStationDump, _ = os.ReadFile("testdata/station_dump.txt")
28 )
29
30 func Test_testDataIsValid(t *testing.T) {
31 for name, data := range map[string][]byte{
32 "dataConfigJSON": dataConfigJSON,
33 "dataConfigYAML": dataConfigYAML,
34 "dataIwDevManaged": dataIwDevManaged,
35 "dataIwDevAP": dataIwDevAP,
36 "dataIwDevAPSsidWithSpaces": dataIwDevAPSsidWithSpaces,
37 "dataIwStationDump": dataIwStationDump,
38 } {
39 require.NotNil(t, data, name)
40 }
41 }
42
43 func TestCollector_Configuration(t *testing.T) {
44 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
45 }
46
47 func TestCollector_Init(t *testing.T) {
48 tests := map[string]struct {
49 config Config
50 wantFail bool
51 }{
52 "fails if 'binary_path' is not set": {
53 wantFail: true,
54 config: Config{
55 BinaryPath: "",
56 },
57 },
58 "fails if failed to find binary": {
59 wantFail: true,
60 config: Config{
61 BinaryPath: "iw!!!",
62 },
63 },
64 }
65
66 for name, test := range tests {
67 t.Run(name, func(t *testing.T) {
68 collr := New()
69 collr.Config = test.config
70
71 if test.wantFail {
72 assert.Error(t, collr.Init(context.Background()))
73 } else {
74 assert.NoError(t, collr.Init(context.Background()))
75 }
76 })
77 }
78 }
79
80 func TestCollector_Cleanup(t *testing.T) {
81 tests := map[string]struct {
82 prepare func() *Collector
83 }{
84 "not initialized exec": {
85 prepare: func() *Collector {
86 return New()
87 },
88 },
89 "after check": {
90 prepare: func() *Collector {
91 collr := New()
92 collr.exec = prepareMockOk()
93 _ = collr.Check(context.Background())
94 return collr
95 },
96 },
97 "after collect": {
98 prepare: func() *Collector {
99 collr := New()
100 collr.exec = prepareMockOk()
101 _ = collr.Collect(context.Background())
102 return collr
103 },
104 },
105 }
106
107 for name, test := range tests {
108 t.Run(name, func(t *testing.T) {
109 collr := test.prepare()
110
111 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
112 })
113 }
114 }
115
116 func TestCollector_Charts(t *testing.T) {
117 assert.NotNil(t, New().Charts())
118 }
119
120 func TestCollector_Check(t *testing.T) {
121 tests := map[string]struct {
122 prepareMock func() *mockIwExec
123 wantFail bool
124 }{
125 "success case": {
126 wantFail: false,
127 prepareMock: prepareMockOk,
128 },
129 "success case ssid with spaces": {
130 wantFail: false,
131 prepareMock: prepareMockOkSsidWithSpaces,
132 },
133 "no ap devices": {
134 wantFail: true,
135 prepareMock: prepareMockNoAPDevices,
136 },
137 "error on devices call": {
138 wantFail: true,
139 prepareMock: prepareMockErrOnDevices,
140 },
141 "error on station stats call": {
142 wantFail: true,
143 prepareMock: prepareMockErrOnStationStats,
144 },
145 "unexpected response": {
146 wantFail: true,
147 prepareMock: prepareMockUnexpectedResponse,
148 },
149 }
150
151 for name, test := range tests {
152 t.Run(name, func(t *testing.T) {
153 collr := New()
154 collr.exec = test.prepareMock()
155
156 if test.wantFail {
157 assert.Error(t, collr.Check(context.Background()))
158 } else {
159 assert.NoError(t, collr.Check(context.Background()))
160 }
161 })
162 }
163 }
164
165 func TestCollector_Collect(t *testing.T) {
166 tests := map[string]struct {
167 prepareMock func() *mockIwExec
168 wantMetrics map[string]int64
169 wantCharts int
170 }{
171 "success case": {
172 prepareMock: prepareMockOk,
173 wantCharts: len(apChartsTmpl) * 2,
174 wantMetrics: map[string]int64{
175 "ap_wlp1s0_testing_average_signal": -50666,
176 "ap_wlp1s0_testing_bitrate_receive": 49400,
177 "ap_wlp1s0_testing_bitrate_transmit": 43333,
178 "ap_wlp1s0_testing_bw_received": 101822,
179 "ap_wlp1s0_testing_bw_sent": 9284,
180 "ap_wlp1s0_testing_clients": 3,
181 "ap_wlp1s0_testing_issues_failures": 1,
182 "ap_wlp1s0_testing_issues_retries": 1,
183 "ap_wlp1s0_testing_packets_received": 2670,
184 "ap_wlp1s0_testing_packets_sent": 51,
185 "ap_wlp1s1_testing_average_signal": -50666,
186 "ap_wlp1s1_testing_bitrate_receive": 49400,
187 "ap_wlp1s1_testing_bitrate_transmit": 43333,
188 "ap_wlp1s1_testing_bw_received": 101822,
189 "ap_wlp1s1_testing_bw_sent": 9284,
190 "ap_wlp1s1_testing_clients": 3,
191 "ap_wlp1s1_testing_issues_failures": 1,
192 "ap_wlp1s1_testing_issues_retries": 1,
193 "ap_wlp1s1_testing_packets_received": 2670,
194 "ap_wlp1s1_testing_packets_sent": 51,
195 },
196 },
197 "success case ssid with spaces": {
198 prepareMock: prepareMockOkSsidWithSpaces,
199 wantCharts: len(apChartsTmpl) * 1,
200 wantMetrics: map[string]int64{
201 "ap_wlp1s0_My_AP_1_average_signal": -50666,
202 "ap_wlp1s0_My_AP_1_bitrate_receive": 49400,
203 "ap_wlp1s0_My_AP_1_bitrate_transmit": 43333,
204 "ap_wlp1s0_My_AP_1_bw_received": 101822,
205 "ap_wlp1s0_My_AP_1_bw_sent": 9284,
206 "ap_wlp1s0_My_AP_1_clients": 3,
207 "ap_wlp1s0_My_AP_1_issues_failures": 1,
208 "ap_wlp1s0_My_AP_1_issues_retries": 1,
209 "ap_wlp1s0_My_AP_1_packets_received": 2670,
210 "ap_wlp1s0_My_AP_1_packets_sent": 51,
211 },
212 },
213 "no ap devices": {
214 prepareMock: prepareMockNoAPDevices,
215 wantMetrics: nil,
216 },
217 "error on devices call": {
218 prepareMock: prepareMockErrOnDevices,
219 wantMetrics: nil,
220 },
221 "error on station stats call": {
222 prepareMock: prepareMockErrOnStationStats,
223 wantMetrics: nil,
224 },
225 "unexpected response": {
226 prepareMock: prepareMockUnexpectedResponse,
227 wantMetrics: nil,
228 },
229 }
230
231 for name, test := range tests {
232 t.Run(name, func(t *testing.T) {
233 collr := New()
234 collr.exec = test.prepareMock()
235
236 mx := collr.Collect(context.Background())
237
238 assert.Equal(t, test.wantMetrics, mx)
239
240 assert.Equal(t, test.wantCharts, len(*collr.Charts()), "wantCharts")
241
242 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
243 })
244 }
245 }
246
247 func prepareMockOk() *mockIwExec {
248 return &mockIwExec{
249 devicesData: dataIwDevAP,
250 stationStatsData: dataIwStationDump,
251 }
252 }
253
254 func prepareMockOkSsidWithSpaces() *mockIwExec {
255 return &mockIwExec{
256 devicesData: dataIwDevAPSsidWithSpaces,
257 stationStatsData: dataIwStationDump,
258 }
259 }
260
261 func prepareMockNoAPDevices() *mockIwExec {
262 return &mockIwExec{
263 devicesData: dataIwDevManaged,
264 }
265 }
266
267 func prepareMockErrOnDevices() *mockIwExec {
268 return &mockIwExec{
269 errOnDevices: true,
270 }
271 }
272
273 func prepareMockErrOnStationStats() *mockIwExec {
274 return &mockIwExec{
275 devicesData: dataIwDevAP,
276 errOnStationStats: true,
277 }
278 }
279
280 func prepareMockUnexpectedResponse() *mockIwExec {
281 return &mockIwExec{
282 devicesData: []byte(`
283 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
284 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
285 Fusce et felis pulvinar, posuere sem non, porttitor eros.
286 `),
287 }
288 }
289
290 type mockIwExec struct {
291 errOnDevices bool
292 errOnStationStats bool
293 devicesData []byte
294 stationStatsData []byte
295 }
296
297 func (m *mockIwExec) devices() ([]byte, error) {
298 if m.errOnDevices {
299 return nil, errors.New("mock.devices() error")
300 }
301
302 return m.devicesData, nil
303 }
304
305 func (m *mockIwExec) stationStatistics(_ string) ([]byte, error) {
306 if m.errOnStationStats {
307 return nil, errors.New("mock.stationStatistics() error")
308 }
309 return m.stationStatsData, nil
310 }