Removing deprecated DMAAP library
[policy/drools-pdp.git] / feature-healthcheck / src / test / java / org / onap / policy / drools / healthcheck / HealthCheckManagerTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2022 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2024 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.drools.healthcheck;
23
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertNotEquals;
27 import static org.junit.jupiter.api.Assertions.assertNotNull;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29 import static org.mockito.ArgumentMatchers.anyString;
30 import static org.mockito.Mockito.doAnswer;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.never;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
35
36 import jakarta.ws.rs.core.Response;
37 import java.net.HttpURLConnection;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Properties;
43 import java.util.stream.Collectors;
44 import org.eclipse.jetty.http.HttpStatus;
45 import org.junit.jupiter.api.BeforeEach;
46 import org.junit.jupiter.api.Test;
47 import org.mockito.AdditionalAnswers;
48 import org.onap.policy.common.endpoints.http.client.HttpClient;
49 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
50 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
51 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory;
52 import org.onap.policy.drools.controller.DroolsController;
53 import org.onap.policy.drools.healthcheck.HealthCheck.Report;
54 import org.onap.policy.drools.healthcheck.HealthCheck.Reports;
55 import org.onap.policy.drools.system.PolicyController;
56 import org.onap.policy.drools.system.PolicyControllerFactory;
57 import org.onap.policy.drools.system.PolicyEngine;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 class HealthCheckManagerTest {
62
63     private static final Logger logger = LoggerFactory.getLogger(HealthCheckManagerTest.class);
64
65     protected static List<Report> select(Reports reports, String name, long code, String message) {
66         return reports.getDetails().stream()
67                 .filter(report -> name.equals(report.getName()))
68                 .filter(report -> report.getCode() == code)
69                 .filter(report -> message.equals(report.getMessage()))
70                 .collect(Collectors.toList());
71     }
72
73     private static final String RPT_MSG = "report-message";
74     private static final String RPT_NAME = "report-name";
75     private static final String EXPECTED = "expected exception";
76
77     private static final String CLIENT_NAME1 = "name-a";
78     private static final String CLIENT_URL1 = "url-a";
79     private static final String CLIENT_NAME2 = "name-b";
80     private static final String CLIENT_URL2 = "url-b";
81     private static final String CLIENT_NAME3 = "name-c";
82     private static final String CLIENT_URL3 = "url-c";
83
84     private Properties properties;
85     private HttpServletServerFactory servletFactory;
86     private HttpServletServer server1;
87     private HttpServletServer server2;
88     private HttpClientFactory clientFactory;
89     private HttpClient client1;
90     private HttpClient client2;
91     private HttpClient client3;
92
93     private PolicyControllerFactory controllerFactory;
94     private PolicyController controller1;
95     private PolicyController controller2;
96     private DroolsController drools1;
97     private DroolsController drools2;
98
99     private PolicyEngine engineMgr;
100     private HealthCheckManager monitor;
101
102     /**
103      * Initializes the object to be tested.
104      */
105     @BeforeEach
106     public void setUp() throws Exception {
107         properties = new Properties();
108         mocks();
109
110         List<HttpServletServer> servers = Arrays.asList(server1, server2);
111         List<HttpClient> clients = Arrays.asList(client1, client2, client3);
112
113         whenClients();
114
115         when(servletFactory.build(properties)).thenReturn(servers);
116         when(clientFactory.build(properties)).thenReturn(clients);
117
118         whenControllers();
119
120         when(engineMgr.isAlive()).thenReturn(true);
121
122         monitor = new HealthCheckMonitorImpl();
123     }
124
125     private void whenControllers() {
126         when(drools1.getGroupId()).thenReturn("1");
127         when(drools2.getGroupId()).thenReturn("2");
128
129         when(drools1.getArtifactId()).thenReturn("1");
130         when(drools2.getArtifactId()).thenReturn("2");
131
132         when(drools1.getVersion()).thenReturn("1");
133         when(drools2.getVersion()).thenReturn("2");
134
135         when(drools1.isAlive()).thenReturn(true);
136         when(drools2.isAlive()).thenReturn(true);
137
138         when(drools1.isBrained()).thenReturn(true);
139         when(drools2.isBrained()).thenReturn(true);
140
141         when(drools1.getSessionNames()).thenReturn(List.of("session1"));
142         when(drools2.getSessionNames()).thenReturn(List.of("session2"));
143
144         doAnswer(AdditionalAnswers
145                 .answersWithDelay(15000L, invocationOnMock -> Map.of("TIMEOUT", 1)))
146                 .when(drools1).factClassNames(anyString());
147
148         when(drools2.factClassNames(anyString()))
149                 .thenReturn(Map.of("java.lang.Integer", 2));
150
151         when(drools1.factCount("session1")).thenReturn(1L);
152         when(drools2.factCount("session2")).thenReturn(2L);
153
154         when(controller1.getDrools()).thenReturn(drools1);
155         when(controller2.getDrools()).thenReturn(drools2);
156
157         when(controller1.getName()).thenReturn("drools1");
158         when(controller2.getName()).thenReturn("drools2");
159
160         when(controller1.isAlive()).thenReturn(true);
161         when(controller2.isAlive()).thenReturn(true);
162     }
163
164     private void whenClients() {
165         when(client1.getName()).thenReturn(CLIENT_NAME1);
166         when(client1.getBaseUrl()).thenReturn(CLIENT_URL1);
167         when(client2.getName()).thenReturn(CLIENT_NAME2);
168         when(client2.getBaseUrl()).thenReturn(CLIENT_URL2);
169         when(client3.getName()).thenReturn(CLIENT_NAME3);
170         when(client3.getBaseUrl()).thenReturn(CLIENT_URL3);
171     }
172
173     private void mocks() {
174         servletFactory = mock(HttpServletServerFactory.class);
175         server1 = mock(HttpServletServer.class);
176         server2 = mock(HttpServletServer.class);
177         clientFactory = mock(HttpClientFactory.class);
178         client1 = mock(HttpClient.class);
179         client2 = mock(HttpClient.class);
180         client3 = mock(HttpClient.class);
181         controllerFactory = mock(PolicyControllerFactory.class);
182         controller1 = mock(PolicyController.class);
183         controller2 = mock(PolicyController.class);
184         drools1 = mock(DroolsController.class);
185         drools2 = mock(DroolsController.class);
186         engineMgr = mock(PolicyEngine.class);
187     }
188
189     @Test
190     void testHealthcheck() {
191         /* engine not alive */
192
193         when(engineMgr.isAlive()).thenReturn(false);
194         assertEngineDisabled(monitor.healthCheck());
195
196         /* engine alive + controllers + clients */
197
198         when(engineMgr.isAlive()).thenReturn(true);
199         assertEngineEnabled(monitor.healthCheck());
200
201         monitor.controllers = List.of(controller1, controller2);
202
203         mockClients();
204
205         var reports = monitor.healthCheck();
206         logger.info("{}", reports);
207
208         assertSummary(reports, 6, false);
209         assertClients(reports);
210         assertControllers(reports);
211     }
212
213     @Test
214     void testControllerHealthcheck() {
215         /* engine not alive */
216
217         when(engineMgr.isAlive()).thenReturn(false);
218         assertEngineDisabled(monitor.controllerHealthcheck());
219
220         /* engine alive */
221
222         when(engineMgr.isAlive()).thenReturn(true);
223         assertEngineEnabled(monitor.healthCheck());
224
225         /* engine + controllers */
226
227         monitor.controllers = List.of(controller1, controller2);
228         var reports = monitor.healthCheck();
229         logger.info("{}", reports);
230
231         assertSummary(reports, 3, false);
232
233         assertReport(reports, true,
234                 HealthCheckManager.ENGINE_NAME, "engine",
235                 HealthCheckManager.SUCCESS_CODE,
236                 HealthCheckManager.ENABLED_MESSAGE);
237
238         assertControllers(reports);
239
240         /* with argument */
241
242         reports = monitor.controllerHealthcheck(controller1);
243         logger.info("{}", reports);
244
245         reports = monitor.controllerHealthcheck(controller2);
246         logger.info("{}", reports);
247
248         assertSummary(reports, 2, true);
249     }
250
251     @Test
252     void testClientHealthcheck() {
253         /* engine not alive */
254
255         when(engineMgr.isAlive()).thenReturn(false);
256         assertEngineDisabled(monitor.clientHealthcheck());
257
258         /* engine alive */
259
260         when(engineMgr.isAlive()).thenReturn(true);
261         assertEngineEnabled(monitor.clientHealthcheck());
262
263         /* engine alive + clients */
264
265         mockClients();
266
267         var reports = monitor.clientHealthcheck();
268         logger.info("{}", reports);
269
270         assertSummary(reports, 4, false);
271         assertClients(reports);
272
273         /* with argument */
274
275         reports = monitor.clientHealthcheck(client1);
276         logger.info("{}", reports);
277
278         assertSummary(reports, 2, true);
279     }
280
281     @Test
282     void reportOnController() {
283
284         /* controller not alive */
285
286         when(controller1.isAlive()).thenReturn(false);
287
288         var reports = monitor.controllerHealthcheck(controller1);
289         assertSummary(reports, 2, false);
290         assertReport(reports, true,
291                 HealthCheckManager.ENGINE_NAME, "engine",
292                 HealthCheckManager.SUCCESS_CODE,
293                 HealthCheckManager.ENABLED_MESSAGE);
294         assertReport(reports, false,
295                     controller1.getName(), controller1.getName(),
296                     HealthCheckManager.DISABLED_CODE, HealthCheckManager.DISABLED_MESSAGE);
297
298         /* drools not brained */
299
300         when(controller1.isAlive()).thenReturn(true);
301         when(drools1.isBrained()).thenReturn(false);
302
303         reports = monitor.controllerHealthcheck(controller1);
304         logger.info("{}", reports);
305
306         assertSummary(reports, 2, true);
307         assertReport(reports, true,
308                 HealthCheckManager.ENGINE_NAME, "engine",
309                 HealthCheckManager.SUCCESS_CODE,
310                 HealthCheckManager.ENABLED_MESSAGE);
311         assertReport(reports, true,
312                 controller1.getName(), "1:1:1",
313                 HealthCheckManager.BRAINLESS_CODE, HealthCheckManager.BRAINLESS_MESSAGE);
314
315         /* drools not alive */
316
317         when(drools1.isBrained()).thenReturn(true);
318         when(drools1.isAlive()).thenReturn(false);
319
320         reports = monitor.controllerHealthcheck(controller1);
321         logger.info("{}", reports);
322
323         assertSummary(reports, 2, false);
324         assertReport(reports, true,
325                 HealthCheckManager.ENGINE_NAME, "engine",
326                 HealthCheckManager.SUCCESS_CODE,
327                 HealthCheckManager.ENABLED_MESSAGE);
328         assertReport(reports, false,
329                 controller1.getName(), "1:1:1",
330                 HealthCheckManager.DISABLED_CODE, HealthCheckManager.DISABLED_MESSAGE);
331
332         /* ok */
333
334         when(drools1.isAlive()).thenReturn(true);
335
336         assertController2(monitor.controllerHealthcheck(controller2));
337     }
338
339     @Test
340     void testReportOnUnknown() {
341         var reports = monitor.summary(monitor.engineHealthcheck(), monitor.futures(List.of(1)));
342         logger.info("{}", reports);
343
344         assertReport(reports, false,
345             HealthCheckManager.UNKNOWN_ENTITY, "java.lang.Integer",
346             HealthCheckManager.UNKNOWN_ENTITY_CODE, HealthCheckManager.UNKNOWN_ENTITY_MESSAGE);
347     }
348
349     @Test
350     void testStart() {
351         // good start
352
353         when(server1.start()).thenReturn(true);
354         when(server1.getName()).thenReturn(HealthCheckManager.HEALTHCHECK_SERVER);
355         when(server2.getName()).thenReturn(HealthCheckManager.LIVENESS_SERVER);
356         assertTrue(monitor.start());
357
358         verify(server1).start();
359         verify(server2, never()).start();
360
361         assertEquals(server1, monitor.getHealthcheckServer());
362         assertEquals(server2, monitor.getLivenessServer());
363
364         // healthcheck server start error
365
366         when(server1.start()).thenThrow(new RuntimeException(EXPECTED));
367         assertFalse(monitor.start());
368
369         /*
370          * Generate exception during building.
371          */
372
373         // new monitor
374         monitor = new HealthCheckMonitorImpl() {
375             @Override
376             protected HttpServletServerFactory getServerFactory() {
377                 throw new RuntimeException(EXPECTED);
378             }
379         };
380         assertFalse(monitor.start());
381
382     }
383
384     @Test
385     void testOpen() {
386
387         /* nothing done */
388
389         monitor.healthCheckProperties = new Properties();
390         monitor.open();
391         assertEquals(List.of(), monitor.controllers);
392
393         /* star-controllers */
394
395         monitor.livenessServer = server1;
396         monitor.healthCheckProperties = new Properties();
397         monitor.healthCheckProperties.setProperty("liveness.controllers", "*");
398         when(server1.start()).thenReturn(true);
399
400         monitor.open();
401         assertEquals(controllerFactory.inventory(), monitor.controllers);
402         verify(server1).start();
403
404         /* comma-list-controllers */
405
406         monitor.controllers = new ArrayList<>();
407         monitor.healthCheckProperties.setProperty("liveness.controllers", "controller1,controller2,controller3");
408         when(controllerFactory.get("controller1")).thenReturn(controller1);
409         when(controllerFactory.get("controller2")).thenReturn(controller2);
410         when(controllerFactory.get("controller3")).thenThrow(new RuntimeException("no controller3"));
411         monitor.open();
412         assertEquals(List.of(controller1, controller2), monitor.controllers);
413     }
414
415     @Test
416     void testShutdown() {
417         monitor.healthcheckServer = server1;
418         monitor.livenessServer = server2;
419         monitor.clients = List.of(client1, client2, client3);
420         when(server1.stop()).thenReturn(true);
421         when(server2.stop()).thenReturn(true);
422
423         monitor.shutdown();
424
425         verify(server1).stop();
426         verify(server2).stop();
427         verify(client1).stop();
428         verify(client2).stop();
429         verify(client3).stop();
430     }
431
432     @Test
433     void testIsAlive() {
434         assertFalse(monitor.isAlive());
435     }
436
437     @Test
438     void testToString() {
439         assertTrue(monitor.toString().contains("HealthCheckManager"));
440     }
441
442     private void mockClient1() {
443         // first client is healthy
444         Response resp = mock(Response.class);
445         when(resp.getStatus()).thenReturn(HttpURLConnection.HTTP_OK);
446         when(resp.readEntity(String.class)).thenReturn(RPT_MSG);
447         when(resp.getStatusInfo()).thenReturn(Response.Status.OK);
448         when(client1.get()).thenReturn(resp);
449     }
450
451     private void mockClient2() {
452         // second client throws an exception
453         when(client2.get()).thenThrow(new RuntimeException(EXPECTED));
454     }
455
456     private void mockClient3() {
457         // third client is not healthy
458         Response resp = mock(Response.class);
459         when(resp.getStatus()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
460         when(resp.readEntity(String.class)).thenReturn(RPT_NAME);
461         when(resp.getStatusInfo()).thenReturn(Response.Status.NOT_FOUND);
462         when(client3.get()).thenReturn(resp);
463     }
464
465     private void mockClients() {
466         monitor.clients = List.of(client1, client2, client3);
467
468         mockClient1();
469         mockClient2();
470         mockClient3();
471     }
472
473     private void assertEngineEnabled(Reports summary) {
474         assertEquals(1, summary.getDetails().size());
475         assertReport(summary, true, HealthCheckManager.ENGINE_NAME, "engine",
476                 HealthCheckManager.SUCCESS_CODE, HealthCheckManager.ENABLED_MESSAGE);
477     }
478
479     private void assertEngineDisabled(Reports summary) {
480         var report = summary.getDetails().get(0);
481         assertFalse(summary.isHealthy());
482         assertEquals(1, summary.getDetails().size());
483         assertFalse(report.isHealthy());
484         assertEquals(HealthCheckManager.ENGINE_NAME, report.getName());
485         assertEquals(HealthCheckManager.DISABLED_CODE, report.getCode());
486         assertEquals(HealthCheckManager.DISABLED_MESSAGE, report.getMessage());
487         assertNotEquals(0L, report.getStartTime());
488         assertNotEquals(0L, report.getEndTime());
489         assertEquals(report.getEndTime() - report.getStartTime(), report.getElapsedTime());
490     }
491
492     private void assertSummary(Reports reports, int size, boolean healthy) {
493         assertNotNull(reports);
494         assertEquals(size, reports.getDetails().size());
495         assertEquals(healthy, reports.isHealthy());
496         assertNotEquals(0L, reports.getStartTime());
497         assertNotEquals(0L, reports.getEndTime());
498         assertEquals(reports.getEndTime() - reports.getStartTime(), reports.getElapsedTime());
499     }
500
501     private void assertReport(Reports summary,
502             boolean healthy, String name, String url, long successCode, String message) {
503         var report = select(summary, name, successCode, message).get(0);
504
505         assertEquals(healthy, report.isHealthy());
506         assertEquals(name, report.getName());
507         assertEquals(url, report.getUrl());
508         assertEquals(successCode, report.getCode());
509         assertEquals(message, report.getMessage());
510         assertNotEquals(0L, report.getStartTime());
511         assertNotEquals(0L, report.getEndTime());
512         assertEquals(report.getEndTime() - report.getStartTime(), report.getElapsedTime());
513     }
514
515     private void assertClient1(Reports reports) {
516         assertReport(reports, true,
517                 client1.getName(), client1.getBaseUrl(),
518                 HttpStatus.OK_200,
519                 HttpStatus.getMessage(200));
520     }
521
522     private void assertClient2(Reports reports) {
523         assertReport(reports, false,
524                 client2.getName(), client2.getBaseUrl(),
525                 HealthCheckManager.UNREACHABLE_CODE,
526                 HealthCheckManager.UNREACHABLE_MESSAGE);
527     }
528
529     private void assertClient3(Reports reports) {
530         assertReport(reports, false,
531                 client3.getName(), client3.getBaseUrl(),
532                 HttpStatus.NOT_FOUND_404,
533                 HttpStatus.getMessage(404));
534     }
535
536     private void assertClients(Reports reports) {
537         assertReport(reports, true,
538                 HealthCheckManager.ENGINE_NAME, "engine",
539                 HealthCheckManager.SUCCESS_CODE,
540                 HealthCheckManager.ENABLED_MESSAGE);
541
542         assertClient1(reports);
543         assertClient2(reports);
544         assertClient3(reports);
545     }
546
547     private void assertController1(Reports reports) {
548         assertReport(reports, false,
549                 controller1.getName(), "1:1:1",
550                 HealthCheckManager.TIMEOUT_CODE, HealthCheckManager.TIMEOUT_MESSAGE);
551     }
552
553     private void assertController2(Reports reports) {
554         assertReport(reports, true,
555                 controller2.getName(), "2:2:2",
556                 2, "[session2:{java.lang.Integer=2}]");
557     }
558
559     private void assertControllers(Reports reports) {
560         assertReport(reports, true,
561                 HealthCheckManager.ENGINE_NAME, "engine",
562                 HealthCheckManager.SUCCESS_CODE,
563                 HealthCheckManager.ENABLED_MESSAGE);
564
565         assertController1(reports);
566         assertController2(reports);
567     }
568
569     /**
570      * Monitor with overrides.
571      */
572     private class HealthCheckMonitorImpl extends HealthCheckManager {
573
574         @Override
575         protected PolicyEngine getEngineManager() {
576             return engineMgr;
577         }
578
579         @Override
580         protected HttpServletServerFactory getServerFactory() {
581             return servletFactory;
582         }
583
584         @Override
585         protected HttpClientFactory getClientFactory() {
586             return clientFactory;
587         }
588
589         @Override
590         protected Properties getPersistentProperties() {
591             return properties;
592         }
593
594         @Override
595         protected PolicyControllerFactory getControllerFactory() {
596             return controllerFactory;
597         }
598
599     }
600 }