diff options
17 files changed, 1041 insertions, 202 deletions
diff --git a/feature-distributed-locking/pom.xml b/feature-distributed-locking/pom.xml index a7eeed6d..0c61e34c 100644 --- a/feature-distributed-locking/pom.xml +++ b/feature-distributed-locking/pom.xml @@ -119,6 +119,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> diff --git a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java index 86b5a66c..ddfe6a5a 100644 --- a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java +++ b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java @@ -134,7 +134,7 @@ public class DistributedLockingFeature implements PolicyEngineFeatureAPI, Policy * @return a new, pooled data source * @throws Exception exception */ - private BasicDataSource makeDataSource() throws Exception { + protected BasicDataSource makeDataSource() throws Exception { Properties props = new Properties(); props.put("driverClassName", lockProps.getDbDriver()); props.put("url", lockProps.getDbUrl()); diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureTest.java new file mode 100644 index 00000000..90e8bfc0 --- /dev/null +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureTest.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.distributed.locking; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.sql.SQLException; +import org.apache.commons.dbcp2.BasicDataSource; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.utils.properties.exception.PropertyException; +import org.onap.policy.drools.persistence.SystemPersistence; + +/** + * Partially tests DistributedLockingFeature; most of the methods are tested via + * {@link TargetLockTest}. + */ +public class DistributedLockingFeatureTest { + private static final String EXPECTED = "expected exception"; + + private BasicDataSource dataSrc; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + SystemPersistence.manager.setConfigurationDir("src/test/resources"); + } + + @Before + public void setUp() throws Exception { + dataSrc = mock(BasicDataSource.class); + } + + @Test + public void testGetSequenceNumber() { + assertEquals(1000, new DistributedLockingFeature().getSequenceNumber()); + } + + @Test(expected = DistributedLockingFeatureException.class) + public void testAfterStart_PropEx() { + new DistributedLockingFeatureImpl(new PropertyException("prop", "val")).afterStart(null); + } + + @Test(expected = DistributedLockingFeatureException.class) + public void testAfterStart_InterruptEx() { + new DistributedLockingFeatureImpl(new InterruptedException(EXPECTED)).afterStart(null); + } + + @Test(expected = DistributedLockingFeatureException.class) + public void testAfterStart_OtherEx() { + new DistributedLockingFeatureImpl(new RuntimeException(EXPECTED)).afterStart(null); + } + + @Test + public void testCleanLockTable() throws Exception { + when(dataSrc.getConnection()).thenThrow(new SQLException(EXPECTED)); + + new DistributedLockingFeatureImpl().afterStart(null); + } + + /** + * Feature that overrides {@link #makeDataSource()}. + */ + private class DistributedLockingFeatureImpl extends DistributedLockingFeature { + /** + * Exception to throw when {@link #makeDataSource()} is invoked. + */ + private final Exception makeEx; + + public DistributedLockingFeatureImpl() { + makeEx = null; + } + + public DistributedLockingFeatureImpl(Exception ex) { + this.makeEx = ex; + } + + @Override + protected BasicDataSource makeDataSource() throws Exception { + if (makeEx != null) { + throw makeEx; + } + + return dataSrc; + } + } +} diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java index 49f1026d..6fa1febb 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java @@ -21,12 +21,19 @@ package org.onap.policy.distributed.locking; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.UUID; import java.util.concurrent.ExecutionException; +import org.apache.commons.dbcp2.BasicDataSource; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -43,6 +50,10 @@ public class TargetLockTest { "jdbc:h2:mem:pooling;INIT=CREATE SCHEMA IF NOT EXISTS pooling\\;SET SCHEMA pooling"; private static final String DB_USER = "user"; private static final String DB_PASSWORD = "password"; + private static final String EXPECTED = "expected exception"; + private static final String MY_RESOURCE = "my-resource-id"; + private static final String MY_OWNER = "my-owner"; + private static final UUID MY_UUID = UUID.randomUUID(); private static Connection conn = null; private static DistributedLockingFeature distLockFeat; @@ -139,7 +150,64 @@ public class TargetLockTest { } @Test - public void testUpdateLock() throws InterruptedException, ExecutionException { + public void testSecondGrab_UpdateOk() throws Exception { + PreparedStatement grabLockInsert = mock(PreparedStatement.class); + when(grabLockInsert.executeUpdate()).thenThrow(new SQLException(EXPECTED)); + + PreparedStatement secondGrabUpdate = mock(PreparedStatement.class); + when(secondGrabUpdate.executeUpdate()).thenReturn(1); + + Connection connMock = mock(Connection.class); + when(connMock.prepareStatement(anyString())).thenReturn(grabLockInsert, secondGrabUpdate); + + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenReturn(connMock); + + assertTrue(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).lock(MAX_AGE_SEC)); + } + + @Test + public void testSecondGrab_UpdateFail_InsertOk() throws Exception { + PreparedStatement grabLockInsert = mock(PreparedStatement.class); + when(grabLockInsert.executeUpdate()).thenThrow(new SQLException(EXPECTED)); + + PreparedStatement secondGrabUpdate = mock(PreparedStatement.class); + when(secondGrabUpdate.executeUpdate()).thenReturn(0); + + PreparedStatement secondGrabInsert = mock(PreparedStatement.class); + when(secondGrabInsert.executeUpdate()).thenReturn(1); + + Connection connMock = mock(Connection.class); + when(connMock.prepareStatement(anyString())).thenReturn(grabLockInsert, secondGrabUpdate, secondGrabInsert); + + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenReturn(connMock); + + assertTrue(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).lock(MAX_AGE_SEC)); + } + + @Test + public void testSecondGrab_UpdateFail_InsertFail() throws Exception { + PreparedStatement grabLockInsert = mock(PreparedStatement.class); + when(grabLockInsert.executeUpdate()).thenThrow(new SQLException(EXPECTED)); + + PreparedStatement secondGrabUpdate = mock(PreparedStatement.class); + when(secondGrabUpdate.executeUpdate()).thenReturn(0); + + PreparedStatement secondGrabInsert = mock(PreparedStatement.class); + when(secondGrabInsert.executeUpdate()).thenReturn(0); + + Connection connMock = mock(Connection.class); + when(connMock.prepareStatement(anyString())).thenReturn(grabLockInsert, secondGrabUpdate, secondGrabInsert); + + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenReturn(connMock); + + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).lock(MAX_AGE_SEC)); + } + + @Test + public void testUpdateLock() throws Exception { // not locked yet - refresh should fail assertEquals( OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); @@ -160,10 +228,6 @@ public class TargetLockTest { "UPDATE pooling.locks SET expirationTime = timestampadd(second, -1, now()) WHERE resourceId = ?"); ) { updateStatement.setString(1, "resource1"); updateStatement.executeUpdate(); - - } catch (SQLException e) { - logger.error("Error in TargetLockTest.testGrabLockSuccess()", e); - throw new RuntimeException(e); } // refresh should fail now @@ -171,19 +235,29 @@ public class TargetLockTest { OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + + // test exception case + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenThrow(new SQLException(EXPECTED)); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).refresh(MAX_AGE_SEC)); } @Test - public void testUnlock() throws InterruptedException, ExecutionException { + public void testUnlock() throws Exception { distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeUnlock("resource1", "owner1")); assertEquals( OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); + + // test exception case + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenThrow(new SQLException(EXPECTED)); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).unlock()); } @Test - public void testIsActive() { + public void testIsActive() throws Exception { assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); @@ -195,10 +269,6 @@ public class TargetLockTest { "UPDATE pooling.locks SET expirationTime = timestampadd(second, -5, now()) WHERE resourceId = ?"); ) { updateStatement.setString(1, "resource1"); updateStatement.executeUpdate(); - - } catch (SQLException e) { - logger.error("Error in TargetLockTest.testIsActive()", e); - throw new RuntimeException(e); } assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); @@ -207,6 +277,20 @@ public class TargetLockTest { // Unlock record, next isActive attempt should fail distLockFeat.beforeUnlock("resource1", "owner1"); assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + + // test exception case for outer "try" + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenThrow(new SQLException(EXPECTED)); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).isActive()); + + // test exception case for inner "try" + PreparedStatement stmt = mock(PreparedStatement.class); + when(stmt.executeQuery()).thenThrow(new SQLException(EXPECTED)); + Connection connMock = mock(Connection.class); + when(connMock.prepareStatement(anyString())).thenReturn(stmt); + dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenReturn(connMock); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).isActive()); } @Test @@ -218,10 +302,24 @@ public class TargetLockTest { } @Test - public void testIsLocked() { + public void testIsLocked() throws Exception { assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLocked("resource1")); distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLocked("resource1")); + + // test exception case for outer "try" + BasicDataSource dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenThrow(new SQLException(EXPECTED)); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).isLocked()); + + // test exception case for inner "try" + PreparedStatement stmt = mock(PreparedStatement.class); + when(stmt.executeQuery()).thenThrow(new SQLException(EXPECTED)); + Connection connMock = mock(Connection.class); + when(connMock.prepareStatement(anyString())).thenReturn(stmt); + dataSrc = mock(BasicDataSource.class); + when(dataSrc.getConnection()).thenReturn(connMock); + assertFalse(new TargetLock(MY_RESOURCE, MY_UUID, MY_OWNER, dataSrc).isLocked()); } private static void getDbConnection() { diff --git a/feature-healthcheck/pom.xml b/feature-healthcheck/pom.xml index 3ed46abc..1fc853e8 100644 --- a/feature-healthcheck/pom.xml +++ b/feature-healthcheck/pom.xml @@ -18,142 +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> - </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/main/java/org/onap/policy/drools/healthcheck/HealthCheckFeature.java b/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheckFeature.java index 3a79a55c..8e7a66ef 100644 --- a/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheckFeature.java +++ b/feature-healthcheck/src/main/java/org/onap/policy/drools/healthcheck/HealthCheckFeature.java @@ -48,7 +48,7 @@ public class HealthCheckFeature implements PolicyEngineFeatureAPI { @Override public boolean afterStart(PolicyEngine engine) { try { - HealthCheck.monitor.start(); + getMonitor().start(); } catch (IllegalStateException e) { logger.error("Healthcheck Monitor cannot be started", e); } @@ -59,7 +59,7 @@ public class HealthCheckFeature implements PolicyEngineFeatureAPI { @Override public boolean afterShutdown(PolicyEngine engine) { try { - HealthCheck.monitor.stop(); + getMonitor().stop(); } catch (IllegalStateException e) { logger.error("Healthcheck Monitor cannot be stopped", e); } diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java index e0312f1f..42d77f26 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.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. @@ -21,7 +21,12 @@ package org.onap.policy.drools.healthcheck; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import java.io.File; import java.io.FileWriter; @@ -30,7 +35,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -50,11 +54,13 @@ public class HealthCheckFeatureTest { */ private static final String HEALTH_CHECK_PROPERTIES_FILE = "feature-healthcheck.properties"; - private static final Path healthCheckPropsPath = - Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), HEALTH_CHECK_PROPERTIES_FILE); + private static final Path healthCheckPropsPath = Paths + .get(SystemPersistence.manager.getConfigurationPath().toString(), HEALTH_CHECK_PROPERTIES_FILE); + + private static final Path healthCheckPropsBackupPath = Paths.get( + SystemPersistence.manager.getConfigurationPath().toString(), HEALTH_CHECK_PROPERTIES_FILE + ".bak"); - private static final Path healthCheckPropsBackupPath = Paths - .get(SystemPersistence.manager.getConfigurationPath().toString(), HEALTH_CHECK_PROPERTIES_FILE + ".bak"); + private static final String EXPECTED = "expected exception"; /** @@ -65,47 +71,47 @@ public class HealthCheckFeatureTest { private static Properties httpProperties = new Properties(); /** - * Set up. + * Set up. */ @BeforeClass public static void setup() { httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, "HEALTHCHECK"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost"); + + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, "7777"); + + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, "7777"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, "username"); + + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, "username"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, "password"); + + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, "password"); httpProperties.setProperty( - PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, - org.onap.policy.drools.healthcheck.RestMockHealthCheck.class.getName()); + PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" + + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, + org.onap.policy.drools.healthcheck.RestMockHealthCheck.class.getName()); httpProperties.setProperty( - PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, - org.onap.policy.drools.healthcheck.TestAafHealthCheckFilter.class.getName()); + PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" + + PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, + org.onap.policy.drools.healthcheck.TestAafHealthCheckFilter.class.getName()); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true"); + + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES, "HEALTHCHECK"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost"); + + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, "7777"); + + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, "7777"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_URL_SUFFIX, "healthcheck/test"); + + PolicyEndPointProperties.PROPERTY_HTTP_URL_SUFFIX, "healthcheck/test"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, "false"); + + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX, "false"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, "username"); + + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, "username"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, "password"); + + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, "password"); httpProperties.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "HEALTHCHECK" - + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true"); + + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true"); configDirSetup(); @@ -148,6 +154,41 @@ public class HealthCheckFeatureTest { } + @Test + public void testGetSequenceNumber() { + assertEquals(1000, new HealthCheckFeature().getSequenceNumber()); + } + + @Test + public void testAfterStart() { + HealthCheck checker = mock(HealthCheck.class); + HealthCheckFeature feature = new HealthCheckFeatureImpl(checker); + + // without exception + assertFalse(feature.afterStart(null)); + verify(checker).start(); + verify(checker, never()).stop(); + + // with exception + doThrow(new IllegalStateException(EXPECTED)).when(checker).start(); + assertFalse(feature.afterStart(null)); + } + + @Test + public void testAfterShutdown() { + HealthCheck checker = mock(HealthCheck.class); + HealthCheckFeature feature = new HealthCheckFeatureImpl(checker); + + // without exception + assertFalse(feature.afterShutdown(null)); + verify(checker).stop(); + verify(checker, never()).start(); + + // with exception + doThrow(new IllegalStateException(EXPECTED)).when(checker).stop(); + assertFalse(feature.afterShutdown(null)); + } + /** * setup up config directory. @@ -191,4 +232,20 @@ public class HealthCheckFeatureTest { } } + /** + * Feature that returns a particular monitor. + */ + private static class HealthCheckFeatureImpl extends HealthCheckFeature { + private final HealthCheck checker; + + public HealthCheckFeatureImpl(HealthCheck checker) { + this.checker = checker; + } + + @Override + public HealthCheck getMonitor() { + return checker; + } + + } } 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 new file mode 100644 index 00000000..2bf1cca5 --- /dev/null +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java @@ -0,0 +1,352 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +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 { + + private static final int RPT_CODE = 100; + 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 testReport() { + Report rpt = new Report(); + + // toString should work with un-populated data + assertNotNull(rpt.toString()); + + rpt.setCode(RPT_CODE); + rpt.setHealthy(true); + rpt.setMessage(RPT_MSG); + rpt.setName(RPT_NAME); + rpt.setUrl(RPT_URL); + + assertEquals(RPT_CODE, rpt.getCode()); + assertEquals(true, rpt.isHealthy()); + assertEquals(RPT_MSG, rpt.getMessage()); + assertEquals(RPT_NAME, rpt.getName()); + assertEquals(RPT_URL, rpt.getUrl()); + + // flip the flag + rpt.setHealthy(false); + assertEquals(false, rpt.isHealthy()); + + // toString should work with populated data + assertNotNull(rpt.toString()); + } + + @Test + public void testReports() { + Reports reports = new Reports(); + + // toString should work with un-populated data + assertNotNull(reports.toString()); + + List<Report> lst = Collections.emptyList(); + reports.setDetails(lst); + reports.setHealthy(true); + + assertTrue(lst == reports.getDetails()); + assertEquals(true, reports.isHealthy()); + + // flip the flag + reports.setHealthy(false); + assertEquals(false, reports.isHealthy()); + + // toString should work with populated data + 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; + } + + } +} diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java index 17d520ad..6b5828c7 100644 --- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java +++ b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java @@ -205,10 +205,12 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener { } } + @Override public String getHost() { return host; } + @Override public String getTopic() { return topic; } @@ -232,10 +234,8 @@ public class PoolingManagerImpl implements PoolingManager, TopicListener { /** * Indicates that the controller is about to start. Starts the publisher for the * internal topic, and creates a thread pool for the timers. - * - * @throws PoolingFeatureException if the internal topic publisher cannot be started */ - public void beforeStart() throws PoolingFeatureException { + public void beforeStart() { synchronized (curLocker) { if (scheduler == null) { dmaapMgr.startPublisher(); diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java index 07fc757b..a943575c 100644 --- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java +++ b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java @@ -478,11 +478,11 @@ public class PoolingFeatureTest { assertFalse(pool.beforeStart(controllerDisabled)); } - @Test(expected = PoolingFeatureRtException.class) + @Test(expected = RuntimeException.class) public void testDoManager_Ex() throws Exception { // generate exception - doThrow(new PoolingFeatureException()).when(mgr1).beforeStart(); + doThrow(new RuntimeException()).when(mgr1).beforeStart(); pool.beforeStart(controller1); } diff --git a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java index 332e2984..13264d60 100644 --- a/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java +++ b/feature-session-persistence/src/main/java/org/onap/policy/drools/persistence/PersistenceFeature.java @@ -543,8 +543,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine logger.error("Clean up of sessioninfo table failed", e); } - // TODO: delete DroolsSessionEntity where sessionId not in - // (sessinfo.xxx) + // delete DroolsSessionEntity where sessionId not in (sessinfo.xxx)? sessInfoCleaned = true; } diff --git a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java index b2dcfb52..5fbb905b 100644 --- a/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java +++ b/feature-session-persistence/src/test/java/org/onap/policy/drools/persistence/DroolsSessionEntityTest.java @@ -103,6 +103,9 @@ public class DroolsSessionEntityTest { @Test public void testEqualsObject() { DroolsSessionEntity entity = makeEnt("mynameA", 1); + + // diff object type + assertFalse(entity.equals("hello")); // reflexive assertTrue(entity.equals(entity)); diff --git a/feature-test-transaction/pom.xml b/feature-test-transaction/pom.xml index f16a50f2..2848e733 100644 --- a/feature-test-transaction/pom.xml +++ b/feature-test-transaction/pom.xml @@ -134,5 +134,10 @@ <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-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java b/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java index 956304b9..bb8a7598 100644 --- a/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java +++ b/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java @@ -40,7 +40,7 @@ public class TestTransactionFeature implements PolicyControllerFeatureAPI { logger.info("TEST_TRANSACTION FEATURE LOADED"); if (controller.isAlive() && !controller.isLocked() && controller.getDrools().isBrained()) { - TestTransaction.manager.register(controller); + getTestTransMgr().register(controller); } return false; } @@ -49,7 +49,7 @@ public class TestTransactionFeature implements PolicyControllerFeatureAPI { public boolean afterLock(PolicyController controller) { logger.info("controller {} locked", controller.getName()); - TestTransaction.manager.unregister(controller); + getTestTransMgr().unregister(controller); return false; } @@ -58,7 +58,7 @@ public class TestTransactionFeature implements PolicyControllerFeatureAPI { logger.info("controller {} unlocked", controller.getName()); if (controller.isAlive() && !controller.isLocked() && controller.getDrools().isBrained()) { - TestTransaction.manager.register(controller); + getTestTransMgr().register(controller); } return false; @@ -68,7 +68,7 @@ public class TestTransactionFeature implements PolicyControllerFeatureAPI { public boolean beforeStop(PolicyController controller) { logger.info("controller {} stopping", controller.getName()); - TestTransaction.manager.unregister(controller); + getTestTransMgr().unregister(controller); return false; } @@ -77,4 +77,12 @@ public class TestTransactionFeature implements PolicyControllerFeatureAPI { public int getSequenceNumber() { return 1000; } + + /** + * Gets the test transaction manager. + * @return the test transaction manager + */ + protected TestTransaction getTestTransMgr() { + return TestTransaction.manager; + } } diff --git a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java new file mode 100644 index 00000000..6bb09903 --- /dev/null +++ b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java @@ -0,0 +1,181 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.testtransaction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.system.PolicyController; + +public class TestTransactionFeatureTest { + + private AtomicInteger regCount; + private AtomicInteger unregCount; + private TestTransaction mgr; + private DroolsController drools; + private PolicyController ctlr; + private TestTransactionFeature feat; + + /** + * Initialize objects for each test. + */ + @Before + public void setUp() { + regCount = new AtomicInteger(0); + unregCount = new AtomicInteger(0); + mgr = mock(TestTransaction.class); + drools = mock(DroolsController.class); + ctlr = mock(PolicyController.class); + + feat = new TestTransactionFeature() { + @Override + protected TestTransaction getTestTransMgr() { + return mgr; + } + }; + + when(ctlr.getDrools()).thenReturn(drools); + + doAnswer(args -> { + regCount.incrementAndGet(); + return null; + }).when(mgr).register(ctlr); + + doAnswer(args -> { + unregCount.incrementAndGet(); + return null; + }).when(mgr).unregister(ctlr); + } + + @Test + public void testAfterStart() { + // try each combination of alive, locked, and brained + checkCombos(regCount, ctlr -> feat.afterStart(ctlr)); + } + + @Test + public void testAfterLock() { + checkSimple(unregCount, ctlr -> feat.afterLock(ctlr)); + } + + @Test + public void testAfterUnlock() { + // try each combination of alive, locked, and brained + checkCombos(regCount, ctlr -> feat.afterUnlock(ctlr)); + } + + @Test + public void testBeforeStop() { + checkSimple(unregCount, ctlr -> feat.beforeStop(ctlr)); + } + + @Test + public void testGetSequenceNumber() { + assertEquals(1000, feat.getSequenceNumber()); + } + + @Test + public void testGetTestTransMgr() { + assertNotNull(new TestTransactionFeature().getTestTransMgr()); + } + + /** + * Try each combination of alive, locked, and brained. + * + * @param counter counter to check after each invocation + * @param method method to invoke + */ + private void checkCombos(AtomicInteger counter, Function<PolicyController, Boolean> method) { + when(ctlr.isAlive()).thenReturn(true); + when(ctlr.isLocked()).thenReturn(true); + when(drools.isBrained()).thenReturn(true); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(true); + when(ctlr.isLocked()).thenReturn(true); + when(drools.isBrained()).thenReturn(false); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + // this is the only one that should cause it to register + when(ctlr.isAlive()).thenReturn(true); + when(ctlr.isLocked()).thenReturn(false); + when(drools.isBrained()).thenReturn(true); + assertFalse(method.apply(ctlr)); + assertEquals(1, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(true); + when(ctlr.isLocked()).thenReturn(false); + when(drools.isBrained()).thenReturn(false); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(false); + when(ctlr.isLocked()).thenReturn(true); + when(drools.isBrained()).thenReturn(true); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(false); + when(ctlr.isLocked()).thenReturn(true); + when(drools.isBrained()).thenReturn(false); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(false); + when(ctlr.isLocked()).thenReturn(false); + when(drools.isBrained()).thenReturn(true); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(false); + when(ctlr.isLocked()).thenReturn(false); + when(drools.isBrained()).thenReturn(false); + assertFalse(method.apply(ctlr)); + assertEquals(0, counter.getAndSet(0)); + } + + /** + * Check the simple case that doesn't depend on the controller state. + * + * @param counter counter to check after each invocation + * @param method method to invoke + */ + private void checkSimple(AtomicInteger counter, Function<PolicyController, Boolean> method) { + when(ctlr.isAlive()).thenReturn(true); + assertFalse(method.apply(ctlr)); + assertEquals(1, counter.getAndSet(0)); + + when(ctlr.isAlive()).thenReturn(false); + assertFalse(method.apply(ctlr)); + assertEquals(1, counter.getAndSet(0)); + } +} diff --git a/packages/base/src/files/etc/ssl/policy-keystore b/packages/base/src/files/etc/ssl/policy-keystore Binary files differindex b92217cf..d0185cce 100644 --- a/packages/base/src/files/etc/ssl/policy-keystore +++ b/packages/base/src/files/etc/ssl/policy-keystore |