blob: 846aa9867775c686ca1ab26dd0d11a065aa4fe09 [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
Joey Armstrong9cdee9f2024-01-03 04:56:14 -05002 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
Scott Baker2c1c4822019-10-16 11:02:41 -07003 *
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
Neha Sharma94f16a92020-06-26 04:17:55 +000075 p.RegisterService(context.Background(), "one")
Scott Baker2c1c4822019-10-16 11:02:41 -070076
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
Neha Sharma94f16a92020-06-26 04:17:55 +000086 p.RegisterService(context.Background(), "one", "two", "three", "four")
Scott Baker2c1c4822019-10-16 11:02:41 -070087
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000102 ctx := context.Background()
103 p.RegisterService(ctx, "one")
104 p.RegisterService(ctx, "two")
105 p.RegisterService(ctx, "three", "four")
Scott Baker2c1c4822019-10-16 11:02:41 -0700106
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
Neha Sharma94f16a92020-06-26 04:17:55 +0000122 p.RegisterService(context.Background(), "one", "one", "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700123
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000134 ctx := context.Background()
135 p.RegisterService(ctx, "one")
136 p.RegisterService(ctx, "one")
137 p.RegisterService(ctx, "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700138
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000149 ctx := context.Background()
150 p.RegisterService(ctx, "one", "two")
151 p.UpdateStatus(ctx, "one", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700152
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000159 ctx := context.Background()
160 p.RegisterService(ctx, "one", "two")
161 p.UpdateStatus(ctx, "one", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700162
163 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set")
164 assert.Equal(t, ServiceStatusUnknown, p.status["two"], "status set")
165
Neha Sharma94f16a92020-06-26 04:17:55 +0000166 p.RegisterService(ctx, "one", "three")
Scott Baker2c1c4822019-10-16 11:02:41 -0700167 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)
Neha Sharma94f16a92020-06-26 04:17:55 +0000175 p.RegisterService(context.Background(), "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700176
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)
Neha Sharma94f16a92020-06-26 04:17:55 +0000204 p.RegisterService(context.Background(), "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700205
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000215 p.RegisterService(context.Background(), "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700216
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{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000236 ctx := context.Background()
237 p.RegisterService(ctx, "one", "two")
238 p.UpdateStatus(ctx, "one", ServiceStatusRunning)
239 p.UpdateStatus(ctx, "two", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700240
241 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
242 w := httptest.NewRecorder()
243 p.readzFunc(w, req)
244 resp := w.Result()
245 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code")
246}
247
248func TestReadzWithServicesDefaultOne(t *testing.T) {
249 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000250 p.RegisterService(context.Background(), "one", "two")
251 p.UpdateStatus(context.Background(), "one", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700252
253 req := httptest.NewRequest("GET", "http://example.com/readz", nil)
254 w := httptest.NewRecorder()
255 p.readzFunc(w, req)
256 resp := w.Result()
257 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
258}
259
260func TestHealthzNoServices(t *testing.T) {
261 p := (&Probe{}).WithReadyFunc(AlwaysTrue)
262 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
263 w := httptest.NewRecorder()
264 p.healthzFunc(w, req)
265 resp := w.Result()
266
267 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code for no services")
268}
269
270func TestHealthzWithServicesWithTrue(t *testing.T) {
271 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysTrue)
Neha Sharma94f16a92020-06-26 04:17:55 +0000272 p.RegisterService(context.Background(), "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700273
274 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
275 w := httptest.NewRecorder()
276 p.healthzFunc(w, req)
277 resp := w.Result()
278 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for registered only services")
279}
280
281func TestHealthzWithServicesWithDefault(t *testing.T) {
282 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000283 p.RegisterService(context.Background(), "one", "two")
Scott Baker2c1c4822019-10-16 11:02:41 -0700284
285 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
286 w := httptest.NewRecorder()
287 p.healthzFunc(w, req)
288 resp := w.Result()
289 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code for registered only services")
290}
291
292func TestHealthzNoServicesDefault(t *testing.T) {
293 p := &Probe{}
294
295 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
296 w := httptest.NewRecorder()
297 p.healthzFunc(w, req)
298 resp := w.Result()
299 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
300}
301
302func TestHealthzWithServicesDefault(t *testing.T) {
303 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000304 p.RegisterService(context.Background(), "one", "two")
305 p.UpdateStatus(context.Background(), "one", ServiceStatusRunning)
306 p.UpdateStatus(context.Background(), "two", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700307
308 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
309 w := httptest.NewRecorder()
310 p.healthzFunc(w, req)
311 resp := w.Result()
312 assert.Equal(t, http.StatusOK, resp.StatusCode, "invalid status code")
313}
314
315func TestHealthzWithServicesDefaultFailed(t *testing.T) {
316 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000317 p.RegisterService(context.Background(), "one", "two")
318 p.UpdateStatus(context.Background(), "one", ServiceStatusFailed)
Scott Baker2c1c4822019-10-16 11:02:41 -0700319
320 req := httptest.NewRequest("GET", "http://example.com/healthz", nil)
321 w := httptest.NewRecorder()
322 p.healthzFunc(w, req)
323 resp := w.Result()
324 assert.Equal(t, http.StatusTeapot, resp.StatusCode, "invalid status code")
325}
326
327func TestSetFuncsToNil(t *testing.T) {
328 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
329 p.WithReadyFunc(nil).WithHealthFunc(nil)
330 assert.Nil(t, p.readyFunc, "ready func not reset to nil")
331 assert.Nil(t, p.healthFunc, "health func not reset to nil")
332}
333
Scott Baker104b67d2019-10-29 15:56:27 -0700334func TestGetProbeFromContext(t *testing.T) {
335 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000336 p.RegisterService(context.Background(), "one")
Scott Baker104b67d2019-10-29 15:56:27 -0700337 ctx := context.WithValue(context.Background(), ProbeContextKey, p)
338 pc := GetProbeFromContext(ctx)
339 assert.Equal(t, p, pc, "Probe from context was not identical to original probe")
340}
341
342func TestGetProbeFromContextMssing(t *testing.T) {
npujar5bf737f2020-01-16 19:35:25 +0530343 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
344 defer cancel()
Scott Baker104b67d2019-10-29 15:56:27 -0700345 pc := GetProbeFromContext(ctx)
346 assert.Nil(t, pc, "Context had a non-nil probe when it should have been nil")
347}
348
Scott Baker2c1c4822019-10-16 11:02:41 -0700349func TestUpdateStatusFromContext(t *testing.T) {
350 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000351 p.RegisterService(context.Background(), "one")
Scott Baker2c1c4822019-10-16 11:02:41 -0700352 ctx := context.WithValue(context.Background(), ProbeContextKey, p)
353 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
354
355 assert.Equal(t, 1, len(p.status), "wrong number of services")
356 _, ok := p.status["one"]
357 assert.True(t, ok, "unable to find registered service")
358 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set correctly from context")
Scott Baker2c1c4822019-10-16 11:02:41 -0700359}
360
361func TestUpdateStatusFromNilContext(t *testing.T) {
362 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000363 p.RegisterService(context.Background(), "one")
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800364 // nolint: staticcheck
Scott Baker2c1c4822019-10-16 11:02:41 -0700365 UpdateStatusFromContext(nil, "one", ServiceStatusRunning)
366
367 assert.Equal(t, 1, len(p.status), "wrong number of services")
368 _, ok := p.status["one"]
369 assert.True(t, ok, "unable to find registered service")
370 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
371
372}
373
374func TestUpdateStatusFromContextWithoutProbe(t *testing.T) {
375 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000376 p.RegisterService(context.Background(), "one")
npujar5bf737f2020-01-16 19:35:25 +0530377 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
378 defer cancel()
Scott Baker2c1c4822019-10-16 11:02:41 -0700379 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
380
381 assert.Equal(t, 1, len(p.status), "wrong number of services")
382 _, ok := p.status["one"]
383 assert.True(t, ok, "unable to find registered service")
384 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
385
386}
387
388func TestUpdateStatusFromContextWrongType(t *testing.T) {
389 p := &Probe{}
Neha Sharma94f16a92020-06-26 04:17:55 +0000390 p.RegisterService(context.Background(), "one")
Scott Baker2c1c4822019-10-16 11:02:41 -0700391 ctx := context.WithValue(context.Background(), ProbeContextKey, "Teapot")
392 UpdateStatusFromContext(ctx, "one", ServiceStatusRunning)
393
394 assert.Equal(t, 1, len(p.status), "wrong number of services")
395 _, ok := p.status["one"]
396 assert.True(t, ok, "unable to find registered service")
397 assert.Equal(t, ServiceStatusUnknown, p.status["one"], "status not set correctly from context")
398}
399
400func TestUpdateStatusNoRegistered(t *testing.T) {
401 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
402
Neha Sharma94f16a92020-06-26 04:17:55 +0000403 p.UpdateStatus(context.Background(), "one", ServiceStatusRunning)
Scott Baker2c1c4822019-10-16 11:02:41 -0700404 assert.Equal(t, 1, len(p.status), "wrong number of services")
405 _, ok := p.status["one"]
406 assert.True(t, ok, "unable to find registered service")
407 assert.Equal(t, ServiceStatusRunning, p.status["one"], "status not set correctly from context")
408}
Scott Baker104b67d2019-10-29 15:56:27 -0700409
410func TestIsReadyTrue(t *testing.T) {
411 p := (&Probe{}).WithReadyFunc(AlwaysTrue).WithHealthFunc(AlwaysFalse)
412
Neha Sharma94f16a92020-06-26 04:17:55 +0000413 p.RegisterService(context.Background(), "SomeService")
Scott Baker104b67d2019-10-29 15:56:27 -0700414
415 assert.True(t, p.IsReady(), "IsReady should have been true")
416}
417
418func TestIsReadyFalse(t *testing.T) {
419 p := (&Probe{}).WithReadyFunc(AlwaysFalse).WithHealthFunc(AlwaysFalse)
420
Neha Sharma94f16a92020-06-26 04:17:55 +0000421 p.RegisterService(context.Background(), "SomeService")
Scott Baker104b67d2019-10-29 15:56:27 -0700422
423 assert.False(t, p.IsReady(), "IsReady should have been false")
424}
425
426func TestGetStatus(t *testing.T) {
427 p := &Probe{}
428
Neha Sharma94f16a92020-06-26 04:17:55 +0000429 p.RegisterService(context.Background(), "one", "two")
430 p.UpdateStatus(context.Background(), "one", ServiceStatusRunning)
Scott Baker104b67d2019-10-29 15:56:27 -0700431
432 ss := p.GetStatus("one")
433 assert.Equal(t, ServiceStatusRunning, ss, "Service status should have been ServiceStatusRunning")
434}
435
436func TestGetStatusMissingService(t *testing.T) {
437 p := &Probe{}
438
Neha Sharma94f16a92020-06-26 04:17:55 +0000439 p.RegisterService(context.Background(), "one", "two")
Scott Baker104b67d2019-10-29 15:56:27 -0700440
441 ss := p.GetStatus("three")
442 assert.Equal(t, ServiceStatusUnknown, ss, "Service status should have been ServiceStatusUnknown")
443}