master
go 247 lines 5.62 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package zookeeper
4
5 import (
6 "bufio"
7 "bytes"
8 "context"
9 "errors"
10 "os"
11 "testing"
12
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15
16 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
17 )
18
19 var (
20 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
21 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
22
23 dataVer39Mntr, _ = os.ReadFile("testdata/v3.9/mntr.txt")
24 dataMntrNotInWhiteList, _ = os.ReadFile("testdata/mntr_notinwhitelist.txt")
25 )
26
27 func Test_testDataIsValid(t *testing.T) {
28 for name, data := range map[string][]byte{
29 "dataConfigJSON": dataConfigJSON,
30 "dataConfigYAML": dataConfigYAML,
31 "dataVer39Mntr": dataVer39Mntr,
32 "dataMntrNotInWhiteListResponse": dataMntrNotInWhiteList,
33 } {
34 assert.NotNil(t, data, name)
35 }
36 }
37
38 func TestCollector_ConfigurationSerialize(t *testing.T) {
39 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
40 }
41
42 func TestCollector_Init(t *testing.T) {
43 tests := map[string]struct {
44 config Config
45 wantFail bool
46 }{
47 "success on default config": {
48 config: New().Config,
49 },
50 "fails on unset 'address'": {
51 wantFail: true,
52 config: Config{
53 Address: "",
54 },
55 },
56 }
57
58 for name, test := range tests {
59 t.Run(name, func(t *testing.T) {
60 collr := New()
61 collr.Config = test.config
62
63 if test.wantFail {
64 assert.Error(t, collr.Init(context.Background()))
65 } else {
66 assert.NoError(t, collr.Init(context.Background()))
67 }
68 })
69 }
70 }
71
72 func TestCollector_Charts(t *testing.T) {
73 assert.NotNil(t, New().Charts())
74 }
75
76 func TestCollector_Cleanup(t *testing.T) {
77 tests := map[string]struct {
78 prepare func(t *testing.T) *Collector
79 }{
80 "not initialized": {
81 prepare: func(t *testing.T) *Collector {
82 return New()
83 },
84 },
85 "initialized": {
86 prepare: func(t *testing.T) *Collector {
87 collr := New()
88 require.NoError(t, collr.Init(context.Background()))
89 return collr
90 },
91 },
92 }
93
94 for name, test := range tests {
95 t.Run(name, func(t *testing.T) {
96 collr := test.prepare(t)
97
98 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
99 })
100 }
101 }
102
103 func TestCollector_Check(t *testing.T) {
104 tests := map[string]struct {
105 prepare func() *mockZookeeperFetcher
106 wantFail bool
107 }{
108 "success v3.9": {
109 wantFail: false,
110 prepare: prepareMockVer39Ok,
111 },
112 "fails if mntr is not whitelisted": {
113 wantFail: true,
114 prepare: prepareMockMntrNotInWhitelist,
115 },
116 "fails on empty response": {
117 wantFail: true,
118 prepare: prepareMockMntrEmptyResponse,
119 },
120 "fails on fetch error": {
121 wantFail: true,
122 prepare: prepareMockErrOnFetch,
123 },
124 }
125
126 for name, test := range tests {
127 t.Run(name, func(t *testing.T) {
128 collr := New()
129 require.NoError(t, collr.Init(context.Background()))
130 collr.fetcher = test.prepare()
131
132 if test.wantFail {
133 assert.Error(t, collr.Check(context.Background()))
134 } else {
135 assert.NoError(t, collr.Check(context.Background()))
136 }
137 })
138 }
139 }
140
141 func TestCollector_Collect(t *testing.T) {
142 tests := map[string]struct {
143 prepare func() *mockZookeeperFetcher
144 wantMetrics map[string]int64
145 }{
146 "success v3.9": {
147 prepare: prepareMockVer39Ok,
148 wantMetrics: map[string]int64{
149 "approximate_data_size": 44,
150 "auth_failed_count": 0,
151 "avg_latency": 0,
152 "connection_drop_count": 0,
153 "connection_rejected": 0,
154 "ephemerals_count": 0,
155 "global_sessions": 0,
156 "max_file_descriptor_count": 1048576,
157 "max_latency": 0,
158 "min_latency": 0,
159 "num_alive_connections": 1,
160 "open_file_descriptor_count": 77,
161 "outstanding_requests": 0,
162 "packets_received": 452,
163 "packets_sent": 1353,
164 "server_state_follower": 0,
165 "server_state_leader": 0,
166 "server_state_observer": 0,
167 "server_state_standalone": 1,
168 "stale_requests": 0,
169 "stale_requests_dropped": 0,
170 "throttled_ops": 0,
171 "uptime": 488,
172 "watch_count": 0,
173 "znode_count": 5,
174 },
175 },
176 "fails if mntr is not whitelisted": {
177 prepare: prepareMockMntrNotInWhitelist,
178 },
179 "fails on empty response": {
180 prepare: prepareMockMntrEmptyResponse,
181 },
182 "fails on fetch error": {
183 prepare: prepareMockErrOnFetch,
184 },
185 }
186
187 for name, test := range tests {
188 t.Run(name, func(t *testing.T) {
189 collr := New()
190 require.NoError(t, collr.Init(context.Background()))
191 collr.fetcher = test.prepare()
192
193 mx := collr.Collect(context.Background())
194
195 assert.Equal(t, test.wantMetrics, mx)
196 if len(mx) > 0 {
197 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
198 }
199 })
200 }
201 }
202
203 func prepareMockVer39Ok() *mockZookeeperFetcher {
204 return &mockZookeeperFetcher{
205 dataMntr: dataVer39Mntr,
206 }
207 }
208
209 func prepareMockMntrNotInWhitelist() *mockZookeeperFetcher {
210 return &mockZookeeperFetcher{
211 dataMntr: dataMntrNotInWhiteList,
212 }
213 }
214
215 func prepareMockMntrEmptyResponse() *mockZookeeperFetcher {
216 return &mockZookeeperFetcher{}
217 }
218
219 func prepareMockErrOnFetch() *mockZookeeperFetcher {
220 return &mockZookeeperFetcher{
221 errOnFetch: true,
222 }
223 }
224
225 type mockZookeeperFetcher struct {
226 dataMntr []byte
227 errOnFetch bool
228 }
229
230 func (m mockZookeeperFetcher) fetch(cmd string) ([]string, error) {
231 if m.errOnFetch {
232 return nil, errors.New("mock fetch error")
233 }
234
235 if cmd != "mntr" {
236 return nil, errors.New("invalid command")
237 }
238
239 var lines []string
240
241 s := bufio.NewScanner(bytes.NewReader(m.dataMntr))
242 for s.Scan() {
243 lines = append(lines, s.Text())
244 }
245
246 return lines, nil
247 }