diff options
author | Jim Hahn <jrh3@att.com> | 2018-10-02 15:29:54 -0400 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2018-10-03 16:56:11 -0400 |
commit | 1bee2d248ad2cd4ec05b44fe967bc6c69aa36f6a (patch) | |
tree | b77a6a40449ac2e033f9450d65708ada3da3ba03 | |
parent | eac53deaf9aec175e36f32bef30919392227f8e5 (diff) |
Add more coverage to drools-pdp health check
Added getProperties() method to Factory, as the system properties could
not be found in the jenkins build, for some reason.
Removed Factory, as not needed for junit testing.
Change-Id: I5070b9502ae06be6995cccbb005653928591512c
Issue-ID: POLICY-1148
Signed-off-by: Jim Hahn <jrh3@att.com>
3 files changed, 439 insertions, 157 deletions
diff --git a/feature-healthcheck/pom.xml b/feature-healthcheck/pom.xml index 17a5053a..1fc853e8 100644 --- a/feature-healthcheck/pom.xml +++ b/feature-healthcheck/pom.xml @@ -18,147 +18,147 @@ ============LICENSE_END========================================================= --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.policy.drools-pdp</groupId> - <artifactId>drools-pdp</artifactId> - <version>1.3.0-SNAPSHOT</version> - </parent> - - <artifactId>feature-healthcheck</artifactId> - - <name>feature-healthcheck</name> - <description>Loadable module that performs remote system healthchecks</description> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.3.0-SNAPSHOT</version> + </parent> + + <artifactId>feature-healthcheck</artifactId> + + <name>feature-healthcheck</name> + <description>Loadable module that performs remote system healthchecks</description> - <properties> - <maven.compiler.source>1.8</maven.compiler.source> - <maven.compiler.target>1.8</maven.compiler.target> - </properties> + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> - <build> - <plugins> - <plugin> - <artifactId>maven-assembly-plugin</artifactId> - <executions> - <execution> - <id>zipfile</id> - <goals> - <goal>single</goal> - </goals> - <phase>package</phase> - <configuration> - <attach>true</attach> - <finalName>${project.artifactId}-${project.version}</finalName> - <descriptors> - <descriptor>src/assembly/assemble_zip.xml</descriptor> - </descriptors> - <appendAssemblyId>false</appendAssemblyId> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <executions> - <execution> - <id>copy-dependencies</id> - <goals> - <goal>copy-dependencies</goal> - </goals> - <phase>prepare-package</phase> - <configuration> - <transitive>false</transitive> - <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory> - <overWriteReleases>false</overWriteReleases> - <overWriteSnapshots>true</overWriteSnapshots> - <overWriteIfNewer>true</overWriteIfNewer> - <useRepositoryLayout>false</useRepositoryLayout> - <addParentPoms>false</addParentPoms> - <copyPom>false</copyPom> - <includeScope>runtime</includeScope> - <excludeTransitive>true</excludeTransitive> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <artifactId>maven-checkstyle-plugin</artifactId> - <executions> - <execution> - <id>onap-java-style</id> - <goals> - <goal>check</goal> - </goals> - <phase>process-sources</phase> - <configuration> - <!-- Use Google Java Style Guide: https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml - with minor changes --> - <configLocation>onap-checkstyle/onap-java-style.xml</configLocation> - <!-- <sourceDirectory> is needed so that checkstyle ignores the generated sources directory --> - <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory> - <includeResources>true</includeResources> - <includeTestSourceDirectory>true</includeTestSourceDirectory> - <includeTestResources>true</includeTestResources> - <excludes> - </excludes> - <suppressionsLocation>${project.baseUri}checkstyle-suppressions.xml</suppressionsLocation> - <consoleOutput>true</consoleOutput> - <failsOnViolation>true</failsOnViolation> - <violationSeverity>warning</violationSeverity> - </configuration> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.onap.oparent</groupId> - <artifactId>checkstyle</artifactId> - <version>${oparent.version}</version> - <scope>compile</scope> - </dependency> - </dependencies> - </plugin> - </plugins> - </build> + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>zipfile</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${project.artifactId}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>false</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeScope>runtime</includeScope> + <excludeTransitive>true</excludeTransitive> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-checkstyle-plugin</artifactId> + <executions> + <execution> + <id>onap-java-style</id> + <goals> + <goal>check</goal> + </goals> + <phase>process-sources</phase> + <configuration> + <!-- Use Google Java Style Guide: https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml + with minor changes --> + <configLocation>onap-checkstyle/onap-java-style.xml</configLocation> + <!-- <sourceDirectory> is needed so that checkstyle ignores the generated sources directory --> + <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory> + <includeResources>true</includeResources> + <includeTestSourceDirectory>true</includeTestSourceDirectory> + <includeTestResources>true</includeTestResources> + <excludes> + </excludes> + <suppressionsLocation>${project.baseUri}checkstyle-suppressions.xml</suppressionsLocation> + <consoleOutput>true</consoleOutput> + <failsOnViolation>true</failsOnViolation> + <violationSeverity>warning</violationSeverity> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.onap.oparent</groupId> + <artifactId>checkstyle</artifactId> + <version>${oparent.version}</version> + <scope>compile</scope> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> - <dependencies> - <dependency> - <groupId>io.swagger</groupId> - <artifactId>swagger-jersey2-jaxrs</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.drools-pdp</groupId> - <artifactId>policy-core</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.common</groupId> - <artifactId>policy-endpoints</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.drools-pdp</groupId> - <artifactId>policy-management</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-api-mockito</artifactId> - <scope>test</scope> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>policy-endpoints</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheck.java b/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheck.java index 40e4f354..36444f8e 100644 --- a/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheck.java +++ b/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheck.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,7 +28,9 @@ import javax.ws.rs.core.Response; import org.onap.policy.common.capabilities.Startable; import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.endpoints.http.client.HttpClientFactory; import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory; import org.onap.policy.drools.persistence.SystemPersistence; import org.onap.policy.drools.system.PolicyEngine; import org.slf4j.Logger; @@ -168,7 +170,7 @@ public interface HealthCheck extends Startable { /** * Perform a healthcheck. - * + * * @return a report */ public Reports healthCheck(); @@ -186,17 +188,17 @@ class HealthCheckMonitor implements HealthCheck { private static Logger logger = LoggerFactory.getLogger(HealthCheckMonitor.class); /** - * attached http servers. + * Attached http servers. */ protected volatile List<HttpServletServer> servers = new ArrayList<>(); /** - * attached http clients. + * Attached http clients. */ protected volatile List<HttpClient> clients = new ArrayList<>(); /** - * healthcheck configuration. + * Healthcheck configuration. */ protected volatile Properties healthCheckProperties = null; @@ -206,14 +208,15 @@ class HealthCheckMonitor implements HealthCheck { @Override public Reports healthCheck() { Reports reports = new Reports(); - reports.setHealthy(PolicyEngine.manager.isAlive()); + boolean thisEngineIsAlive = getEngineManager().isAlive(); + reports.setHealthy(thisEngineIsAlive); HealthCheck.Report engineReport = new Report(); - engineReport.setHealthy(PolicyEngine.manager.isAlive()); + engineReport.setHealthy(thisEngineIsAlive); engineReport.setName("PDP-D"); engineReport.setUrl("self"); - engineReport.setCode(PolicyEngine.manager.isAlive() ? 200 : 500); - engineReport.setMessage(PolicyEngine.manager.isAlive() ? "alive" : "not alive"); + engineReport.setCode(thisEngineIsAlive ? 200 : 500); + engineReport.setMessage(thisEngineIsAlive ? "alive" : "not alive"); reports.getDetails().add(engineReport); for (HttpClient client : clients) { @@ -248,10 +251,9 @@ class HealthCheckMonitor implements HealthCheck { public boolean start() { try { - this.healthCheckProperties = - SystemPersistence.manager.getProperties(HealthCheckFeature.CONFIGURATION_PROPERTIES_NAME); - this.servers = HttpServletServer.factory.build(healthCheckProperties); - this.clients = HttpClient.factory.build(healthCheckProperties); + this.healthCheckProperties = getPersistentProperties(HealthCheckFeature.CONFIGURATION_PROPERTIES_NAME); + this.servers = getServerFactory().build(healthCheckProperties); + this.clients = getClientFactory().build(healthCheckProperties); for (HttpServletServer server : servers) { startServer(server); @@ -307,7 +309,7 @@ class HealthCheckMonitor implements HealthCheck { /** * Get servers. - * + * * @return list of attached Http Servers */ public List<HttpServletServer> getServers() { @@ -316,7 +318,7 @@ class HealthCheckMonitor implements HealthCheck { /** * Get clients. - * + * * @return list of attached Http Clients */ public List<HttpClient> getClients() { @@ -354,4 +356,21 @@ class HealthCheckMonitor implements HealthCheck { return builder.toString(); } + // the following methods may be overridden by junit tests + + protected PolicyEngine getEngineManager() { + return PolicyEngine.manager; + } + + protected HttpServletServerFactory getServerFactory() { + return HttpServletServer.factory; + } + + protected HttpClientFactory getClientFactory() { + return HttpClient.factory; + } + + protected Properties getPersistentProperties(String propertyName) { + return SystemPersistence.manager.getProperties(propertyName); + } } diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java index 850b1edf..2bf1cca5 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java @@ -21,14 +21,28 @@ package org.onap.policy.drools.healthcheck; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.net.HttpURLConnection; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Properties; +import javax.ws.rs.core.Response; +import org.junit.Before; import org.junit.Test; +import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.endpoints.http.client.HttpClientFactory; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory; import org.onap.policy.drools.healthcheck.HealthCheck.Report; import org.onap.policy.drools.healthcheck.HealthCheck.Reports; +import org.onap.policy.drools.system.PolicyEngine; public class HealthCheckTest { @@ -36,9 +50,62 @@ public class HealthCheckTest { private static final String RPT_MSG = "report-message"; private static final String RPT_NAME = "report-name"; private static final String RPT_URL = "report-url"; + private static final String EXPECTED = "expected exception"; + + private static final String CLIENT_NAME1 = "name-a"; + private static final String CLIENT_URL1 = "url-a"; + private static final String CLIENT_NAME2 = "name-b"; + private static final String CLIENT_URL2 = "url-b"; + private static final String CLIENT_NAME3 = "name-c"; + private static final String CLIENT_URL3 = "url-c"; + + private Properties properties; + private HttpServletServerFactory servletFactory; + private HttpServletServer server1; + private HttpServletServer server2; + private HttpClientFactory clientFactory; + private HttpClient client1; + private HttpClient client2; + private HttpClient client3; + private List<HttpServletServer> servers; + private List<HttpClient> clients; + private PolicyEngine engineMgr; + private HealthCheckMonitor monitor; + + /** + * Initializes the object to be tested. + * + * @throws Exception if an error occurs + */ + @Before + public void setUp() throws Exception { + properties = new Properties(); + servletFactory = mock(HttpServletServerFactory.class); + server1 = mock(HttpServletServer.class); + server2 = mock(HttpServletServer.class); + clientFactory = mock(HttpClientFactory.class); + client1 = mock(HttpClient.class); + client2 = mock(HttpClient.class); + client3 = mock(HttpClient.class); + servers = Arrays.asList(server1, server2); + clients = Arrays.asList(client1, client2, client3); + engineMgr = mock(PolicyEngine.class); + + when(client1.getName()).thenReturn(CLIENT_NAME1); + when(client1.getBaseUrl()).thenReturn(CLIENT_URL1); + when(client2.getName()).thenReturn(CLIENT_NAME2); + when(client2.getBaseUrl()).thenReturn(CLIENT_URL2); + when(client3.getName()).thenReturn(CLIENT_NAME3); + when(client3.getBaseUrl()).thenReturn(CLIENT_URL3); + when(servletFactory.build(properties)).thenReturn(servers); + when(clientFactory.build(properties)).thenReturn(clients); + when(engineMgr.isAlive()).thenReturn(true); + + monitor = new HealthCheckMonitorImpl(); + } @Test - public void testHealthCheck_Report() { + public void testReport() { Report rpt = new Report(); // toString should work with un-populated data @@ -65,7 +132,7 @@ public class HealthCheckTest { } @Test - public void testHealthCheck_Reports() { + public void testReports() { Reports reports = new Reports(); // toString should work with un-populated data @@ -86,4 +153,200 @@ public class HealthCheckTest { assertNotNull(reports.toString()); } + @Test + public void testHealthCheckMonitor_HealthCheck() { + monitor.start(); + + // first client is healthy + Response resp = mock(Response.class); + when(resp.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); + when(resp.readEntity(String.class)).thenReturn(RPT_MSG); + when(client1.get()).thenReturn(resp); + + // second client throws an exception + when(client2.get()).thenThrow(new RuntimeException(EXPECTED)); + + // third client is not healthy + resp = mock(Response.class); + when(resp.getStatus()).thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR); + when(resp.readEntity(String.class)).thenReturn(RPT_NAME); + when(client3.get()).thenReturn(resp); + + Reports reports = monitor.healthCheck(); + assertNotNull(reports); + assertEquals(4, reports.getDetails().size()); + assertFalse(reports.isHealthy()); + + int index = 0; + + Report report = reports.getDetails().get(index++); + assertEquals(true, report.isHealthy()); + assertEquals("PDP-D", report.getName()); + assertEquals("self", report.getUrl()); + assertEquals("alive", report.getMessage()); + assertEquals(HttpURLConnection.HTTP_OK, report.getCode()); + + report = reports.getDetails().get(index++); + assertEquals(true, report.isHealthy()); + assertEquals(client1.getName(), report.getName()); + assertEquals(client1.getBaseUrl(), report.getUrl()); + assertEquals(RPT_MSG, report.getMessage()); + assertEquals(HttpURLConnection.HTTP_OK, report.getCode()); + + report = reports.getDetails().get(index++); + assertEquals(false, report.isHealthy()); + assertEquals(client2.getName(), report.getName()); + assertEquals(client2.getBaseUrl(), report.getUrl()); + + report = reports.getDetails().get(index++); + assertEquals(false, report.isHealthy()); + assertEquals(client3.getName(), report.getName()); + assertEquals(client3.getBaseUrl(), report.getUrl()); + assertEquals(RPT_NAME, report.getMessage()); + assertEquals(HttpURLConnection.HTTP_INTERNAL_ERROR, report.getCode()); + + // indicate that engine is no longer healthy and re-run health check + when(engineMgr.isAlive()).thenReturn(false); + + reports = monitor.healthCheck(); + report = reports.getDetails().get(0); + + assertEquals(false, report.isHealthy()); + assertEquals("not alive", report.getMessage()); + assertEquals(500, report.getCode()); + } + + @Test + public void testHealthCheckMonitor_Start() { + // arrange for one server to throw an exception + when(server1.start()).thenThrow(new RuntimeException(EXPECTED)); + + assertTrue(monitor.start()); + + verify(server1).start(); + verify(server2).start(); + + /* + * Generate exception during building. + */ + + // new monitor + monitor = new HealthCheckMonitorImpl() { + @Override + protected HttpServletServerFactory getServerFactory() { + throw new RuntimeException(EXPECTED); + } + }; + + assertFalse(monitor.start()); + } + + @Test + public void testHealthCheckMonitor_Stop() { + monitor.start(); + + // arrange for one server and one client to throw an exception + when(server1.stop()).thenThrow(new RuntimeException(EXPECTED)); + when(client2.stop()).thenThrow(new RuntimeException(EXPECTED)); + + assertTrue(monitor.stop()); + + verify(server1).stop(); + verify(server2).stop(); + verify(client1).stop(); + verify(client2).stop(); + verify(client3).stop(); + } + + @Test + public void testHealthCheckMonitor_Shutdown() { + monitor.start(); + monitor.shutdown(); + + // at least one "stop" should have been called + verify(server1).stop(); + } + + @Test + public void testHealthCheckMonitor_IsAlive() { + assertFalse(monitor.isAlive()); + + monitor.start(); + assertTrue(monitor.isAlive()); + } + + @Test + public void testHealthCheckMonitor_GetServers_GetClients() { + monitor.start(); + assertEquals(servers, monitor.getServers()); + assertEquals(clients, monitor.getClients()); + } + + @Test + public void testHealthCheckMonitor_GetHttpBody() { + Response response = mock(Response.class); + when(response.readEntity(String.class)).thenReturn(RPT_MSG); + assertEquals(RPT_MSG, monitor.getHttpBody(response, client1)); + + // readEntity() throws an exception + when(response.readEntity(String.class)).thenThrow(new RuntimeException(EXPECTED)); + assertEquals(null, monitor.getHttpBody(response, client1)); + } + + @Test + public void testHealthCheckMonitor_StartServer() { + monitor.startServer(server1); + verify(server1).start(); + + // force start() to throw an exception - monitor should still work + when(server1.start()).thenThrow(new RuntimeException(EXPECTED)); + monitor.startServer(server1); + } + + @Test + public void testHealthCheckMonitor_ToString() { + assertTrue(monitor.toString().startsWith("HealthCheckMonitor [")); + } + + @Test + public void testHealthCheckMonitor_GetEngineManager() { + assertNotNull(new HealthCheckMonitor().getEngineManager()); + } + + @Test + public void testHealthCheckMonitor_GetServerFactory() { + assertNotNull(new HealthCheckMonitor().getServerFactory()); + } + + @Test + public void testHealthCheckMonitor_GetClientFactory() { + assertNotNull(new HealthCheckMonitor().getClientFactory()); + } + + /** + * Monitor with overrides. + */ + private class HealthCheckMonitorImpl extends HealthCheckMonitor { + + @Override + protected PolicyEngine getEngineManager() { + return engineMgr; + } + + @Override + protected HttpServletServerFactory getServerFactory() { + return servletFactory; + } + + @Override + protected HttpClientFactory getClientFactory() { + return clientFactory; + } + + @Override + protected Properties getPersistentProperties(String propertyName) { + return properties; + } + + } } |