master
go 256 lines 6.68 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package varnish
4
5 import (
6 "context"
7 "errors"
8 "os"
9 "testing"
10
11 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
12
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15 )
16
17 var (
18 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
19 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
20
21 dataVer71Varnishstat, _ = os.ReadFile("testdata/v7.1/varnishstat.txt")
22 )
23
24 func Test_testDataIsValid(t *testing.T) {
25 for name, data := range map[string][]byte{
26 "dataConfigJSON": dataConfigJSON,
27 "dataConfigYAML": dataConfigYAML,
28 "dataVer71Varnishstat": dataVer71Varnishstat,
29 } {
30 require.NotNil(t, data, name)
31 }
32 }
33
34 func TestCollector_Configuration(t *testing.T) {
35 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
36 }
37
38 func TestCollector_Init(t *testing.T) {
39 tests := map[string]struct {
40 config Config
41 wantFail bool
42 }{
43 "success with default config": {
44 wantFail: false,
45 config: New().Config,
46 },
47 }
48
49 for name, test := range tests {
50 t.Run(name, func(t *testing.T) {
51 collr := New()
52 collr.Config = test.config
53
54 if test.wantFail {
55 assert.Error(t, collr.Init(context.Background()))
56 } else {
57 assert.NoError(t, collr.Init(context.Background()))
58 }
59 })
60 }
61 }
62
63 func TestCollector_Cleanup(t *testing.T) {
64 tests := map[string]struct {
65 prepare func() *Collector
66 }{
67 "not initialized exec": {
68 prepare: func() *Collector {
69 return New()
70 },
71 },
72 "after check": {
73 prepare: func() *Collector {
74 collr := New()
75 collr.exec = prepareMockOkVer71()
76 _ = collr.Check(context.Background())
77 return collr
78 },
79 },
80 "after collect": {
81 prepare: func() *Collector {
82 collr := New()
83 collr.exec = prepareMockOkVer71()
84 _ = collr.Collect(context.Background())
85 return collr
86 },
87 },
88 }
89
90 for name, test := range tests {
91 t.Run(name, func(t *testing.T) {
92 collr := test.prepare()
93
94 assert.NotPanics(t, func() { collr.Cleanup(context.Background()) })
95 })
96 }
97 }
98
99 func TestCollector_Charts(t *testing.T) {
100 assert.NotNil(t, New().Charts())
101 }
102
103 func TestCollector_Check(t *testing.T) {
104 tests := map[string]struct {
105 prepareMock func() *mockVarnishstatExec
106 wantFail bool
107 }{
108 "success case": {
109 wantFail: false,
110 prepareMock: prepareMockOkVer71,
111 },
112 "error on varnishstat call": {
113 wantFail: true,
114 prepareMock: prepareMockErrOnVarnishstatCall,
115 },
116 "unexpected response": {
117 wantFail: true,
118 prepareMock: prepareMockUnexpectedResponse,
119 },
120 }
121
122 for name, test := range tests {
123 t.Run(name, func(t *testing.T) {
124 collr := New()
125 collr.exec = test.prepareMock()
126
127 if test.wantFail {
128 assert.Error(t, collr.Check(context.Background()))
129 } else {
130 assert.NoError(t, collr.Check(context.Background()))
131 }
132 })
133 }
134 }
135
136 func TestCollector_Collect(t *testing.T) {
137 tests := map[string]struct {
138 prepareMock func() *mockVarnishstatExec
139 wantMetrics map[string]int64
140 wantCharts int
141 }{
142 "success case varnish v7.1": {
143 prepareMock: prepareMockOkVer71,
144 wantCharts: len(varnishCharts) + len(backendChartsTmpl)*2 + len(storageChartsTmpl)*2,
145 wantMetrics: map[string]int64{
146 "MAIN.backend_busy": 0,
147 "MAIN.backend_conn": 2,
148 "MAIN.backend_fail": 0,
149 "MAIN.backend_recycle": 4,
150 "MAIN.backend_req": 4,
151 "MAIN.backend_retry": 0,
152 "MAIN.backend_reuse": 2,
153 "MAIN.backend_unhealthy": 0,
154 "MAIN.cache_hit": 0,
155 "MAIN.cache_hitmiss": 0,
156 "MAIN.cache_hitpass": 0,
157 "MAIN.cache_miss": 0,
158 "MAIN.client_req": 4,
159 "MAIN.esi_errors": 0,
160 "MAIN.esi_warnings": 0,
161 "MAIN.n_expired": 0,
162 "MAIN.n_lru_limited": 0,
163 "MAIN.n_lru_moved": 0,
164 "MAIN.n_lru_nuked": 0,
165 "MAIN.sess_conn": 4,
166 "MAIN.sess_dropped": 0,
167 "MAIN.thread_queue_len": 0,
168 "MAIN.threads": 200,
169 "MAIN.threads_created": 200,
170 "MAIN.threads_destroyed": 0,
171 "MAIN.threads_failed": 0,
172 "MAIN.threads_limited": 0,
173 "MAIN.uptime": 33834,
174 "MGT.child_died": 0,
175 "MGT.child_dump": 0,
176 "MGT.child_exit": 0,
177 "MGT.child_panic": 0,
178 "MGT.child_start": 1,
179 "MGT.child_stop": 0,
180 "MGT.uptime": 33833,
181 "SMA.Transient.g_alloc": 0,
182 "SMA.Transient.g_bytes": 0,
183 "SMA.Transient.g_space": 0,
184 "SMA.s0.g_alloc": 0,
185 "SMA.s0.g_bytes": 0,
186 "SMA.s0.g_space": 268435456,
187 "VBE.boot.default.bereq_bodybytes": 0,
188 "VBE.boot.default.bereq_hdrbytes": 5214,
189 "VBE.boot.default.beresp_bodybytes": 1170,
190 "VBE.boot.default.beresp_hdrbytes": 753,
191 "VBE.boot.nginx2.bereq_bodybytes": 0,
192 "VBE.boot.nginx2.bereq_hdrbytes": 0,
193 "VBE.boot.nginx2.beresp_bodybytes": 0,
194 "VBE.boot.nginx2.beresp_hdrbytes": 0,
195 },
196 },
197 "error on varnishstat call": {
198 prepareMock: prepareMockErrOnVarnishstatCall,
199 },
200 "unexpected response": {
201 prepareMock: prepareMockUnexpectedResponse,
202 },
203 }
204
205 for name, test := range tests {
206 t.Run(name, func(t *testing.T) {
207 collr := New()
208 collr.exec = test.prepareMock()
209
210 mx := collr.Collect(context.Background())
211
212 assert.Equal(t, test.wantMetrics, mx)
213
214 if len(test.wantMetrics) > 0 {
215 assert.Equal(t, test.wantCharts, len(*collr.Charts()))
216 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
217 }
218 })
219 }
220 }
221
222 func prepareMockOkVer71() *mockVarnishstatExec {
223 return &mockVarnishstatExec{
224 dataVarnishstat: dataVer71Varnishstat,
225 }
226 }
227
228 func prepareMockErrOnVarnishstatCall() *mockVarnishstatExec {
229 return &mockVarnishstatExec{
230 dataVarnishstat: nil,
231 errOnVarnishstatCall: true,
232 }
233 }
234
235 func prepareMockUnexpectedResponse() *mockVarnishstatExec {
236 return &mockVarnishstatExec{
237 dataVarnishstat: []byte(`
238 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
239 Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
240 Fusce et felis pulvinar, posuere sem non, porttitor eros.
241 `),
242 }
243 }
244
245 type mockVarnishstatExec struct {
246 errOnVarnishstatCall bool
247 dataVarnishstat []byte
248 }
249
250 func (m *mockVarnishstatExec) statistics() ([]byte, error) {
251 if m.errOnVarnishstatCall {
252 return nil, errors.New("mock statistics() error")
253 }
254
255 return m.dataVarnishstat, nil
256 }