master
go 244 lines 5.57 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package rspamd
4
5 import (
6 "context"
7 "net/http"
8 "net/http/httptest"
9 "os"
10 "testing"
11
12 "github.com/netdata/netdata/go/plugins/pkg/web"
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 dataV34Stat, _ = os.ReadFile("testdata/v3.4-stat.json")
24 )
25
26 func Test_testDataIsValid(t *testing.T) {
27 for name, data := range map[string][]byte{
28 "dataConfigJSON": dataConfigJSON,
29 "dataConfigYAML": dataConfigYAML,
30 "dataV34Stat": dataV34Stat,
31 } {
32 require.NotNil(t, data, name)
33 }
34 }
35
36 func TestCollector_ConfigurationSerialize(t *testing.T) {
37 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
38 }
39
40 func TestCollector_Init(t *testing.T) {
41 tests := map[string]struct {
42 wantFail bool
43 config Config
44 }{
45 "success with default": {
46 wantFail: false,
47 config: New().Config,
48 },
49 "fail when URL not set": {
50 wantFail: true,
51 config: Config{
52 HTTPConfig: web.HTTPConfig{
53 RequestConfig: web.RequestConfig{URL: ""},
54 },
55 },
56 },
57 }
58
59 for name, test := range tests {
60 t.Run(name, func(t *testing.T) {
61 collr := New()
62 collr.Config = test.config
63
64 if test.wantFail {
65 assert.Error(t, collr.Init(context.Background()))
66 } else {
67 assert.NoError(t, collr.Init(context.Background()))
68 }
69 })
70 }
71 }
72
73 func TestCollector_Charts(t *testing.T) {
74 assert.NotNil(t, New().Charts())
75 }
76
77 func TestCollector_Check(t *testing.T) {
78 tests := map[string]struct {
79 wantFail bool
80 prepare func(t *testing.T) (*Collector, func())
81 }{
82 "success on valid response": {
83 wantFail: false,
84 prepare: prepareCaseOk,
85 },
86 "fails on unexpected json response": {
87 wantFail: true,
88 prepare: prepareCaseUnexpectedJsonResponse,
89 },
90 "fails on invalid format response": {
91 wantFail: true,
92 prepare: prepareCaseInvalidFormatResponse,
93 },
94 "fails on connection refused": {
95 wantFail: true,
96 prepare: prepareCaseConnectionRefused,
97 },
98 }
99
100 for name, test := range tests {
101 t.Run(name, func(t *testing.T) {
102 collr, cleanup := test.prepare(t)
103 defer cleanup()
104
105 if test.wantFail {
106 assert.Error(t, collr.Check(context.Background()))
107 } else {
108 assert.NoError(t, collr.Check(context.Background()))
109 }
110 })
111 }
112 }
113
114 func TestCollector_Collect(t *testing.T) {
115 tests := map[string]struct {
116 prepare func(t *testing.T) (*Collector, func())
117 wantMetrics map[string]int64
118 }{
119 "success on valid response": {
120 prepare: prepareCaseOk,
121 wantMetrics: map[string]int64{
122 "actions_add_header": 1,
123 "actions_custom": 0,
124 "actions_discard": 0,
125 "actions_greylist": 1,
126 "actions_invalid_max_action": 0,
127 "actions_no_action": 1,
128 "actions_quarantine": 0,
129 "actions_reject": 1,
130 "actions_rewrite_subject": 1,
131 "actions_soft_reject": 1,
132 "actions_unknown_action": 0,
133 "connections": 1,
134 "control_connections": 117,
135 "ham_count": 1,
136 "learned": 1,
137 "scanned": 1,
138 "spam_count": 1,
139 },
140 },
141 "fails on unexpected json response": {
142 prepare: prepareCaseUnexpectedJsonResponse,
143 },
144 "fails on invalid format response": {
145 prepare: prepareCaseInvalidFormatResponse,
146 },
147 "fails on connection refused": {
148 prepare: prepareCaseConnectionRefused,
149 },
150 }
151
152 for name, test := range tests {
153 t.Run(name, func(t *testing.T) {
154 collr, cleanup := test.prepare(t)
155 defer cleanup()
156
157 mx := collr.Collect(context.Background())
158
159 require.Equal(t, test.wantMetrics, mx)
160
161 if len(test.wantMetrics) > 0 {
162 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
163 }
164 })
165 }
166 }
167
168 func prepareCaseOk(t *testing.T) (*Collector, func()) {
169 t.Helper()
170 srv := httptest.NewServer(http.HandlerFunc(
171 func(w http.ResponseWriter, r *http.Request) {
172 switch r.URL.Path {
173 case "/stat":
174 _, _ = w.Write(dataV34Stat)
175 default:
176 w.WriteHeader(http.StatusNotFound)
177 }
178 }))
179
180 collr := New()
181 collr.URL = srv.URL
182 require.NoError(t, collr.Init(context.Background()))
183
184 return collr, srv.Close
185 }
186
187 func prepareCaseUnexpectedJsonResponse(t *testing.T) (*Collector, func()) {
188 t.Helper()
189 resp := `
190 {
191 "elephant": {
192 "burn": false,
193 "mountain": true,
194 "fog": false,
195 "skin": -1561907625,
196 "burst": "anyway",
197 "shadow": 1558616893
198 },
199 "start": "ever",
200 "base": 2093056027,
201 "mission": -2007590351,
202 "victory": 999053756,
203 "die": false
204 }
205 `
206 srv := httptest.NewServer(http.HandlerFunc(
207 func(w http.ResponseWriter, r *http.Request) {
208 switch r.URL.Path {
209 case "/stat":
210 _, _ = w.Write([]byte(resp))
211 default:
212 w.WriteHeader(http.StatusNotFound)
213 }
214 }))
215
216 collr := New()
217 collr.URL = srv.URL
218 require.NoError(t, collr.Init(context.Background()))
219
220 return collr, srv.Close
221 }
222
223 func prepareCaseInvalidFormatResponse(t *testing.T) (*Collector, func()) {
224 t.Helper()
225 srv := httptest.NewServer(http.HandlerFunc(
226 func(w http.ResponseWriter, r *http.Request) {
227 _, _ = w.Write([]byte("hello and\n goodbye"))
228 }))
229
230 collr := New()
231 collr.URL = srv.URL
232 require.NoError(t, collr.Init(context.Background()))
233
234 return collr, srv.Close
235 }
236
237 func prepareCaseConnectionRefused(t *testing.T) (*Collector, func()) {
238 t.Helper()
239 collr := New()
240 collr.URL = "http://127.0.0.1:65001/stat"
241 require.NoError(t, collr.Init(context.Background()))
242
243 return collr, func() {}
244 }