]>
Commit | Line | Data |
---|---|---|
2ad41f52 AG |
1 | package statuscake |
2 | ||
3 | import ( | |
4 | "bytes" | |
5 | "encoding/json" | |
6 | "io/ioutil" | |
7 | "log" | |
8 | "net/http" | |
9 | "net/url" | |
10 | "os" | |
11 | "path/filepath" | |
12 | "strings" | |
13 | "testing" | |
14 | ||
15 | "github.com/stretchr/testify/assert" | |
16 | "github.com/stretchr/testify/require" | |
17 | ) | |
18 | ||
19 | func TestTest_Validate(t *testing.T) { | |
20 | assert := assert.New(t) | |
21 | require := require.New(t) | |
22 | ||
23 | test := &Test{ | |
24 | Timeout: 200, | |
25 | Confirmation: 100, | |
26 | Public: 200, | |
27 | Virus: 200, | |
28 | TestType: "FTP", | |
29 | RealBrowser: 100, | |
30 | TriggerRate: 100, | |
31 | CheckRate: 100000, | |
32 | CustomHeader: "here be dragons", | |
33 | WebsiteName: "", | |
34 | WebsiteURL: "", | |
35 | } | |
36 | ||
37 | err := test.Validate() | |
38 | require.NotNil(err) | |
39 | ||
40 | message := err.Error() | |
41 | assert.Contains(message, "WebsiteName is required") | |
42 | assert.Contains(message, "WebsiteURL is required") | |
43 | assert.Contains(message, "Timeout must be 0 or between 6 and 99") | |
44 | assert.Contains(message, "Confirmation must be between 0 and 9") | |
45 | assert.Contains(message, "CheckRate must be between 0 and 23999") | |
46 | assert.Contains(message, "Public must be 0 or 1") | |
47 | assert.Contains(message, "Virus must be 0 or 1") | |
48 | assert.Contains(message, "TestType must be HTTP, TCP, or PING") | |
49 | assert.Contains(message, "RealBrowser must be 0 or 1") | |
50 | assert.Contains(message, "TriggerRate must be between 0 and 59") | |
51 | assert.Contains(message, "CustomHeader must be provided as json string") | |
52 | ||
53 | test.Timeout = 10 | |
54 | test.Confirmation = 2 | |
55 | test.Public = 1 | |
56 | test.Virus = 1 | |
57 | test.TestType = "HTTP" | |
58 | test.RealBrowser = 1 | |
59 | test.TriggerRate = 50 | |
60 | test.CheckRate = 10 | |
61 | test.WebsiteName = "Foo" | |
62 | test.WebsiteURL = "http://example.com" | |
63 | test.CustomHeader = `{"test": 15}` | |
64 | test.NodeLocations = []string{"foo", "bar"} | |
65 | ||
66 | err = test.Validate() | |
67 | assert.Nil(err) | |
68 | } | |
69 | ||
70 | func TestTest_ToURLValues(t *testing.T) { | |
71 | assert := assert.New(t) | |
72 | ||
73 | test := &Test{ | |
74 | TestID: 123, | |
75 | Paused: true, | |
76 | WebsiteName: "Foo Bar", | |
77 | CustomHeader: `{"some":{"json": ["value"]}}`, | |
78 | WebsiteURL: "http://example.com", | |
79 | Port: 3000, | |
80 | NodeLocations: []string{"foo", "bar"}, | |
81 | Timeout: 11, | |
82 | PingURL: "http://example.com/ping", | |
83 | Confirmation: 1, | |
84 | CheckRate: 500, | |
85 | BasicUser: "myuser", | |
86 | BasicPass: "mypass", | |
87 | Public: 1, | |
88 | LogoImage: "http://example.com/logo.jpg", | |
89 | Branding: 1, | |
90 | WebsiteHost: "hoster", | |
91 | Virus: 1, | |
92 | FindString: "hello", | |
93 | DoNotFind: true, | |
94 | TestType: "HTTP", | |
95 | RealBrowser: 1, | |
96 | TriggerRate: 50, | |
97 | TestTags: []string{"tag1", "tag2"}, | |
98 | StatusCodes: "500", | |
99 | EnableSSLAlert: false, | |
100 | FollowRedirect: false, | |
101 | } | |
102 | ||
103 | expected := url.Values{ | |
104 | "TestID": {"123"}, | |
105 | "Paused": {"1"}, | |
106 | "WebsiteName": {"Foo Bar"}, | |
107 | "WebsiteURL": {"http://example.com"}, | |
108 | "CustomHeader": {`{"some":{"json": ["value"]}}`}, | |
109 | "Port": {"3000"}, | |
110 | "NodeLocations": {"foo,bar"}, | |
111 | "Timeout": {"11"}, | |
112 | "PingURL": {"http://example.com/ping"}, | |
113 | "ContactGroup": {""}, | |
114 | "Confirmation": {"1"}, | |
115 | "CheckRate": {"500"}, | |
116 | "BasicUser": {"myuser"}, | |
117 | "BasicPass": {"mypass"}, | |
118 | "Public": {"1"}, | |
119 | "LogoImage": {"http://example.com/logo.jpg"}, | |
120 | "Branding": {"1"}, | |
121 | "WebsiteHost": {"hoster"}, | |
122 | "Virus": {"1"}, | |
123 | "FindString": {"hello"}, | |
124 | "DoNotFind": {"1"}, | |
125 | "TestType": {"HTTP"}, | |
126 | "RealBrowser": {"1"}, | |
127 | "TriggerRate": {"50"}, | |
128 | "TestTags": {"tag1,tag2"}, | |
129 | "StatusCodes": {"500"}, | |
130 | "UseJar": {"0"}, | |
131 | "PostRaw": {""}, | |
132 | "FinalEndpoint": {""}, | |
133 | "EnableSSLAlert": {"0"}, | |
134 | "FollowRedirect": {"0"}, | |
135 | } | |
136 | ||
137 | assert.Equal(expected, test.ToURLValues()) | |
138 | ||
139 | test.TestID = 0 | |
140 | delete(expected, "TestID") | |
141 | ||
142 | assert.Equal(expected.Encode(), test.ToURLValues().Encode()) | |
143 | } | |
144 | ||
145 | func TestTests_All(t *testing.T) { | |
146 | assert := assert.New(t) | |
147 | require := require.New(t) | |
148 | ||
149 | c := &fakeAPIClient{ | |
150 | fixture: "tests_all_ok.json", | |
151 | } | |
152 | tt := newTests(c) | |
153 | tests, err := tt.All() | |
154 | require.Nil(err) | |
155 | ||
156 | assert.Equal("/Tests", c.sentRequestPath) | |
157 | assert.Equal("GET", c.sentRequestMethod) | |
158 | assert.Nil(c.sentRequestValues) | |
159 | assert.Len(tests, 2) | |
160 | ||
161 | expectedTest := &Test{ | |
162 | TestID: 100, | |
163 | Paused: false, | |
164 | TestType: "HTTP", | |
165 | WebsiteName: "www 1", | |
166 | ContactGroup: []string{"1"}, | |
167 | Status: "Up", | |
168 | Uptime: 100, | |
169 | NodeLocations: []string{"foo", "bar"}, | |
170 | } | |
171 | assert.Equal(expectedTest, tests[0]) | |
172 | ||
173 | expectedTest = &Test{ | |
174 | TestID: 101, | |
175 | Paused: true, | |
176 | TestType: "HTTP", | |
177 | WebsiteName: "www 2", | |
178 | ContactGroup: []string{"2"}, | |
179 | Status: "Down", | |
180 | Uptime: 0, | |
181 | NodeLocations: []string{"foo"}, | |
182 | TestTags: []string{"test1", "test2"}, | |
183 | } | |
184 | assert.Equal(expectedTest, tests[1]) | |
185 | } | |
186 | ||
187 | func TestTests_AllWithFilter(t *testing.T) { | |
188 | assert := assert.New(t) | |
189 | require := require.New(t) | |
190 | ||
191 | c := &fakeAPIClient{ | |
192 | fixture: "tests_all_ok.json", | |
193 | } | |
194 | ||
195 | v := url.Values{} | |
196 | v.Set("tags", "test1,test2") | |
197 | tt := newTests(c) | |
198 | tests, err := tt.AllWithFilter(v) | |
199 | require.Nil(err) | |
200 | ||
201 | assert.Equal("/Tests", c.sentRequestPath) | |
202 | assert.Equal("GET", c.sentRequestMethod) | |
203 | assert.NotNil(c.sentRequestValues) | |
204 | assert.Len(tests, 1) | |
205 | ||
206 | expectedTest := &Test{ | |
207 | TestID: 101, | |
208 | Paused: true, | |
209 | TestType: "HTTP", | |
210 | WebsiteName: "www 2", | |
211 | ContactGroup: []string{"2"}, | |
212 | Status: "Down", | |
213 | Uptime: 0, | |
214 | NodeLocations: []string{"foo"}, | |
215 | TestTags: []string{"test1", "test2"}, | |
216 | } | |
217 | assert.Equal(expectedTest, tests[0]) | |
218 | } | |
219 | ||
220 | func TestTests_Update_OK(t *testing.T) { | |
221 | assert := assert.New(t) | |
222 | require := require.New(t) | |
223 | ||
224 | c := &fakeAPIClient{ | |
225 | fixture: "tests_update_ok.json", | |
226 | } | |
227 | tt := newTests(c) | |
228 | ||
229 | test1 := &Test{ | |
230 | WebsiteName: "foo", | |
231 | } | |
232 | ||
233 | test2, err := tt.Update(test1) | |
234 | require.Nil(err) | |
235 | ||
236 | assert.Equal("/Tests/Update", c.sentRequestPath) | |
237 | assert.Equal("PUT", c.sentRequestMethod) | |
238 | assert.NotNil(c.sentRequestValues) | |
239 | assert.NotNil(test2) | |
240 | ||
241 | assert.Equal(1234, test2.TestID) | |
242 | } | |
243 | ||
244 | func TestTests_Update_Error(t *testing.T) { | |
245 | assert := assert.New(t) | |
246 | require := require.New(t) | |
247 | ||
248 | c := &fakeAPIClient{ | |
249 | fixture: "tests_update_error.json", | |
250 | } | |
251 | tt := newTests(c) | |
252 | ||
253 | test1 := &Test{ | |
254 | WebsiteName: "foo", | |
255 | } | |
256 | ||
257 | test2, err := tt.Update(test1) | |
258 | assert.Nil(test2) | |
259 | ||
260 | require.NotNil(err) | |
261 | assert.IsType(&updateError{}, err) | |
262 | assert.Contains(err.Error(), "issue a") | |
263 | } | |
264 | ||
265 | func TestTests_Update_ErrorWithSliceOfIssues(t *testing.T) { | |
266 | assert := assert.New(t) | |
267 | require := require.New(t) | |
268 | ||
269 | c := &fakeAPIClient{ | |
270 | fixture: "tests_update_error_slice_of_issues.json", | |
271 | } | |
272 | tt := newTests(c) | |
273 | ||
274 | test1 := &Test{ | |
275 | WebsiteName: "foo", | |
276 | } | |
277 | ||
278 | test2, err := tt.Update(test1) | |
279 | assert.Nil(test2) | |
280 | ||
281 | require.NotNil(err) | |
282 | assert.IsType(&updateError{}, err) | |
283 | assert.Equal("Required Data is Missing., hello, world", err.Error()) | |
284 | } | |
285 | ||
286 | func TestTests_Delete_OK(t *testing.T) { | |
287 | assert := assert.New(t) | |
288 | require := require.New(t) | |
289 | ||
290 | c := &fakeAPIClient{ | |
291 | fixture: "tests_delete_ok.json", | |
292 | } | |
293 | tt := newTests(c) | |
294 | ||
295 | err := tt.Delete(1234) | |
296 | require.Nil(err) | |
297 | ||
298 | assert.Equal("/Tests/Details", c.sentRequestPath) | |
299 | assert.Equal("DELETE", c.sentRequestMethod) | |
300 | assert.Equal(url.Values{"TestID": {"1234"}}, c.sentRequestValues) | |
301 | } | |
302 | ||
303 | func TestTests_Delete_Error(t *testing.T) { | |
304 | assert := assert.New(t) | |
305 | require := require.New(t) | |
306 | ||
307 | c := &fakeAPIClient{ | |
308 | fixture: "tests_delete_error.json", | |
309 | } | |
310 | tt := newTests(c) | |
311 | ||
312 | err := tt.Delete(1234) | |
313 | require.NotNil(err) | |
314 | assert.Equal("this is an error", err.Error()) | |
315 | } | |
316 | ||
317 | func TestTests_Detail_OK(t *testing.T) { | |
318 | assert := assert.New(t) | |
319 | require := require.New(t) | |
320 | ||
321 | c := &fakeAPIClient{ | |
322 | fixture: "tests_detail_ok.json", | |
323 | } | |
324 | tt := newTests(c) | |
325 | ||
326 | test, err := tt.Detail(1234) | |
327 | require.Nil(err) | |
328 | ||
329 | assert.Equal("/Tests/Details", c.sentRequestPath) | |
330 | assert.Equal("GET", c.sentRequestMethod) | |
331 | assert.Equal(url.Values{"TestID": {"1234"}}, c.sentRequestValues) | |
332 | ||
333 | assert.Equal(test.TestID, 6735) | |
334 | assert.Equal(test.TestType, "HTTP") | |
335 | assert.Equal(test.Paused, false) | |
336 | assert.Equal(test.WebsiteName, "NL") | |
337 | assert.Equal(test.CustomHeader, `{"some":{"json": ["value"]}}`) | |
338 | assert.Equal(test.UserAgent, "product/version (comment)") | |
339 | assert.Equal(test.ContactGroup, []string{"536"}) | |
340 | assert.Equal(test.Status, "Up") | |
341 | assert.Equal(test.Uptime, 0.0) | |
342 | assert.Equal(test.CheckRate, 60) | |
343 | assert.Equal(test.Timeout, 40) | |
344 | assert.Equal(test.LogoImage, "") | |
345 | assert.Equal(test.WebsiteHost, "Various") | |
346 | assert.Equal(test.FindString, "") | |
347 | assert.Equal(test.DoNotFind, false) | |
348 | assert.Equal(test.NodeLocations, []string{"foo", "bar"}) | |
349 | } | |
350 | ||
351 | type fakeAPIClient struct { | |
352 | sentRequestPath string | |
353 | sentRequestMethod string | |
354 | sentRequestValues url.Values | |
355 | fixture string | |
356 | } | |
357 | ||
358 | func (c *fakeAPIClient) put(path string, v url.Values) (*http.Response, error) { | |
359 | return c.all("PUT", path, v) | |
360 | } | |
361 | ||
362 | func (c *fakeAPIClient) delete(path string, v url.Values) (*http.Response, error) { | |
363 | return c.all("DELETE", path, v) | |
364 | } | |
365 | ||
366 | func (c *fakeAPIClient) get(path string, v url.Values) (*http.Response, error) { | |
367 | return c.all("GET", path, v) | |
368 | } | |
369 | ||
370 | func (c *fakeAPIClient) all(method string, path string, v url.Values) (*http.Response, error) { | |
371 | c.sentRequestMethod = method | |
372 | c.sentRequestPath = path | |
373 | c.sentRequestValues = v | |
374 | ||
375 | p := filepath.Join("fixtures", c.fixture) | |
376 | f, err := os.Open(p) | |
377 | if err != nil { | |
378 | log.Fatal(err) | |
379 | } | |
380 | ||
381 | var resp *http.Response | |
382 | if len(c.sentRequestValues.Get("tags")) > 0 { | |
383 | var storedResponses []Test | |
384 | var returnResponses []Test | |
385 | byteValue, _ := ioutil.ReadAll(f) | |
386 | json.Unmarshal(byteValue, &storedResponses) | |
387 | requestedTags := strings.Split(c.sentRequestValues.Get("tags"), ",") | |
388 | ||
389 | for _, storedResponse := range storedResponses { | |
390 | if len(requestedTags) > len(storedResponse.TestTags) { // if we are requesting more tags than whats stored then there are no matches | |
391 | continue | |
392 | } | |
393 | ||
394 | match := true | |
395 | for i, tag := range requestedTags { | |
396 | if tag != storedResponse.TestTags[i] { | |
397 | match = false | |
398 | } | |
399 | } | |
400 | ||
401 | if match { // we can add it to the response now | |
402 | returnResponses = append(returnResponses, storedResponse) | |
403 | } | |
404 | } | |
405 | ||
406 | if len(returnResponses) == 0 { | |
407 | return nil, nil | |
408 | } | |
409 | ||
410 | newByteValue, _ := json.Marshal(&returnResponses) | |
411 | resp = &http.Response{ | |
412 | Body: ioutil.NopCloser(bytes.NewBuffer(newByteValue)), | |
413 | } | |
414 | ||
415 | } else { | |
416 | resp = &http.Response{ | |
417 | Body: f, | |
418 | } | |
419 | } | |
420 | ||
421 | return resp, nil | |
422 | } |