@ohos-ports/cloudnative-health 2.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1213 @@
1
+ /*
2
+ * Copyright IBM Corporation 2018
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
+ */
16
+
17
+ import { should, expect } from 'chai';
18
+ import { HealthChecker, State, Plugin, StartupCheck, ReadinessCheck, LivenessCheck, ShutdownCheck, PingCheck } from '../../index';
19
+ import { HealthStatus } from '../../src/healthcheck/HealthChecker';
20
+ import * as http from 'http';
21
+ should();
22
+
23
+ let mockServer: http.Server;
24
+ before((done) => {
25
+ mockServer = http.createServer((req, res) => {
26
+ res.writeHead(200);
27
+ res.end();
28
+ });
29
+ mockServer.listen(3000, done);
30
+ });
31
+ after((done) => {
32
+ if (mockServer) {
33
+ mockServer.close(done);
34
+ } else {
35
+ done();
36
+ }
37
+ });
38
+
39
+ describe('Health Checker test suite', () => {
40
+
41
+
42
+ it('Startup reports DOWN', async () => {
43
+ let healthCheck = new HealthChecker();
44
+ const promise = () => new Promise<void>((_resolve, _reject) => {
45
+ throw new Error("Startup Failure");
46
+ });
47
+ let check = new StartupCheck("check", promise);
48
+
49
+ await healthCheck.registerStartupCheck(check);
50
+ const status = await healthCheck.getStatus();
51
+ const result = status.status;
52
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`);
53
+ });
54
+
55
+ it('Startup reports UP', async () => {
56
+ let healthCheck = new HealthChecker();
57
+ // tslint:disable-next-line:no-shadowed-variable
58
+ const promise = () => new Promise<void>((resolve, _reject) => {
59
+ resolve();
60
+ });
61
+ let check = new StartupCheck("check", promise);
62
+ await healthCheck.registerStartupCheck(check);
63
+ const status = await healthCheck.getStatus();
64
+ const result = status.status;
65
+ expect(result).to.equal(State.UP, `Should return: ${State.UP} , but returned: ${result}`);
66
+ });
67
+
68
+ it('Startup reports STARTING when first is starting and second is up', async () => {
69
+ let healthCheck = new HealthChecker();
70
+
71
+ const Check1 = () => new Promise<void>((resolve, _reject) => {
72
+ setTimeout(resolve, 1000, 'foo');
73
+ });
74
+
75
+ let check1 = new StartupCheck('Check1', Check1);
76
+ healthCheck.registerStartupCheck(check1);
77
+
78
+ const Check2 = () => new Promise<void>((resolve, _reject) => {
79
+ resolve();
80
+ });
81
+
82
+ let check2 = new StartupCheck('Check2', Check2);
83
+
84
+ //don't await as the check should not be resolved or rejected -> resembles an app starting
85
+ healthCheck.registerStartupCheck(check2);
86
+ const status = await healthCheck.getStatus();
87
+ const result = status.status;
88
+ const expected = State.STARTING;
89
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
90
+ });
91
+
92
+ it('Health reports STARTING with a pending startUp check', async() => {
93
+ let healthCheck = new HealthChecker();
94
+
95
+ const Check1 = () => new Promise<void>((resolve,_reject) => {
96
+ setTimeout(resolve, 100, 'foo');
97
+ });
98
+
99
+ let startCheck = new StartupCheck('StartCheck',Check1);
100
+ healthCheck.registerStartupCheck(startCheck);
101
+ const status = await healthCheck.getStatus();
102
+ const result = status.status;
103
+ const expected = State.STARTING;
104
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
105
+ });
106
+
107
+ it('Liveness reports UP with a pending startUp check that will resolve', async() => {
108
+ let healthCheck = new HealthChecker();
109
+
110
+ const Check1 = () => new Promise<void>((resolve,_reject) => {
111
+ setTimeout(resolve, 100, 'foo');
112
+ });
113
+
114
+ let startCheck = new StartupCheck('StartCheck',Check1);
115
+ healthCheck.registerStartupCheck(startCheck);
116
+ const status = await healthCheck.getLivenessStatus();
117
+ const result = status.status;
118
+ const expected = State.UP;
119
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
120
+ });
121
+
122
+ it('Liveness reports DOWN with a pending startUp check that will fail', async() => {
123
+ let healthCheck = new HealthChecker();
124
+
125
+ const Check1 = () => new Promise<void>((_resolve,reject) => {
126
+ setTimeout(reject, 1000, 'foo');
127
+ });
128
+
129
+ let startCheck = new StartupCheck('StartCheck',Check1);
130
+ healthCheck.registerStartupCheck(startCheck);
131
+ const status = await healthCheck.getLivenessStatus();
132
+ const result = status.status;
133
+ const expected = State.DOWN;
134
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
135
+ });
136
+
137
+ it('Readiness reports UP with a pending startUp check that will resolve', async() => {
138
+ let healthCheck = new HealthChecker();
139
+
140
+ const Check1 = () => new Promise<void>((resolve,_reject) => {
141
+ setTimeout(resolve, 100, 'foo');
142
+ });
143
+
144
+ let startCheck = new StartupCheck('StartCheck',Check1);
145
+ healthCheck.registerStartupCheck(startCheck);
146
+ const status = await healthCheck.getReadinessStatus();
147
+ const result = status.status;
148
+ const expected = State.UP;
149
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
150
+ });
151
+
152
+ it('Readiness reports DOWN with a pending startUp check that will fail', async() => {
153
+ let healthCheck = new HealthChecker();
154
+
155
+ const Check1 = () => new Promise<void>((resolve,reject) => {
156
+ setTimeout(reject, 100, 'foo');
157
+ });
158
+
159
+ let startCheck = new StartupCheck('StartCheck',Check1);
160
+ healthCheck.registerStartupCheck(startCheck);
161
+ const status = await healthCheck.getReadinessStatus();
162
+ const result = status.status;
163
+ const expected = State.DOWN;
164
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
165
+ });
166
+
167
+ it('Startup reports STARTING when first is up and the second is starting', async () => {
168
+ let healthCheck = new HealthChecker();
169
+
170
+ const Check1 = () => new Promise<void>((resolve, _reject) => {
171
+ resolve();
172
+ });
173
+
174
+ let check1 = new StartupCheck('Check1', Check1);
175
+ healthCheck.registerStartupCheck(check1);
176
+
177
+ const Check2 = () => new Promise<void>((resolve, _reject) => {
178
+ setTimeout(resolve,1000,'foo');
179
+ });
180
+
181
+ let check2 = new StartupCheck('Check2', Check2);
182
+ healthCheck.registerStartupCheck(check2); //do not await as its starting but not complete
183
+ const status = await healthCheck.getStatus();
184
+ const result = status.status;
185
+ const expected = State.STARTING;
186
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
187
+ });
188
+
189
+ it('Startup reports STARTING with returned Promise', async () => { //check this bad boi
190
+ let healthCheck = new HealthChecker();
191
+
192
+ const promise = () => new Promise<void>((_resolve, _reject) => {
193
+ // tslint:disable-next-line:no-shadowed-variable no-unused-expression
194
+ new Promise((resolve, _reject) => {
195
+ setTimeout(resolve, 1000, 'foo');
196
+ });
197
+ });
198
+ let check = new StartupCheck("check", promise);
199
+ healthCheck.registerStartupCheck(check)
200
+ .then(async () => {
201
+ const status = await healthCheck.getStatus();
202
+ const result = status.status;
203
+ expect(result).to.equal(State.STARTING, `Should return: ${State.STARTING} , but returned: ${result}`);
204
+ });
205
+ });
206
+
207
+ it('Startup reports STARTING without returned Promise', async () => { //check this bad boi
208
+ let healthCheck = new HealthChecker()
209
+ const promise = () => new Promise<void>((_resolve, _reject) => {
210
+ // tslint:disable-next-line:no-unused-expression no-shadowed-variable
211
+ new Promise((resolve, _reject) => {
212
+ setTimeout(resolve, 1000, 'foo');
213
+ });
214
+ });
215
+ let check = new StartupCheck("check", promise)
216
+ healthCheck.registerStartupCheck(check)
217
+ .then(async () => {
218
+ const status = await healthCheck.getStatus();
219
+ const result = status.status;
220
+ expect(result).to.equal(State.STARTING, `Should return: ${State.STARTING} , but returned: ${result}`);
221
+ });
222
+ });
223
+
224
+ it('Startup reports STARTING when multiple checks are still starting', async () => { //check this bad boi
225
+ let healthCheck = new HealthChecker()
226
+ const promise1 = () => new Promise<void>((_resolve, _reject) => {
227
+ // tslint:disable-next-line:no-unused-expression no-shadowed-variable
228
+ new Promise((resolve, _reject) => {
229
+ setTimeout(resolve, 1000, 'foo');
230
+ });
231
+ });
232
+ let check1 = new StartupCheck("check", promise1);
233
+
234
+ const promise2 = () => new Promise<void>((_resolve, _reject) => {
235
+ // tslint:disable-next-line:no-unused-expression no-shadowed-variable
236
+ new Promise((resolve, _reject) => {
237
+ setTimeout(resolve, 100, 'foo');
238
+ });
239
+ });
240
+ let check2 = new StartupCheck("check", promise2)
241
+
242
+ healthCheck.registerStartupCheck(check1);
243
+ healthCheck.registerStartupCheck(check2)
244
+ .then(async() => {
245
+ const status = await healthCheck.getStatus()
246
+ const result = status.status
247
+ expect(result).to.equal(State.STARTING, `Should return: ${State.STARTING} , but returned: ${result}`)
248
+ });
249
+ });
250
+
251
+ it('Liveness reports DOWN if startup is DOWN', async () => {
252
+ let healthCheck = new HealthChecker();
253
+
254
+ const promiseOne = () => new Promise<void>((_resolve, _reject) => {
255
+ throw new Error("Liveness Failure");
256
+ })
257
+
258
+ let checkOne = new LivenessCheck("checkOne", promiseOne);
259
+
260
+ healthCheck.registerLivenessCheck(checkOne);
261
+
262
+ const status = await healthCheck.getLivenessStatus();
263
+ const result = status.status;
264
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`)
265
+ })
266
+
267
+ it('Startup is UP and Liveness is DOWN, calling Liveness status should report DOWN', async () => {
268
+ let healthCheck = new HealthChecker();
269
+
270
+ const LivenessPromise = () => new Promise<void>((_resolve, _reject) => {
271
+ throw new Error("error");
272
+ })
273
+
274
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
275
+ resolve();
276
+ });
277
+
278
+ let checkOne = new LivenessCheck("checkOne", LivenessPromise);
279
+ let checkTwo = new StartupCheck("checkTwo",StartupPromise);
280
+ //startup check promise is resolved so liveness should not fallback to get startupStatus
281
+
282
+ await healthCheck.registerStartupCheck(checkTwo);
283
+ healthCheck.registerLivenessCheck(checkOne);
284
+
285
+ const status = await healthCheck.getLivenessStatus();
286
+ const result = status.status;
287
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`);
288
+ });
289
+
290
+ it('Startup is UP and Liveness is DOWN, calling getStatus should report DOWN', async () => {
291
+ let healthCheck = new HealthChecker();
292
+
293
+ const LivenessPromise = () => new Promise<void>((_resolve, _reject) => {
294
+ throw new Error("error");
295
+ })
296
+
297
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
298
+ resolve();
299
+ });
300
+
301
+ let checkOne = new LivenessCheck("checkOne", LivenessPromise);
302
+ let checkTwo = new StartupCheck("checkTwo",StartupPromise);
303
+
304
+ await healthCheck.registerStartupCheck(checkTwo);
305
+ healthCheck.registerLivenessCheck(checkOne);
306
+
307
+ const status = await healthCheck.getStatus();
308
+ const result = status.status;
309
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`);
310
+ });
311
+
312
+
313
+ it('Startup is UP and Liveness is UP, calling Liveness status should report UP', async () => {
314
+ let healthCheck = new HealthChecker();
315
+
316
+ const LivenessPromise = () => new Promise<void>((resolve, _reject) => {
317
+ resolve();
318
+ })
319
+
320
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
321
+ resolve();
322
+ });
323
+
324
+ let checkOne = new LivenessCheck("checkOne", LivenessPromise);
325
+ let checkTwo = new StartupCheck("checkTwo",StartupPromise);
326
+
327
+ await healthCheck.registerStartupCheck(checkTwo);
328
+ healthCheck.registerLivenessCheck(checkOne);
329
+
330
+ const status = await healthCheck.getLivenessStatus();
331
+ const result = status.status
332
+ expect(result).to.equal(State.UP, `Should return: ${State.UP} , but returned: ${result}`)
333
+ });
334
+
335
+ it('Startup is UP and Readiness is DOWN, calling Readiness status should report DOWN', async () => {
336
+ let healthCheck = new HealthChecker();
337
+
338
+ const ReadinessPromise = () => new Promise<void>((_resolve, _reject) => {
339
+ throw new Error("error")
340
+ })
341
+
342
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
343
+ resolve();
344
+ });
345
+
346
+ let checkOne = new ReadinessCheck("checkOne", ReadinessPromise);
347
+ let checkTwo = new StartupCheck("checkTwo",StartupPromise);
348
+
349
+ await healthCheck.registerStartupCheck(checkTwo);
350
+ healthCheck.registerReadinessCheck(checkOne);
351
+
352
+ const status = await healthCheck.getReadinessStatus();
353
+ const result = status.status
354
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`)
355
+ });
356
+
357
+ it('Startup is UP and Readiness is DOWN, calling getSatus should report DOWN', async () => {
358
+ let healthcheck = new HealthChecker();
359
+
360
+ const ReadinessPromise = () => new Promise<void>((_resolve, _reject) => {
361
+ throw new Error("error")
362
+ })
363
+
364
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
365
+ resolve();
366
+ });
367
+
368
+ let checkone = new ReadinessCheck("checkone", ReadinessPromise);
369
+ let checktwo = new StartupCheck("checktwo",StartupPromise);
370
+
371
+ await healthcheck.registerStartupCheck(checktwo);
372
+ healthcheck.registerReadinessCheck(checkone);
373
+
374
+ const status = await healthcheck.getStatus();
375
+ const result = status.status
376
+ expect(result).to.equal(State.DOWN, `Should return: ${State.DOWN} , but returned: ${result}`)
377
+ });
378
+
379
+ it('Startup is UP, getStartupComplete should return true with a liveness check', async() => {
380
+ let healthcheck = new HealthChecker();
381
+
382
+ const StartupPromise = () => new Promise<void>((resolve, _reject) => {
383
+ resolve();
384
+ });
385
+
386
+ let check = new LivenessCheck("check",StartupPromise);
387
+
388
+ healthcheck.registerLivenessCheck(check);
389
+ let status = await healthcheck.getLivenessStatus();
390
+
391
+ let result = await healthcheck.getStartUpComplete();
392
+
393
+ expect(result).to.equal(true, `Should return that startupComplete is true, but returned ${result}`)
394
+ });
395
+
396
+ it('Startup is DOWN, getStartupComplete should return false with a getStatus call', async() => {
397
+ let healthcheck = new HealthChecker();
398
+
399
+ const StartupPromise = () => new Promise<void>((_resolve, _reject) => {
400
+ throw new Error("Startup failed");
401
+ });
402
+
403
+ let check = new StartupCheck("check",StartupPromise);
404
+
405
+ healthcheck.registerStartupCheck(check);
406
+ await healthcheck.getStatus();
407
+
408
+ let result = healthcheck.getStartUpComplete();
409
+
410
+ expect(result).to.equal(false, `Should return that startupComplete is false, but returned ${result}`)
411
+ });
412
+
413
+ it('Startup is DOWN and should return DOWN with a liveness check', async() => {
414
+ let healthcheck = new HealthChecker();
415
+
416
+ const StartupPromise = () => new Promise<void>((_resolve,_reject) => {
417
+ throw new Error("Startup failed");
418
+ });
419
+
420
+ const LivenessPromise = () => new Promise<void>((resolve,_reject) => {
421
+ resolve();
422
+ });
423
+
424
+ let check = new StartupCheck("check",StartupPromise);
425
+ let check2 = new ReadinessCheck("check2",LivenessPromise);
426
+
427
+ await healthcheck.registerStartupCheck(check)
428
+ healthcheck.registerLivenessCheck(check2)
429
+
430
+ let status = await healthcheck.getLivenessStatus()
431
+ let result = status.status
432
+ expect(result).to.equal(State.DOWN, `Should return ${State.DOWN} but returned ${result}`)
433
+ });
434
+
435
+ it('Health reports UP by default', async () => {
436
+ let healthcheck = new HealthChecker()
437
+ const status = await healthcheck.getStatus();
438
+ let result = status.status;
439
+ expect(result).to.equal(State.UP, `Should return: ${State.UP}, but returned: ${result}`);
440
+ });
441
+
442
+ it('Health reports UP and empty checks array no registered liveness checks', async () => {
443
+ let healthcheck = new HealthChecker()
444
+ const status = await healthcheck.getStatus();
445
+ const result = JSON.stringify(status)
446
+
447
+ let expected = "{\"status\":\"UP\",\"checks\":[]}"
448
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
449
+ });
450
+
451
+ it('Health reports UP and check result with single registered liveness check', async () => {
452
+ let healthcheck = new HealthChecker();
453
+ // tslint:disable-next-line:no-shadowed-variable
454
+ const promise = () => new Promise<void>((resolve, _reject) => {
455
+ resolve()
456
+ });
457
+ let check = new LivenessCheck("check", promise)
458
+ healthcheck.registerLivenessCheck(check)
459
+
460
+ const status = await healthcheck.getStatus();
461
+ const result = JSON.stringify(status)
462
+
463
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
464
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
465
+ })
466
+
467
+ it('Health reports UP and check result with two registered liveness checks', async () => {
468
+ let healthcheck = new HealthChecker();
469
+ // tslint:disable-next-line:no-shadowed-variable
470
+ const promiseone = () => new Promise<void>((resolve, _reject) => {
471
+ resolve()
472
+ });
473
+ let checkone = new LivenessCheck("checkone", promiseone)
474
+
475
+ // tslint:disable-next-line:no-shadowed-variable
476
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
477
+ resolve()
478
+ });
479
+ let checktwo = new LivenessCheck("checktwo", promisetwo)
480
+
481
+ healthcheck.registerLivenessCheck(checkone)
482
+ healthcheck.registerLivenessCheck(checktwo)
483
+
484
+ const status = await healthcheck.getStatus();
485
+ const result = JSON.stringify(status);
486
+
487
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"checkone\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
488
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
489
+ })
490
+
491
+ it('Health reports DOWN and check result with single failed liveness check', async () => {
492
+ let healthcheck = new HealthChecker();
493
+ const promise = () => new Promise<void>((_resolve, _reject) => {
494
+ throw new Error("Startup Failure");
495
+ });
496
+ let check = new LivenessCheck("check", promise);
497
+ healthcheck.registerLivenessCheck(check);
498
+
499
+ const status = await healthcheck.getStatus();
500
+ const result = JSON.stringify(status);
501
+
502
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Startup Failure\"}}]}"
503
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
504
+ });
505
+
506
+ it('Health reports DOWN and check result with single rejected liveness check', async () => {
507
+ let healthcheck = new HealthChecker();
508
+ const promise = () => new Promise<void>((_resolve, reject) => {
509
+ reject(new Error("Startup Failure"));
510
+ });
511
+ let check = new LivenessCheck("check", promise)
512
+ healthcheck.registerLivenessCheck(check)
513
+
514
+ const status = await healthcheck.getStatus();
515
+ const result = JSON.stringify(status)
516
+
517
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Startup Failure\"}}]}"
518
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
519
+ });
520
+
521
+ it('Health reports UP with running Liveness PingCheck', async () => {
522
+ let healthcheck = new HealthChecker();
523
+
524
+ let check = new PingCheck("localhost", "", "3000")
525
+
526
+ healthcheck.registerLivenessCheck(check)
527
+ const status = await healthcheck.getStatus();
528
+ const result = JSON.stringify(status)
529
+
530
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"PingCheck HEAD:localhost:3000/\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
531
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
532
+ });
533
+
534
+ it('Health reports DOWN with failing Liveness PingCheck', async () => {
535
+ let healthcheck = new HealthChecker();
536
+
537
+ let check = new PingCheck("not-an-address.com")
538
+
539
+ healthcheck.registerLivenessCheck(check)
540
+ const status = await healthcheck.getStatus();
541
+
542
+ let expected = 'PingCheck HEAD:not-an-address.com:80/'
543
+ const statusVal = status.status
544
+ const checksState = status.checks[0].state
545
+ const checkName = status.checks[0].name
546
+ expect(statusVal).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${statusVal}`);
547
+ expect(checksState).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${checksState}`);
548
+ expect(checkName).to.equal(expected, `Should return: ${expected}, but returned: ${checkName}`);
549
+ });
550
+
551
+ it('Health reports DOWN on second invocation of a liveness check', async () => {
552
+ let healthcheck = new HealthChecker();
553
+
554
+ let count = 0;
555
+ const promise = () => new Promise<void>((resolve, reject) => {
556
+ if (count > 0) {
557
+ reject(new Error("Liveness failure"));
558
+ } else {
559
+ count = count + 1;
560
+ resolve()
561
+ }
562
+ });
563
+
564
+ let check = new LivenessCheck("check", promise)
565
+ healthcheck.registerLivenessCheck(check)
566
+ let status = await healthcheck.getStatus();
567
+ status = await healthcheck.getStatus();
568
+ const result = JSON.stringify(status)
569
+
570
+ let expected = "{\"status\":\"\DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Liveness failure\"}}]}"
571
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
572
+ });
573
+
574
+ it('Health reports UP on second invocation of a liveness check', async () => {
575
+ let healthcheck = new HealthChecker();
576
+
577
+ let count = 0;
578
+ const promise = () => new Promise<void>((resolve, reject) => {
579
+ if (count > 0) {
580
+ resolve()
581
+ } else {
582
+ count = count + 1;
583
+ reject(new Error("Liveness failure"));
584
+ }
585
+ });
586
+
587
+ let check = new LivenessCheck("check", promise)
588
+ healthcheck.registerLivenessCheck(check)
589
+ let status = await healthcheck.getStatus();
590
+ status = await healthcheck.getStatus();
591
+ const result = JSON.stringify(status)
592
+
593
+ let expected = "{\"status\":\"\UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
594
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
595
+ });
596
+
597
+ it('Health reports DOWN and check result with one passed and one failed Liveness checks', async () => {
598
+ let healthcheck = new HealthChecker();
599
+
600
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
601
+ throw new Error("Startup Failure");
602
+ })
603
+ let checkone = new LivenessCheck("checkone", promiseone)
604
+
605
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
606
+ resolve()
607
+ });
608
+ let checktwo = new LivenessCheck("checktwo", promisetwo)
609
+
610
+ healthcheck.registerLivenessCheck(checkone)
611
+ healthcheck.registerLivenessCheck(checktwo)
612
+
613
+ const status = await healthcheck.getStatus();
614
+ const result = JSON.stringify(status);
615
+
616
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Startup Failure\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
617
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
618
+ });
619
+
620
+ it('Health reports DOWN and check result with one passed Liveness and one failed Readiness checks', async () => {
621
+ let healthcheck = new HealthChecker();
622
+
623
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
624
+ throw new Error("Readiness Failure");
625
+ })
626
+ let checkone = new ReadinessCheck("checkone", promiseone)
627
+
628
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
629
+ resolve()
630
+ });
631
+ let checktwo = new LivenessCheck("checktwo", promisetwo)
632
+
633
+ healthcheck.registerReadinessCheck(checkone)
634
+ healthcheck.registerLivenessCheck(checktwo)
635
+
636
+ const status = await healthcheck.getStatus();
637
+ const result = JSON.stringify(status);
638
+
639
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Readiness Failure\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
640
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
641
+ });
642
+
643
+ it('Readiness reports UP by default', async () => {
644
+ let healthcheck = new HealthChecker()
645
+ const status = await healthcheck.getReadinessStatus();
646
+ let result = status.status;
647
+ expect(result).to.equal(State.UP, `Should return: ${State.UP}, but returned: ${result}`);
648
+ });
649
+
650
+ it('Readiness reports UP and empty checks array no registered checks', async () => {
651
+ let healthcheck = new HealthChecker()
652
+ const status = await healthcheck.getReadinessStatus();
653
+ const result = JSON.stringify(status)
654
+
655
+ let expected = "{\"status\":\"UP\",\"checks\":[]}"
656
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
657
+ });
658
+
659
+ it('Readiness reports UP and check result with single registered check', async () => {
660
+ let healthcheck = new HealthChecker();
661
+ // tslint:disable-next-line:no-shadowed-variable
662
+ const promise = () => new Promise<void>((resolve, _reject) => {
663
+ resolve()
664
+ });
665
+ let check = new ReadinessCheck("check", promise)
666
+ healthcheck.registerReadinessCheck(check)
667
+
668
+ const status = await healthcheck.getReadinessStatus();
669
+ const result = JSON.stringify(status)
670
+
671
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
672
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
673
+ })
674
+
675
+ it('Readiness reports UP and check result with two registered checks', async () => {
676
+ let healthcheck = new HealthChecker();
677
+ // tslint:disable-next-line:no-shadowed-variable
678
+ const promiseone = () => new Promise<void>((resolve, _reject) => {
679
+ resolve()
680
+ });
681
+ let checkone = new ReadinessCheck("checkone", promiseone)
682
+
683
+ // tslint:disable-next-line:no-shadowed-variable
684
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
685
+ resolve()
686
+ });
687
+ let checktwo = new ReadinessCheck("checktwo", promisetwo)
688
+
689
+ healthcheck.registerReadinessCheck(checkone)
690
+ healthcheck.registerReadinessCheck(checktwo)
691
+
692
+ const status = await healthcheck.getReadinessStatus();
693
+ const result = JSON.stringify(status);
694
+
695
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"checkone\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
696
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
697
+ })
698
+
699
+ it('Readiness reports DOWN and check result with single failed check', async () => {
700
+ let healthcheck = new HealthChecker();
701
+ const promise = () => new Promise<void>((_resolve, _reject) => {
702
+ throw new Error("Readiness Failure");
703
+ });
704
+ let check = new ReadinessCheck("check", promise);
705
+ healthcheck.registerReadinessCheck(check);
706
+
707
+ const status = await healthcheck.getReadinessStatus();
708
+ const result = JSON.stringify(status);
709
+
710
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Readiness Failure\"}}]}"
711
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
712
+ });
713
+
714
+ it('Readiness reports DOWN and check result with single rejected check', async () => {
715
+ let healthcheck = new HealthChecker();
716
+ const promise = () => new Promise<void>((_resolve, reject) => {
717
+ reject(new Error("Readiness Failure"));
718
+ });
719
+ let check = new ReadinessCheck("check", promise)
720
+ healthcheck.registerReadinessCheck(check)
721
+
722
+ const status = await healthcheck.getReadinessStatus();
723
+ const result = JSON.stringify(status)
724
+
725
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Readiness Failure\"}}]}"
726
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
727
+ });
728
+
729
+ it('Readiness reports UP with running PingCheck', async () => {
730
+ let healthcheck = new HealthChecker();
731
+
732
+ let check = new PingCheck("localhost", "", "3000")
733
+
734
+ healthcheck.registerReadinessCheck(check)
735
+ const status = await healthcheck.getReadinessStatus();
736
+ const result = JSON.stringify(status)
737
+
738
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"PingCheck HEAD:localhost:3000/\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
739
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
740
+ });
741
+
742
+ it('Readiness reports DOWN with failing PingCheck', async () => {
743
+ let healthcheck = new HealthChecker();
744
+
745
+ let check = new PingCheck("not-an-address.com")
746
+
747
+ healthcheck.registerReadinessCheck(check)
748
+ const status = await healthcheck.getReadinessStatus();
749
+
750
+ let expected = 'PingCheck HEAD:not-an-address.com:80/'
751
+ const statusVal = status.status
752
+ const checksState = status.checks[0].state
753
+ const checkName = status.checks[0].name
754
+ expect(statusVal).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${statusVal}`);
755
+ expect(checksState).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${checksState}`);
756
+ expect(checkName).to.equal(expected, `Should return: ${expected}, but returned: ${checkName}`);
757
+ });
758
+
759
+ it('Readiness reports DOWN and check result with one passed and one failed registered checks', async () => {
760
+ let healthcheck = new HealthChecker();
761
+
762
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
763
+ throw new Error("Readiness Failure");
764
+ })
765
+ let checkone = new ReadinessCheck("checkone", promiseone)
766
+
767
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
768
+ resolve()
769
+ });
770
+ let checktwo = new ReadinessCheck("checktwo", promisetwo)
771
+
772
+ healthcheck.registerReadinessCheck(checkone)
773
+ healthcheck.registerReadinessCheck(checktwo)
774
+
775
+ const status = await healthcheck.getReadinessStatus();
776
+ const result = JSON.stringify(status);
777
+
778
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Readiness Failure\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
779
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
780
+ });
781
+
782
+ it('Readiness reports DOWN on second invocation of a readiness check', async () => {
783
+ let healthcheck = new HealthChecker();
784
+
785
+ let count = 0;
786
+ const promise = () => new Promise<void>((resolve, reject) => {
787
+ if (count > 0) {
788
+ reject(new Error("Readiness failure"));
789
+ } else {
790
+ count = count + 1;
791
+ resolve()
792
+ }
793
+ });
794
+
795
+ let check = new ReadinessCheck("check", promise)
796
+ healthcheck.registerReadinessCheck(check)
797
+ let status = await healthcheck.getReadinessStatus();
798
+ status = await healthcheck.getReadinessStatus();
799
+ const result = JSON.stringify(status)
800
+
801
+ let expected = "{\"status\":\"\DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Readiness failure\"}}]}"
802
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
803
+ });
804
+
805
+ it('Readiness reports UP on second invocation of a readiness check', async () => {
806
+ let healthcheck = new HealthChecker();
807
+
808
+ let count = 0;
809
+ const promise = () => new Promise<void>((resolve, reject) => {
810
+ if (count > 0) {
811
+ resolve()
812
+ } else {
813
+ count = count + 1;
814
+ reject(new Error("Readiness failure"));
815
+ }
816
+ });
817
+
818
+ let check = new ReadinessCheck("check", promise)
819
+ healthcheck.registerReadinessCheck(check)
820
+ let status = await healthcheck.getReadinessStatus();
821
+ status = await healthcheck.getReadinessStatus();
822
+ const result = JSON.stringify(status)
823
+
824
+ let expected = "{\"status\":\"\UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
825
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
826
+ });
827
+
828
+ it('Liveness reports UP by default', async () => {
829
+ let healthcheck = new HealthChecker()
830
+ const status = await healthcheck.getLivenessStatus();
831
+ let result = status.status;
832
+ expect(result).to.equal(State.UP, `Should return: ${State.UP}, but returned: ${result}`);
833
+ });
834
+
835
+ it('Liveness reports UP and empty checks array no registered checks', async () => {
836
+ let healthcheck = new HealthChecker()
837
+ const status = await healthcheck.getLivenessStatus();
838
+ const result = JSON.stringify(status)
839
+
840
+ let expected = "{\"status\":\"UP\",\"checks\":[]}"
841
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
842
+ });
843
+
844
+ it('Liveness reports UP and check result with single registered check', async () => {
845
+ let healthcheck = new HealthChecker();
846
+ // tslint:disable-next-line:no-shadowed-variable
847
+ const promise = () => new Promise<void>((resolve, _reject) => {
848
+ resolve()
849
+ });
850
+ let check = new LivenessCheck("check", promise)
851
+ healthcheck.registerLivenessCheck(check)
852
+
853
+ const status = await healthcheck.getLivenessStatus();
854
+ const result = JSON.stringify(status)
855
+
856
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
857
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
858
+ })
859
+
860
+ it('Liveness reports UP and check result with two registered checks', async () => {
861
+ let healthcheck = new HealthChecker();
862
+ // tslint:disable-next-line:no-shadowed-variable
863
+ const promiseone = () => new Promise<void>((resolve, _reject) => {
864
+ resolve()
865
+ });
866
+ let checkone = new LivenessCheck("checkone", promiseone)
867
+
868
+ // tslint:disable-next-line:no-shadowed-variable
869
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
870
+ resolve()
871
+ });
872
+ let checktwo = new LivenessCheck("checktwo", promisetwo)
873
+
874
+ healthcheck.registerLivenessCheck(checkone)
875
+ healthcheck.registerLivenessCheck(checktwo)
876
+
877
+ const status = await healthcheck.getLivenessStatus();
878
+ const result = JSON.stringify(status);
879
+
880
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"checkone\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
881
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
882
+ })
883
+
884
+ it('Liveness reports DOWN and check result with single failed check', async () => {
885
+ let healthcheck = new HealthChecker();
886
+ const promise = () => new Promise<void>((_resolve, _reject) => {
887
+ throw new Error("Liveness Failure");
888
+ });
889
+ let check = new LivenessCheck("check", promise);
890
+ healthcheck.registerLivenessCheck(check);
891
+
892
+ const status = await healthcheck.getLivenessStatus();
893
+ const result = JSON.stringify(status);
894
+
895
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Liveness Failure\"}}]}"
896
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
897
+ });
898
+
899
+ it('Liveness reports DOWN and check result with single rejected check', async () => {
900
+ let healthcheck = new HealthChecker();
901
+ const promise = () => new Promise<void>((_resolve, reject) => {
902
+ reject(new Error("Liveness Failure"));
903
+ });
904
+ let check = new LivenessCheck("check", promise)
905
+ healthcheck.registerLivenessCheck(check)
906
+
907
+ const status = await healthcheck.getLivenessStatus();
908
+ const result = JSON.stringify(status)
909
+
910
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Liveness Failure\"}}]}"
911
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
912
+ });
913
+
914
+ it('Liveness reports UP with running PingCheck', async () => {
915
+ let healthcheck = new HealthChecker();
916
+
917
+ let check = new PingCheck("localhost", "", "3000")
918
+
919
+ healthcheck.registerLivenessCheck(check)
920
+ const status = await healthcheck.getLivenessStatus();
921
+ const result = JSON.stringify(status)
922
+
923
+ let expected = "{\"status\":\"UP\",\"checks\":[{\"name\":\"PingCheck HEAD:localhost:3000/\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
924
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
925
+ });
926
+
927
+ it('Liveness reports DOWN with failing PingCheck', async () => {
928
+ let healthcheck = new HealthChecker();
929
+
930
+ let check = new PingCheck("not-an-address.com")
931
+
932
+ healthcheck.registerLivenessCheck(check)
933
+ const status = await healthcheck.getLivenessStatus();
934
+
935
+ let expected = 'PingCheck HEAD:not-an-address.com:80/'
936
+ const statusVal = status.status
937
+ const checksState = status.checks[0].state
938
+ const checkName = status.checks[0].name
939
+ expect(statusVal).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${statusVal}`);
940
+ expect(checksState).to.equal(State.DOWN, `Should return: ${State.DOWN}, but returned: ${checksState}`);
941
+ expect(checkName).to.equal(expected, `Should return: ${expected}, but returned: ${checkName}`);
942
+ });
943
+
944
+ it('Liveness reports DOWN and check result with one passed and one failed registered checks', async () => {
945
+ let healthcheck = new HealthChecker();
946
+
947
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
948
+ throw new Error("Liveness Failure");
949
+ })
950
+ let checkone = new LivenessCheck("checkone", promiseone)
951
+
952
+ const promisetwo = () => new Promise<void>((resolve, _reject) => {
953
+ resolve()
954
+ });
955
+ let checktwo = new LivenessCheck("checktwo", promisetwo)
956
+
957
+ healthcheck.registerLivenessCheck(checkone)
958
+ healthcheck.registerLivenessCheck(checktwo)
959
+
960
+ const status = await healthcheck.getLivenessStatus();
961
+ const result = JSON.stringify(status);
962
+
963
+ let expected = "{\"status\":\"DOWN\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Liveness Failure\"}},{\"name\":\"checktwo\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
964
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
965
+ });
966
+
967
+ it('Liveness reports DOWN on second invocation of a liveness check', async () => {
968
+ let healthcheck = new HealthChecker();
969
+
970
+ let count = 0;
971
+ const promise = () => new Promise<void>((resolve, reject) => {
972
+ if (count > 0) {
973
+ reject(new Error("Liveness failure"));
974
+ } else {
975
+ count = count + 1;
976
+ resolve()
977
+ }
978
+ });
979
+
980
+ let check = new LivenessCheck("check", promise)
981
+ healthcheck.registerLivenessCheck(check)
982
+ let status = await healthcheck.getLivenessStatus();
983
+ status = await healthcheck.getLivenessStatus();
984
+ const result = JSON.stringify(status)
985
+
986
+ let expected = "{\"status\":\"\DOWN\",\"checks\":[{\"name\":\"check\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Liveness failure\"}}]}"
987
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
988
+ });
989
+
990
+ it('Liveness reports UP on second invocation of a liveness check', async () => {
991
+ let healthcheck = new HealthChecker();
992
+
993
+ let count = 0;
994
+ const promise = () => new Promise<void>((resolve, reject) => {
995
+ if (count > 0) {
996
+ resolve()
997
+ } else {
998
+ count = count + 1;
999
+ reject(new Error("Liveness failure"));
1000
+ }
1001
+ });
1002
+
1003
+ let check = new LivenessCheck("check", promise)
1004
+ healthcheck.registerLivenessCheck(check)
1005
+ let status = await healthcheck.getLivenessStatus();
1006
+ status = await healthcheck.getLivenessStatus();
1007
+ const result = JSON.stringify(status)
1008
+
1009
+ let expected = "{\"status\":\"\UP\",\"checks\":[{\"name\":\"check\",\"state\":\"UP\",\"data\":{\"reason\":\"\"}}]}"
1010
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1011
+ });
1012
+
1013
+ it('Shutdown reports STOPPED once stopped', async () => {
1014
+ process.removeAllListeners('SIGTERM');
1015
+ let healthcheck = new HealthChecker();
1016
+ // tslint:disable-next-line:no-shadowed-variable
1017
+ const promiseone = () => new Promise<void>((resolve, _reject) => {
1018
+ setTimeout(resolve, 50);
1019
+ });
1020
+ let checkone = new ShutdownCheck("checkone", promiseone)
1021
+ healthcheck.registerShutdownCheck(checkone)
1022
+
1023
+ let result;
1024
+ await new Promise((resolve) => {
1025
+ process.once('SIGTERM', async () => {
1026
+ // Give shutdown a chance to process
1027
+ await setTimeout(async () => {
1028
+ const status = await healthcheck.getStatus()
1029
+ result = status.status;
1030
+ resolve();
1031
+ }, 100);
1032
+ });
1033
+ process.kill(process.pid, 'SIGTERM');
1034
+ });
1035
+
1036
+ const expected = State.STOPPED;
1037
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1038
+ })
1039
+
1040
+ it('Shutdown reports STOPPING whilst stopping', async () => {
1041
+ process.removeAllListeners('SIGTERM');
1042
+ let healthcheck = new HealthChecker();
1043
+
1044
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
1045
+ // tslint:disable-next-line:no-shadowed-variable no-unused-expression
1046
+ new Promise((resolve, _reject) => {
1047
+ setTimeout(resolve, 1000, 'foo');
1048
+ });
1049
+ });
1050
+
1051
+ let checkone = new ShutdownCheck("checkone", promiseone)
1052
+ healthcheck.registerShutdownCheck(checkone)
1053
+
1054
+ let result;
1055
+ await new Promise(resolve => {
1056
+ process.once('SIGTERM', async () => {
1057
+ const status = await healthcheck.getStatus();
1058
+ result = status.status;
1059
+ resolve()
1060
+ });
1061
+ process.kill(process.pid, 'SIGTERM')
1062
+ });
1063
+
1064
+ const expected = State.STOPPING;
1065
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1066
+ })
1067
+
1068
+ it('Shutdown reports STOPPED and DOWN for check for error during shutdown', async () => {
1069
+ process.removeAllListeners('SIGTERM');
1070
+ let healthcheck = new HealthChecker();
1071
+
1072
+ const promise = () => new Promise<void>((_resolve, _reject) => {
1073
+ throw new Error("Shutdown Failure");
1074
+ });
1075
+
1076
+ let checkone = new ShutdownCheck("checkone", promise)
1077
+ healthcheck.registerShutdownCheck(checkone)
1078
+
1079
+ let result;
1080
+ await new Promise(resolve => {
1081
+ process.once('SIGTERM', async () => {
1082
+ // must be wrapped in timeout to simulate a node tick to ensure "process.on('SIGTERM', this.onShutdownRequest)" have been executed
1083
+ setTimeout(async () => {
1084
+ const status = await healthcheck.getStatus();
1085
+ result = JSON.stringify(status);
1086
+ resolve();
1087
+ });
1088
+ });
1089
+ process.kill(process.pid, 'SIGTERM')
1090
+ });
1091
+
1092
+ const expected = "{\"status\":\"STOPPED\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Shutdown Failure\"}}]}";
1093
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1094
+ });
1095
+
1096
+ it('Shutdown reports STOPPED and DOWN/DOWN for check for error during shutdown', async () => {
1097
+ process.removeAllListeners('SIGTERM');
1098
+ let healthcheck = new HealthChecker();
1099
+
1100
+ const promiseone = () => new Promise<void>((_resolve, _reject) => {
1101
+ throw new Error("Shutdown Failure");
1102
+ });
1103
+ let checkone = new ShutdownCheck("checkone", promiseone)
1104
+ healthcheck.registerShutdownCheck(checkone)
1105
+
1106
+ const promisetwo = () => new Promise<void>((_resolve, _reject) => {
1107
+ throw new Error("Shutdown Failure");
1108
+ });
1109
+ let checktwo = new ShutdownCheck("checktwo", promisetwo)
1110
+ healthcheck.registerShutdownCheck(checktwo)
1111
+
1112
+ let result;
1113
+ await new Promise(resolve => {
1114
+ process.once('SIGTERM', () => {
1115
+ // must be wrapped in timeout to simulate a node tick to ensure "process.on('SIGTERM', this.onShutdownRequest)" have been executed
1116
+ setTimeout(async () => {
1117
+ const status = await healthcheck.getStatus()
1118
+ result = JSON.stringify(status);
1119
+ resolve()
1120
+ });
1121
+ });
1122
+ process.kill(process.pid, 'SIGTERM')
1123
+ });
1124
+
1125
+ let expected = "{\"status\":\"STOPPED\",\"checks\":[{\"name\":\"checkone\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Shutdown Failure\"}},{\"name\":\"checktwo\",\"state\":\"DOWN\",\"data\":{\"reason\":\"Shutdown Failure\"}}]}"
1126
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1127
+ })
1128
+
1129
+ it('Shutdown reports STOPPING and STOPPED/STOPPING for checks for one complete and one running shutdown', async () => {
1130
+ process.removeAllListeners('SIGTERM');
1131
+ let healthcheck = new HealthChecker();
1132
+
1133
+ // tslint:disable-next-line:no-shadowed-variable
1134
+ const promiseone = () => new Promise<void>((resolve, _reject) => {
1135
+ resolve()
1136
+ });
1137
+
1138
+ let checkone = new ShutdownCheck("checkone", promiseone)
1139
+ healthcheck.registerShutdownCheck(checkone)
1140
+
1141
+ const promisetwo = () => new Promise<void>((_resolve, _reject) => {
1142
+ // tslint:disable-next-line:no-shadowed-variable no-unused-expression
1143
+ new Promise((resolve, _reject) => {
1144
+ setTimeout(resolve, 1000, 'foo');
1145
+ });
1146
+ });
1147
+
1148
+ let checktwo = new ShutdownCheck("checktwo", promisetwo)
1149
+ healthcheck.registerShutdownCheck(checktwo)
1150
+
1151
+ let result
1152
+ await new Promise(resolve => {
1153
+ process.once('SIGTERM', () => {
1154
+ setTimeout(async () => {
1155
+ const status = await healthcheck.getStatus();
1156
+ result = JSON.stringify(status);
1157
+ resolve();
1158
+ });
1159
+ });
1160
+ process.kill(process.pid, 'SIGTERM');
1161
+ });
1162
+
1163
+ const expected = "{\"status\":\"STOPPING\",\"checks\":[{\"name\":\"checkone\",\"state\":\"STOPPED\",\"data\":{\"reason\":\"\"}},{\"name\":\"checktwo\",\"state\":\"STOPPING\",\"data\":{\"reason\":\"\"}}]}"
1164
+ expect(result).to.equal(expected, `Should return: ${expected}, but returned: ${result}`);
1165
+ });
1166
+ });
1167
+
1168
+ describe('Should convert any promise reject to return an error message as a string' , () => {
1169
+ {
1170
+ class foo {
1171
+ get message() {
1172
+ return "bar"
1173
+ }
1174
+ }
1175
+
1176
+ // array of errors and their expected return values when passed to promise reject
1177
+
1178
+ [
1179
+ [new Error("Readiness Failure"), "Readiness Failure"],
1180
+ [null, ""],
1181
+ [undefined, ""],
1182
+ [1, "1"],
1183
+ [new Error(), "Error"],
1184
+ [new foo(), "bar"]
1185
+ ].forEach(([err,str]) => {
1186
+
1187
+ it(`When err is ${err} should return ${str}`, async() => {
1188
+
1189
+ let healthcheck = new HealthChecker();
1190
+ const readinessPromise = () => new Promise<void>((resolve, reject) => {
1191
+ reject(err);
1192
+ });
1193
+
1194
+ let check = new ReadinessCheck("readinessCheck", readinessPromise);
1195
+ healthcheck.registerReadinessCheck(check);
1196
+ let status = await healthcheck.getReadinessStatus();
1197
+ const result = JSON.stringify(status);
1198
+
1199
+ let expected = {
1200
+ "status":"DOWN",
1201
+ "checks":
1202
+ [{
1203
+ "name":"readinessCheck",
1204
+ "state":"DOWN",
1205
+ "data": {
1206
+ "reason": str
1207
+ }
1208
+ }]
1209
+ };
1210
+ expect(result).to.equal(JSON.stringify(expected), `Should return: ${expected}, but returned: ${result}`);
1211
+ });
1212
+ })};
1213
+ });