blob: 77cd6a8e2e3c9aaff16235b05055e297a1e71f4a [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
2 * Copyright 2019-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package probe
17
18import (
19 "context"
20 "encoding/json"
Girish Kumare6f45e82020-03-20 10:46:54 +000021 "github.com/stretchr/testify/assert"
Scott Baker2c1c4822019-10-16 11:02:41 -070022 "io/ioutil"
23 "net/http"
24 "net/http/httptest"
25 "testing"
npujar5bf737f2020-01-16 19:35:25 +053026 "time"
Scott Baker2c1c4822019-10-16 11:02:41 -070027)
28
Scott Baker2c1c4822019-10-16 11:02:41 -070029func TestServiceStatusString(t *testing.T) {
30 assert.Equal(t, "Unknown", ServiceStatusUnknown.String(), "ServiceStatusUnknown")
31 assert.Equal(t, "Preparing", ServiceStatusPreparing.String(), "ServiceStatusPreparing")
32 assert.Equal(t, "Prepared", ServiceStatusPrepared.String(), "ServiceStatusPrepared")
33 assert.Equal(t, "Running", ServiceStatusRunning.String(), "ServiceStatusRunning")
34 assert.Equal(t, "Stopped", ServiceStatusStopped.String(), "ServiceStatusStopped")
35 assert.Equal(t, "Failed", ServiceStatusFailed.String(), "ServiceStatusFailed")
Scott Baker104b67d2019-10-29 15:56:27 -070036 assert.Equal(t, "NotReady", ServiceStatusNotReady.String(), "ServiceStatusNotReady")
Scott Baker2c1c4822019-10-16 11:02:41 -070037}
38
39func AlwaysTrue(map[string]ServiceStatus) bool {
40 return true
41}
42
43func AlwaysFalse(map[string]ServiceStatus) bool {
44 return false
45}
46
47func TestWithFuncs(t *testing.T) {
48 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
49
50 assert.NotNil(t, p.readyFunc, "ready func not set")
51 assert.True(t, p.readyFunc(nil), "ready func not set correctly")
52 assert.NotNil(t, p.healthFunc, "health func not set")
53 assert.False(t, p.healthFunc(nil), "health func not set correctly")
54}
55
56func TestWithReadyFuncOnly(t *testing.T) {
57 p := (&Probe{}).WithReadyFunc(AlwaysTrue)
58
59 assert.NotNil(t, p.readyFunc, "ready func not set")
60 assert.True(t, p.readyFunc(nil), "ready func not set correctly")
61 assert.Nil(t, p.healthFunc, "health func set")
62}
63
64func TestWithHealthFuncOnly(t *testing.T) {
65 p := (&Probe{}).WithHealthFunc(AlwaysTrue)
66
67 assert.Nil(t, p.readyFunc, "ready func set")
68 assert.NotNil(t, p.healthFunc, "health func not set")
69 assert.True(t, p.healthFunc(nil), "health func not set correctly")
70}
71
72func TestRegisterOneService(t *testing.T) {
73 p := &Probe{}
74
75 p.RegisterService("one")
76
77 assert.Equal(t, 1, len(p.status), "wrong number of services")
78
79 _, ok := p.status["one"]
80 assert.True(t, ok, "service not found")
81}
82
83func TestRegisterMultipleServices(t *testing.T) {
84 p := &Probe{}
85
86 p.RegisterService("one", "two", "three", "four")
87
88 assert.Equal(t, 4, len(p.status), "wrong number of services")
89
90 _, ok := p.status["one"]
91 assert.True(t, ok, "service one not found")
92 _, ok = p.status["two"]
93 assert.True(t, ok, "service two not found")
94 _, ok = p.status["three"]
95 assert.True(t, ok, "service three not found")
96 _, ok = p.status["four"]
97 assert.True(t, ok, "service four not found")
98}
99
100func TestRegisterMultipleServicesIncremental(t *testing.T) {
101 p := &Probe{}
102
103 p.RegisterService("one")
104 p.RegisterService("two")
105 p.RegisterService("three", "four")
106
107 assert.Equal(t, 4, len(p.status), "wrong number of services")
108
109 _, ok := p.status["one"]
110 assert.True(t, ok, "service one not found")
111 _, ok = p.status["two"]
112 assert.True(t, ok, "service two not found")
113 _, ok = p.status["three"]
114 assert.True(t, ok, "service three not found")
115 _, ok = p.status["four"]
116 assert.True(t, ok, "service four not found")
117}
118
119func TestRegisterMultipleServicesDuplicates(t *testing.T) {
120 p := &Probe{}
121
122 p.RegisterService("one", "one", "one", "two")
123
124 assert.Equal(t, 2, len(p.status), "wrong number of services")
125
126 _, ok := p.status["one"]
127 assert.True(t, ok, "service one not found")
128 _, ok = p.status["two"]
129 assert.True(t, ok, "service two not found")
130}
131
132func TestRegisterMultipleServicesDuplicatesIncremental(t *testing.T) {
133 p := &Probe{}
134
135 p.RegisterService("one")
136 p.RegisterService("one")
137 p.RegisterService("one", "two")
138
139 assert.Equal(t, 2, len(p.status), "wrong number of services")
140
141 _, ok := p.status["one"]
142 assert.True(t, ok, "service one not found")
143 _, ok = p.status["two"]
144 assert.True(t, ok, "service two not found")
145}
146
147func TestUpdateStatus(t *testing.T) {
148 p := &Probe{}
149
150 p.RegisterService("one", "two")
151 p.UpdateStatus("one", ServiceStatusRunning)
152
153 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set")
154 assert.Equal(t, ServiceStatusUnknown, p.status["two"], "status set")
155}
156
157func TestRegisterOverwriteStatus(t *testing.T) {
158 p := &Probe{}
159
160 p.RegisterService("one", "two")
161 p.UpdateStatus("one", ServiceStatusRunning)
162
163 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set")
164 assert.Equal(t, ServiceStatusUnknown, p.status["two"], "status set")
165
166 p.RegisterService("one", "three")
167 assert.Equal(t, 3, len(p.status), "wrong number of services")
168 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status overridden")
169 assert.Equal(t, ServiceStatusUnknown, p.status["two"], "status set")
170 assert.Equal(t, ServiceStatusUnknown, p.status["three"], "status set")
171}
172
173func TestDetailzWithServies(t *testing.T) {
174 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysTrue)
175 p.RegisterService("one", "two")
176
177 req := httptest.NewRequest("GET", "http://example.com/detailz", nil)
178 w := httptest.NewRecorder()
179 p.detailzFunc(w, req)
180 resp := w.Result()
181 body, _ := ioutil.ReadAll(resp.Body)
182
183 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for no services")
184 assert.Equal(t, "application/json", resp.Header.Get("Content-Type"), "wrong content type")
185 var vals map[string]string
186 err := json.Unmarshal(body, &vals)
187 assert.Nil(t, err, "unable to unmarshal values")
188 assert.Equal(t, "Unknown", vals["one"], "wrong value")
189 assert.Equal(t, "Unknown", vals["two"], "wrong value")
190}
191
192func TestReadzNoServices(t *testing.T) {
193 p := (&Probe{}).WithReadyFunc(AlwaysTrue)
194 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
195 w := httptest.NewRecorder()
196 p.readzFunc(w, req)
197 resp := w.Result()
198
199 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code for no services")
200}
201
202func TestReadzWithServicesWithTrue(t *testing.T) {
203 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysTrue)
204 p.RegisterService("one", "two")
205
206 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
207 w := httptest.NewRecorder()
208 p.readzFunc(w, req)
209 resp := w.Result()
210 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for registered only services")
211}
212
213func TestReadzWithServicesWithDefault(t *testing.T) {
214 p := &Probe{}
215 p.RegisterService("one", "two")
216
217 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
218 w := httptest.NewRecorder()
219 p.readzFunc(w, req)
220 resp := w.Result()
221 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code for registered only services")
222}
223
224func TestReadzNpServicesDefault(t *testing.T) {
225 p := &Probe{}
226
227 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
228 w := httptest.NewRecorder()
229 p.readzFunc(w, req)
230 resp := w.Result()
231 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
232}
233
234func TestReadzWithServicesDefault(t *testing.T) {
235 p := &Probe{}
236 p.RegisterService("one", "two")
237 p.UpdateStatus("one", ServiceStatusRunning)
238 p.UpdateStatus("two", ServiceStatusRunning)
239
240 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
241 w := httptest.NewRecorder()
242 p.readzFunc(w, req)
243 resp := w.Result()
244 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code")
245}
246
247func TestReadzWithServicesDefaultOne(t *testing.T) {
248 p := &Probe{}
249 p.RegisterService("one", "two")
250 p.UpdateStatus("one", ServiceStatusRunning)
251
252 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
253 w := httptest.NewRecorder()
254 p.readzFunc(w, req)
255 resp := w.Result()
256 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
257}
258
259func TestHealthzNoServices(t *testing.T) {
260 p := (&Probe{}).WithReadyFunc(AlwaysTrue)
261 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
262 w := httptest.NewRecorder()
263 p.healthzFunc(w, req)
264 resp := w.Result()
265
266 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code for no services")
267}
268
269func TestHealthzWithServicesWithTrue(t *testing.T) {
270 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysTrue)
271 p.RegisterService("one", "two")
272
273 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
274 w := httptest.NewRecorder()
275 p.healthzFunc(w, req)
276 resp := w.Result()
277 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for registered only services")
278}
279
280func TestHealthzWithServicesWithDefault(t *testing.T) {
281 p := &Probe{}
282 p.RegisterService("one", "two")
283
284 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
285 w := httptest.NewRecorder()
286 p.healthzFunc(w, req)
287 resp := w.Result()
288 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for registered only services")
289}
290
291func TestHealthzNoServicesDefault(t *testing.T) {
292 p := &Probe{}
293
294 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
295 w := httptest.NewRecorder()
296 p.healthzFunc(w, req)
297 resp := w.Result()
298 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
299}
300
301func TestHealthzWithServicesDefault(t *testing.T) {
302 p := &Probe{}
303 p.RegisterService("one", "two")
304 p.UpdateStatus("one", ServiceStatusRunning)
305 p.UpdateStatus("two", ServiceStatusRunning)
306
307 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
308 w := httptest.NewRecorder()
309 p.healthzFunc(w, req)
310 resp := w.Result()
311 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code")
312}
313
314func TestHealthzWithServicesDefaultFailed(t *testing.T) {
315 p := &Probe{}
316 p.RegisterService("one", "two")
317 p.UpdateStatus("one", ServiceStatusFailed)
318
319 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
320 w := httptest.NewRecorder()
321 p.healthzFunc(w, req)
322 resp := w.Result()
323 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
324}
325
326func TestSetFuncsToNil(t *testing.T) {
327 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
328 p.WithReadyFunc(nil).WithHealthFunc(nil)
329 assert.Nil(t, p.readyFunc, "ready func not reset to nil")
330 assert.Nil(t, p.healthFunc, "health func not reset to nil")
331}
332
Scott Baker104b67d2019-10-29 15:56:27 -0700333func TestGetProbeFromContext(t *testing.T) {
334 p := &Probe{}
335 p.RegisterService("one")
336 ctx := context.WithValue(context.Background(), ProbeContextKey, p)
337 pc := GetProbeFromContext(ctx)
338 assert.Equal(t, p, pc, "Probe from context was not identical to original probe")
339}
340
341func TestGetProbeFromContextMssing(t *testing.T) {
npujar5bf737f2020-01-16 19:35:25 +0530342 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
343 defer cancel()
Scott Baker104b67d2019-10-29 15:56:27 -0700344 pc := GetProbeFromContext(ctx)
345 assert.Nil(t, pc, "Context had a non-nil probe when it should have been nil")
346}
347
Scott Baker2c1c4822019-10-16 11:02:41 -0700348func TestUpdateStatusFromContext(t *testing.T) {
349 p := &Probe{}
350 p.RegisterService("one")
351 ctx := context.WithValue(context.Background(), ProbeContextKey, p)
352 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
353
354 assert.Equal(t, 1, len(p.status), "wrong number of services")
355 _, ok := p.status["one"]
356 assert.True(t, ok, "unable to find registered service")
357 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set correctly from context")
Scott Baker2c1c4822019-10-16 11:02:41 -0700358}
359
360func TestUpdateStatusFromNilContext(t *testing.T) {
361 p := &Probe{}
362 p.RegisterService("one")
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800363 // nolint: staticcheck
Scott Baker2c1c4822019-10-16 11:02:41 -0700364 UpdateStatusFromContext(nil, "one", ServiceStatusRunning)
365
366 assert.Equal(t, 1, len(p.status), "wrong number of services")
367 _, ok := p.status["one"]
368 assert.True(t, ok, "unable to find registered service")
369 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
370
371}
372
373func TestUpdateStatusFromContextWithoutProbe(t *testing.T) {
374 p := &Probe{}
375 p.RegisterService("one")
npujar5bf737f2020-01-16 19:35:25 +0530376 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
377 defer cancel()
Scott Baker2c1c4822019-10-16 11:02:41 -0700378 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
379
380 assert.Equal(t, 1, len(p.status), "wrong number of services")
381 _, ok := p.status["one"]
382 assert.True(t, ok, "unable to find registered service")
383 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
384
385}
386
387func TestUpdateStatusFromContextWrongType(t *testing.T) {
388 p := &Probe{}
389 p.RegisterService("one")
390 ctx := context.WithValue(context.Background(), ProbeContextKey, "Teapot")
391 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
392
393 assert.Equal(t, 1, len(p.status), "wrong number of services")
394 _, ok := p.status["one"]
395 assert.True(t, ok, "unable to find registered service")
396 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
397}
398
399func TestUpdateStatusNoRegistered(t *testing.T) {
400 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
401
402 p.UpdateStatus("one", ServiceStatusRunning)
403 assert.Equal(t, 1, len(p.status), "wrong number of services")
404 _, ok := p.status["one"]
405 assert.True(t, ok, "unable to find registered service")
406 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set correctly from context")
407}
Scott Baker104b67d2019-10-29 15:56:27 -0700408
409func TestIsReadyTrue(t *testing.T) {
410 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
411
412 p.RegisterService("SomeService")
413
414 assert.True(t, p.IsReady(), "IsReady should have been true")
415}
416
417func TestIsReadyFalse(t *testing.T) {
418 p := (&Probe{}).WithReadyFunc(AlwaysFalse).WithHealthFunc(AlwaysFalse)
419
420 p.RegisterService("SomeService")
421
422 assert.False(t, p.IsReady(), "IsReady should have been false")
423}
424
425func TestGetStatus(t *testing.T) {
426 p := &Probe{}
427
428 p.RegisterService("one", "two")
429 p.UpdateStatus("one", ServiceStatusRunning)
430
431 ss := p.GetStatus("one")
432 assert.Equal(t, ServiceStatusRunning, ss, "Service status should have been ServiceStatusRunning")
433}
434
435func TestGetStatusMissingService(t *testing.T) {
436 p := &Probe{}
437
438 p.RegisterService("one", "two")
439
440 ss := p.GetStatus("three")
441 assert.Equal(t, ServiceStatusUnknown, ss, "Service status should have been ServiceStatusUnknown")
442}