From: Pamela Dragosh Date: Wed, 24 Jul 2019 13:21:28 +0000 (+0000) Subject: Merge "S3P Stability and Performance Tests" X-Git-Tag: 2.1.1~6 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=df317bffbb2591e3c169d8cf12f6de1d0213df76;hp=9e27b690b9d9962597bd7f651a99640d1f9de28d;p=policy%2Fxacml-pdp.git Merge "S3P Stability and Performance Tests" --- diff --git a/applications/common/pom.xml b/applications/common/pom.xml index 1c7adf81..bb6f3b12 100644 --- a/applications/common/pom.xml +++ b/applications/common/pom.xml @@ -37,6 +37,11 @@ junit test + + org.powermock + powermock-api-mockito + test + com.h2database h2 diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/operationshistory/CountRecentOperationsPipTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/operationshistory/CountRecentOperationsPipTest.java index 10b9d899..b01fa708 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/operationshistory/CountRecentOperationsPipTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/operationshistory/CountRecentOperationsPipTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019 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. @@ -19,70 +19,130 @@ package org.onap.policy.pdp.xacml.application.common.operationshistory; import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.pip.StdPIPResponse; import java.io.FileInputStream; -import java.lang.reflect.Method; +import java.io.IOException; import java.sql.Date; import java.time.Instant; - +import java.util.Arrays; +import java.util.LinkedList; import java.util.Properties; +import java.util.Queue; import java.util.UUID; - import javax.persistence.EntityManager; import javax.persistence.Persistence; import javax.persistence.Query; - import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CountRecentOperationsPipTest { private static final Logger LOGGER = LoggerFactory.getLogger(CountRecentOperationsPipTest.class); - private static CountRecentOperationsPip pipEngine; + + private static final String ACTOR = "my-actor"; + private static final String RECIPE = "my-recipe"; + private static final String TARGET = "my-target"; + private static final String TEST_PROPERTIES = "src/test/resources/test.properties"; private static EntityManager em; + @Mock + private PIPRequest pipRequest; + + @Mock + private PIPFinder pipFinder; + + @Mock + private PIPResponse resp1; + + @Mock + private PIPResponse resp2; + + @Mock + private PIPResponse resp3; + + @Mock + private Status okStatus; + + private Properties properties; + private Queue responses; + private Queue attributes; + + private CountRecentOperationsPip pipEngine; + /** - * Create an instance of our engine and also the persistence - * factory. + * Establishes a connection to the DB and keeps it open until all tests have + * completed. * - * @throws Exception connectivity issues + * @throws IOException if properties cannot be loaded */ @BeforeClass - public static void setup() throws Exception { - LOGGER.info("Setting up PIP Testing"); - // - // Create instance - // - pipEngine = new CountRecentOperationsPip(); + public static void setUpBeforeClass() throws IOException { // // Load our test properties to use // - Properties properties = new Properties(); - try (FileInputStream is = new FileInputStream("src/test/resources/test.properties")) { - properties.load(is); + Properties props2 = new Properties(); + try (FileInputStream is = new FileInputStream(TEST_PROPERTIES)) { + props2.load(is); } // - // Configure it using properties - // - pipEngine.configure("issuer", properties); - LOGGER.info("PIP configured now creating our entity manager"); - LOGGER.info("properties {}", properties); - // // Connect to in-mem db // String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit"; LOGGER.info("persistenceunit {}", persistenceUnit); - em = Persistence.createEntityManagerFactory(properties.getProperty(persistenceUnit), properties) - .createEntityManager(); + em = Persistence.createEntityManagerFactory(props2.getProperty(persistenceUnit), props2).createEntityManager(); // // // LOGGER.info("Configured own entity manager", em.toString()); } + /** + * Create an instance of our engine. + * + * @throws Exception if an error occurs + */ + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:hour"); + + pipEngine = new MyPip(); + + properties = new Properties(); + try (FileInputStream is = new FileInputStream(TEST_PROPERTIES)) { + properties.load(is); + } + + when(pipFinder.getMatchingAttributes(any(), eq(pipEngine))).thenReturn(resp1, resp2, resp3); + + responses = new LinkedList<>(Arrays.asList(resp1, resp2, resp3)); + attributes = new LinkedList<>(Arrays.asList(ACTOR, RECIPE, TARGET)); + + when(resp1.getStatus()).thenReturn(okStatus); + when(resp2.getStatus()).thenReturn(okStatus); + when(resp3.getStatus()).thenReturn(okStatus); + + when(okStatus.isOk()).thenReturn(true); + } + private Dbao createEntry(String cl, String target, String outcome) { // // Create entry @@ -99,31 +159,63 @@ public class CountRecentOperationsPipTest { return newEntry; } + @Test + public void testAttributesRequired() { + assertEquals(3, pipEngine.attributesRequired().size()); + } + + @Test + public void testConfigure_DbException() throws Exception { + properties.put("javax.persistence.jdbc.url", "invalid"); + pipEngine.configure("issuer", properties); + } + + @Test + public void testGetAttributes_NullIssuer() throws PIPException { + when(pipRequest.getIssuer()).thenReturn(null); + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder)); + } + + @Test + public void testGetAttributes_WrongIssuer() throws PIPException { + when(pipRequest.getIssuer()).thenReturn("wrong-issuer"); + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder)); + } + + @Test + public void testGetAttributes_NullActor() throws PIPException { + attributes = new LinkedList<>(Arrays.asList(null, RECIPE, TARGET)); + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder)); + } + + @Test + public void testGetAttributes_NullRecipe() throws PIPException { + attributes = new LinkedList<>(Arrays.asList(ACTOR, null, TARGET)); + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder)); + } + + @Test + public void testGetAttributes_NullTarget() throws PIPException { + attributes = new LinkedList<>(Arrays.asList(ACTOR, RECIPE, null)); + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder)); + } + @Test public void testGetCountFromDb() throws Exception { // - // Use reflection to run getCountFromDB + // Configure it using properties // - Method method = CountRecentOperationsPip.class.getDeclaredMethod("doDatabaseQuery", - String.class, - String.class, - String.class, - int.class, - String.class); - method.setAccessible(true); + pipEngine.configure("issuer", properties); + LOGGER.info("PIP configured now creating our entity manager"); + LOGGER.info("properties {}", properties); // // create entry // Dbao newEntry = createEntry("cl-foobar-1", "vnf-1", "SUCCESS"); // - // Test pipEngine - // - long count = (long) method.invoke(pipEngine, newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget(), - 1, "HOUR"); - // // No entries yet // - assertEquals(0, count); + assertEquals(0, getCount(newEntry)); // // Add entry // @@ -133,18 +225,53 @@ public class CountRecentOperationsPipTest { // // Directly check ground truth // - Query queryCount = em.createNativeQuery("select count(*) as numops from operationshistory") - .setParameter(1, 1); + Query queryCount = em.createNativeQuery("select count(*) as numops from operationshistory").setParameter(1, 1); LOGGER.info("{} entries", queryCount.getSingleResult()); // - // Test pipEngine - // - count = (long) method.invoke(pipEngine, newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget(), - 1, "HOUR"); - // // Should count 1 entry now // - assertEquals(1, count); + assertEquals(1, getCount(newEntry)); + } + + private long getCount(Dbao newEntry) throws PIPException { + responses = new LinkedList<>(Arrays.asList(resp1, resp2, resp3)); + attributes = new LinkedList<>( + Arrays.asList(newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget())); + + PIPResponse result = pipEngine.getAttributes(pipRequest, pipFinder); + + Attribute attr = result.getAttributes().iterator().next(); + AttributeValue value = attr.getValues().iterator().next(); + + return ((Number) value.getValue()).longValue(); + } + + @Test + public void testStringToChronoUnit() throws PIPException { + // not configured yet + Dbao newEntry = createEntry("cl-foobar-1", "vnf-1", "SUCCESS"); + assertEquals(-1, getCount(newEntry)); + + // now configure it + pipEngine.configure("issuer", properties); + + String[] units = {"second", "minute", "hour", "day", "week", "month", "year"}; + + for (String unit : units) { + when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:" + unit); + + /* + * It would be better to use assertEquals below, but the test DB doesn't + * support week, month, or year. + */ + + // should run without throwing an exception + getCount(newEntry); + } + + // invalid time unit + when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:invalid"); + assertEquals(-1, getCount(newEntry)); } /** @@ -157,4 +284,16 @@ public class CountRecentOperationsPipTest { } } + private class MyPip extends CountRecentOperationsPip { + + @Override + protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { + return responses.remove(); + } + + @Override + protected String findFirstAttributeValue(PIPResponse pipResponse) { + return attributes.remove(); + } + } } diff --git a/lombok.config b/lombok.config new file mode 100644 index 00000000..7a21e880 --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +lombok.addLombokGeneratedAnnotation = true diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java index 29044744..3177c096 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java @@ -20,15 +20,19 @@ package org.onap.policy.pdpx.main.comm; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import lombok.Getter; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pdpx.main.XacmlState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class XacmlPdpHearbeatPublisher extends TimerTask { +public class XacmlPdpHearbeatPublisher implements Runnable { + public static final int DEFAULT_INTERVAL_MS = 60000; private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpHearbeatPublisher.class); @@ -42,9 +46,12 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { /** * Current timer interval, in milliseconds. */ - private long intervalMs = 60000; + @Getter + private long intervalMs = DEFAULT_INTERVAL_MS; - private Timer timer = null; + private ScheduledExecutorService timerThread; + + private ScheduledFuture timer; /** @@ -70,9 +77,9 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { * Method to terminate the heart beat. */ public synchronized void terminate() { - if (timer != null) { - timer.cancel(); - timer.purge(); + if (timerThread != null) { + timerThread.shutdownNow(); + timerThread = null; timer = null; } } @@ -87,9 +94,9 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { if (intervalMs != null && intervalMs > 0 && intervalMs != this.intervalMs) { this.intervalMs = intervalMs; - if (timer != null) { - terminate(); - start(); + if (timerThread != null) { + timer.cancel(false); + timer = timerThread.scheduleWithFixedDelay(this, 0, this.intervalMs, TimeUnit.MILLISECONDS); } } } @@ -98,9 +105,15 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { * Starts the timer. */ public synchronized void start() { - if (timer == null) { - timer = new Timer(true); - timer.scheduleAtFixedRate(this, 0, this.intervalMs); + if (timerThread == null) { + timerThread = makeTimerThread(); + timer = timerThread.scheduleWithFixedDelay(this, 0, this.intervalMs, TimeUnit.MILLISECONDS); } } + + // these may be overridden by junit tests + + protected ScheduledExecutorService makeTimerThread() { + return Executors.newScheduledThreadPool(1); + } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java index 2a8ef99f..64ffdeda 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java @@ -55,7 +55,7 @@ public class XacmlPdpUpdateListener extends ScoListener { super(PdpUpdate.class); this.state = state; this.heartbeat = heartbeat; - this.publisher = new XacmlPdpUpdatePublisher(client, state, appManager); + this.publisher = makePublisher(client, state, appManager); } @Override @@ -77,4 +77,10 @@ public class XacmlPdpUpdateListener extends ScoListener { } + // these may be overridden by junit tests + protected XacmlPdpUpdatePublisher makePublisher(TopicSinkClient client, XacmlState state, + XacmlPdpApplicationManager appManager) { + + return new XacmlPdpUpdatePublisher(client, state, appManager); + } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java deleted file mode 100644 index a6213da2..00000000 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java +++ /dev/null @@ -1,159 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pdpx.main.rest; - -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import org.onap.policy.common.capabilities.Startable; -import org.onap.policy.common.endpoints.http.server.HttpServletServer; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -import org.onap.policy.common.endpoints.parameters.RestServerParameters; -import org.onap.policy.common.gson.GsonMessageBodyHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class to manage life cycle of xacml pdp rest server. - * - */ -public class XacmlPdpRestServer implements Startable { - - private static final String SEPARATOR = "."; - private static final String HTTP_SERVER_SERVICES = "http.server.services"; - private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpRestServer.class); - - private List servers = new ArrayList<>(); - - private final RestServerParameters restServerParameters; - - /** - * Constructor for instantiating XacmlPdpRestServer. - * - * @param restServerParameters the rest server parameters - */ - public XacmlPdpRestServer(final RestServerParameters restServerParameters) { - this.restServerParameters = restServerParameters; - } - - /** - * {@inheritDoc}. - */ - @Override - public boolean start() { - try { - LOGGER.info("Starting XacmlPdpRestServer..."); - - // - // Get the server properties - // - servers = HttpServletServerFactoryInstance.getServerFactory().build(getServerProperties()); - // - // Start all the servers - // - for (final HttpServletServer server : servers) { - if (server.isAaf()) { - server.addFilterClass(null, XacmlPdpAafFilter.class.getName()); - } - server.start(); - } - LOGGER.info("servers are started"); - } catch (final Exception exp) { - LOGGER.error("Failed to start xacml pdp http server", exp); - return false; - } - return true; - } - - /** - * Creates the server properties object using restServerParameters. - * - * @return the properties object - */ - private Properties getServerProperties() { - final Properties props = new Properties(); - props.setProperty(HTTP_SERVER_SERVICES, restServerParameters.getName()); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".host", - restServerParameters.getHost()); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".port", - Integer.toString(restServerParameters.getPort())); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".restClasses", - XacmlPdpRestController.class.getName()); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".managed", "false"); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".swagger", "true"); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".userName", - restServerParameters.getUserName()); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".password", - restServerParameters.getPassword()); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".https", - String.valueOf(restServerParameters.isHttps())); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".aaf", - String.valueOf(restServerParameters.isAaf())); - props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".serialization.provider", - GsonMessageBodyHandler.class.getName()); - return props; - } - - /** - * {@inheritDoc}. - */ - @Override - public boolean stop() { - for (final HttpServletServer server : servers) { - try { - server.shutdown(); - } catch (final Exception exp) { - LOGGER.error("Failed to stop xacml pdp http server", exp); - } - } - return true; - } - - /** - * {@inheritDoc}. - */ - @Override - public void shutdown() { - stop(); - } - - /** - * {@inheritDoc}. - */ - @Override - public boolean isAlive() { - return !servers.isEmpty(); - } - - /** - * {@inheritDoc}. - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("XacmlPdpRestServer [servers="); - builder.append(servers); - builder.append("]"); - return builder.toString(); - } - -} diff --git a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java index eb3ac230..70253c09 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java @@ -29,6 +29,7 @@ import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.TopicSource; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; +import org.onap.policy.common.endpoints.http.server.RestServer; import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; import org.onap.policy.common.parameters.ParameterService; import org.onap.policy.common.utils.services.ServiceManagerContainer; @@ -40,8 +41,9 @@ import org.onap.policy.pdpx.main.comm.XacmlPdpHearbeatPublisher; import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpStateChangeListener; import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpUpdateListener; import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup; +import org.onap.policy.pdpx.main.rest.XacmlPdpAafFilter; import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; -import org.onap.policy.pdpx.main.rest.XacmlPdpRestServer; +import org.onap.policy.pdpx.main.rest.XacmlPdpRestController; import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,11 +67,6 @@ public class XacmlPdpActivator extends ServiceManagerContainer { // The parameters of this policy xacml pdp activator private final XacmlPdpParameterGroup xacmlPdpParameterGroup; - /** - * The XACML PDP REST API server. - */ - private XacmlPdpRestServer restServer; - /** * Listens for messages on the topic, decodes them into a {@link PdpStatus} message, and then * dispatches them to appropriate listener. @@ -91,6 +88,7 @@ public class XacmlPdpActivator extends ServiceManagerContainer { final XacmlPdpHearbeatPublisher heartbeat; final TopicSinkClient sinkClient; final XacmlState state; + final RestServer restServer; try { XacmlPdpApplicationManager appmgr = @@ -119,6 +117,9 @@ public class XacmlPdpActivator extends ServiceManagerContainer { msgDispatcher.register(PdpMessageType.PDP_UPDATE.name(), new XacmlPdpUpdateListener(sinkClient, state, heartbeat, appmgr)); + restServer = new RestServer(xacmlPdpParameterGroup.getRestServerParameters(), XacmlPdpAafFilter.class, + XacmlPdpRestController.class); + } catch (RuntimeException | TopicSinkClientException e) { throw new PolicyXacmlPdpRuntimeException(e.getMessage(), e); } @@ -146,13 +147,9 @@ public class XacmlPdpActivator extends ServiceManagerContainer { heartbeat::start, heartbeat::terminate); - addAction("Create REST server", - () -> restServer = new XacmlPdpRestServer(xacmlPdpParameterGroup.getRestServerParameters()), - () -> restServer = null); - addAction("REST server", - () -> restServer.start(), - () -> restServer.stop()); + restServer::start, + restServer::stop); // @formatter:on } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/XacmlStateTest.java b/main/src/test/java/org/onap/policy/pdpx/main/XacmlStateTest.java new file mode 100644 index 00000000..20136bf0 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/XacmlStateTest.java @@ -0,0 +1,164 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main; + +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.when; + +import java.util.Arrays; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.models.pdp.concepts.PdpResponseDetails; +import org.onap.policy.models.pdp.concepts.PdpStateChange; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.models.pdp.enums.PdpHealthStatus; +import org.onap.policy.models.pdp.enums.PdpResponseStatus; +import org.onap.policy.models.pdp.enums.PdpState; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; +import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator; + +public class XacmlStateTest { + private static final String PDP_TYPE = "xacml"; + private static final String GROUP = "my-group"; + private static final String SUBGROUP = "my-subgroup"; + private static final PdpState STATE = PdpState.SAFE; + + @Mock + private XacmlPdpApplicationManager appmgr; + + @Mock + private XacmlPdpActivator act; + + private ToscaPolicyTypeIdentifier ident1; + private ToscaPolicyTypeIdentifier ident2; + + private String hostName; + + private XacmlState state; + + /** + * Initializes objects, including the state. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + hostName = NetworkUtil.getHostname(); + + ident1 = new ToscaPolicyTypeIdentifier("nameA", "typeA"); + ident2 = new ToscaPolicyTypeIdentifier("nameB", "typeB"); + + when(appmgr.getToscaPolicyTypeIdents()).thenReturn(Arrays.asList(ident1, ident2)); + + XacmlPdpActivator.setCurrent(act); + + state = new XacmlState(appmgr); + } + + @AfterClass + public static void tearDownAfterClass() { + XacmlPdpActivator.setCurrent(null); + } + + @Test + public void testShouldHandle() { + PdpUpdate msg = new PdpUpdate(); + assertFalse(state.shouldHandle(msg)); + + msg.setName(NetworkUtil.getHostname()); + assertTrue(state.shouldHandle(msg)); + } + + @Test + public void testGenHeartbeat() { + // not healthy + PdpStatus status = state.genHeartbeat(); + assertEquals(PdpHealthStatus.NOT_HEALTHY, status.getHealthy()); + assertEquals(hostName, status.getName()); + assertEquals(PDP_TYPE, status.getPdpType()); + assertEquals(PdpState.PASSIVE, status.getState()); + assertEquals("[ToscaPolicyTypeIdentifier(name=nameA, version=typeA), " + + "ToscaPolicyTypeIdentifier(name=nameB, version=typeB)]", + status.getSupportedPolicyTypes().toString()); + assertTrue(status.getPolicies().isEmpty()); + + // healthy + when(act.isAlive()).thenReturn(true); + + status = state.genHeartbeat(); + assertEquals(PdpHealthStatus.HEALTHY, status.getHealthy()); + } + + @Test + public void testUpdateInternalStatePdpStateChange() { + PdpStateChange req = new PdpStateChange(); + req.setName(hostName); + req.setPdpGroup(GROUP); + req.setPdpSubgroup(SUBGROUP); + req.setState(STATE); + + PdpStatus status = state.updateInternalState(req); + assertEquals(PdpState.SAFE, status.getState()); + + PdpResponseDetails resp = status.getResponse(); + assertNotNull(resp); + assertEquals(req.getRequestId(), resp.getResponseTo()); + assertEquals(PdpResponseStatus.SUCCESS, resp.getResponseStatus()); + + // ensure info was saved + status = state.genHeartbeat(); + assertEquals(PdpState.SAFE, status.getState()); + } + + @Test + public void testUpdateInternalStatePdpUpdate() { + PdpUpdate req = new PdpUpdate(); + req.setPdpGroup(GROUP); + req.setPdpSubgroup(SUBGROUP); + + PdpStatus status = state.updateInternalState(req); + + PdpResponseDetails resp = status.getResponse(); + assertNotNull(resp); + assertEquals(req.getRequestId(), resp.getResponseTo()); + assertEquals(PdpResponseStatus.SUCCESS, resp.getResponseStatus()); + + // ensure info was saved + status = state.genHeartbeat(); + assertEquals(GROUP, status.getPdpGroup()); + assertEquals(SUBGROUP, status.getPdpSubgroup()); + } + + @Test + public void testTerminatePdpMessage() { + PdpStatus status = state.terminatePdpMessage(); + assertEquals(PdpState.TERMINATED, status.getState()); + } +} diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java new file mode 100644 index 00000000..a1f50771 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main.comm; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.pdpx.main.XacmlState; + +public class XacmlPdpHearbeatPublisherTest { + + private static final long INTERVAL1 = 1000L; + private static final long INTERVAL2 = 2000L; + private static final long INTERVAL_INVALID = 0; + + @Mock + private TopicSinkClient client; + + @Mock + private XacmlState state; + + @Mock + private ScheduledExecutorService executor; + + @Mock + private ScheduledFuture timer1; + + @Mock + private ScheduledFuture timer2; + + @Mock + private PdpStatus status; + + private Queue> timers; + + private XacmlPdpHearbeatPublisher publisher; + + + /** + * Initializes objects, including the publisher. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(state.genHeartbeat()).thenReturn(status); + + timers = new LinkedList<>(Arrays.asList(timer1, timer2)); + + when(executor.scheduleWithFixedDelay(any(), anyLong(), anyLong(), any())).thenAnswer(args -> timers.remove()); + + publisher = new MyPublisher(client, state); + } + + @Test + public void testRun() { + publisher.run(); + + verify(state).genHeartbeat(); + verify(client).send(status); + } + + @Test + public void testTerminate() { + // not yet started + publisher.terminate(); + + + // now start it and then try again + publisher.start(); + publisher.terminate(); + + // timer2 should still be in the queue + assertSame(timer2, timers.peek()); + + + // repeat - nothing more should happen + publisher.terminate(); + + // timer2 should still be in the queue + assertSame(timer2, timers.peek()); + } + + @Test + public void testRestart() { + // not started yet - should only update the interval + publisher.restart(INTERVAL1); + + assertEquals(INTERVAL1, publisher.getIntervalMs()); + assertSame(timer1, timers.peek()); + + // now start it + publisher.start(); + verify(executor).scheduleWithFixedDelay(publisher, 0, INTERVAL1, TimeUnit.MILLISECONDS); + + // null interval - no changes + publisher.restart(null); + verify(executor, times(1)).scheduleWithFixedDelay(any(), anyInt(), anyLong(), any()); + assertSame(timer2, timers.peek()); + + // same interval - no changes + publisher.restart(INTERVAL1); + verify(executor, times(1)).scheduleWithFixedDelay(any(), anyInt(), anyLong(), any()); + assertSame(timer2, timers.peek()); + + // invalid interval - no changes + publisher.restart(INTERVAL_INVALID); + verify(executor, times(1)).scheduleWithFixedDelay(any(), anyInt(), anyLong(), any()); + assertSame(timer2, timers.peek()); + + // new interval - old timer should be cancelled and new started + publisher.restart(INTERVAL2); + verify(timer1).cancel(anyBoolean()); + verify(executor).scheduleWithFixedDelay(publisher, 0, INTERVAL2, TimeUnit.MILLISECONDS); + } + + @Test + public void testStart() { + publisher.start(); + + verify(executor).scheduleWithFixedDelay(publisher, 0, XacmlPdpHearbeatPublisher.DEFAULT_INTERVAL_MS, + TimeUnit.MILLISECONDS); + + // repeat - nothing more should happen + publisher.start(); + verify(executor, times(1)).scheduleWithFixedDelay(any(), anyInt(), anyLong(), any()); + verify(timer1, never()).cancel(anyBoolean()); + } + + @Test + public void testMakeTimerThread() { + // create a plain listener to test the "real" makeTimer() method + publisher = new XacmlPdpHearbeatPublisher(client, state); + + publisher.start(); + publisher.restart(100L); + publisher.terminate(); + } + + private class MyPublisher extends XacmlPdpHearbeatPublisher { + + public MyPublisher(TopicSinkClient topicSinkClient, XacmlState state) { + super(topicSinkClient, state); + } + + @Override + protected ScheduledExecutorService makeTimerThread() { + return executor; + } + } +} diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpPapRegistrationTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpPapRegistrationTest.java new file mode 100644 index 00000000..c05e0999 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpPapRegistrationTest.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main.comm; + +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; +import org.onap.policy.models.pdp.concepts.PdpStatus; + +public class XacmlPdpPapRegistrationTest { + + @Mock + private TopicSinkClient client; + + @Mock + private PdpStatus status; + + private XacmlPdpPapRegistration reg; + + /** + * Initializes objects, including the registration object. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(client.send(status)).thenReturn(true); + + reg = new XacmlPdpPapRegistration(client); + } + + @Test + public void testPdpRegistration_SendOk() throws TopicSinkClientException { + reg.pdpRegistration(status); + } + + @Test + public void testPdpRegistration_SendFail() throws TopicSinkClientException { + when(client.send(status)).thenReturn(false); + reg.pdpRegistration(status); + } + + @Test + public void testPdpRegistration_SendEx() throws TopicSinkClientException { + when(client.send(status)).thenThrow(new IllegalStateException()); + reg.pdpRegistration(status); + } +} diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java new file mode 100644 index 00000000..31bec51e --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java @@ -0,0 +1,181 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main.comm; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; +import org.onap.policy.pdpx.main.XacmlState; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; +import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager; + + +/** + * Initializes objects, including the publisher. + */ +public class XacmlPdpUpdatePublisherTest { + + private static final int NEW_COUNT = 4; + + @Mock + private TopicSinkClient client; + + @Mock + private XacmlState state; + + @Mock + private PdpStatus status; + + @Mock + private XacmlPdpApplicationManager appmgr; + + @Mock + private ToscaPolicy deployed1; + + @Mock + private ToscaPolicy deployed2; + + @Mock + private ToscaPolicy deployed3; + + @Mock + private ToscaPolicy deployed4; + + @Mock + private ToscaPolicy added1; + + @Mock + private ToscaPolicy added2; + + @Mock + private PdpUpdate update; + + private XacmlPdpUpdatePublisher publisher; + + + /** + * Initializes objects, including the publisher. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + Map deployedPolicies = new HashMap<>(); + deployedPolicies.put(deployed1, null); + deployedPolicies.put(deployed2, null); + deployedPolicies.put(deployed3, null); + deployedPolicies.put(deployed4, null); + when(appmgr.getToscaPolicies()).thenReturn(deployedPolicies); + + // update includes two overlaps + List updatePolicies = Arrays.asList(added1, deployed2, deployed3, added2); + when(update.getPolicies()).thenReturn(updatePolicies); + + when(appmgr.getPolicyCount()).thenReturn(NEW_COUNT); + + when(state.updateInternalState(update)).thenReturn(status); + + when(client.send(any())).thenReturn(true); + + publisher = new XacmlPdpUpdatePublisher(client, state, appmgr); + } + + @Test + public void testHandlePdpUpdate() { + XacmlPdpStatisticsManager statmgr = new XacmlPdpStatisticsManager(); + XacmlPdpStatisticsManager.setCurrent(statmgr); + + publisher.handlePdpUpdate(update); + + // two removed + verify(appmgr).removeUndeployedPolicy(deployed1); + verify(appmgr).removeUndeployedPolicy(deployed4); + + // two added + verify(appmgr).loadDeployedPolicy(added1); + verify(appmgr).loadDeployedPolicy(added2); + + // two untouched + verify(appmgr, never()).removeUndeployedPolicy(deployed2); + verify(appmgr, never()).removeUndeployedPolicy(deployed3); + verify(appmgr, never()).loadDeployedPolicy(deployed2); + verify(appmgr, never()).loadDeployedPolicy(deployed3); + + assertEquals(NEW_COUNT, statmgr.getTotalPoliciesCount()); + + verify(client).send(status); + } + + @Test + public void testHandlePdpUpdate_NullPolicies() { + when(update.getPolicies()).thenReturn(null); + + publisher.handlePdpUpdate(update); + + // all removed + verify(appmgr).removeUndeployedPolicy(deployed1); + verify(appmgr).removeUndeployedPolicy(deployed2); + verify(appmgr).removeUndeployedPolicy(deployed3); + verify(appmgr).removeUndeployedPolicy(deployed4); + + // none added + verify(appmgr, never()).loadDeployedPolicy(any()); + + verify(client).send(status); + } + + @Test + public void testHandlePdpUpdate_NullStats() { + XacmlPdpStatisticsManager.setCurrent(null); + + // should work without throwing an exception + publisher.handlePdpUpdate(update); + + verify(client).send(status); + } + + @Test + public void testHandlePdpUpdate_SendFail() { + + when(client.send(any())).thenReturn(false); + + publisher.handlePdpUpdate(update); + + verify(client).send(status); + } + +} diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListenerTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListenerTest.java new file mode 100644 index 00000000..b49f4e29 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListenerTest.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main.comm.listeners; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.models.pdp.concepts.PdpStateChange; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.pdpx.main.XacmlState; +import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpStateChangeListener; + +public class XacmlPdpStateChangeListenerTest { + private static final String TOPIC = "my-topic"; + + @Mock + private TopicSinkClient client; + + @Mock + private XacmlState state; + + @Mock + private PdpStatus status; + + @Mock + private PdpStateChange change; + + private XacmlPdpStateChangeListener listener; + + /** + * Initializes objects, including the listener. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + listener = new XacmlPdpStateChangeListener(client, state); + + when(state.shouldHandle(change)).thenReturn(true); + when(state.updateInternalState(change)).thenReturn(status); + + when(client.send(status)).thenReturn(true); + } + + @Test + public void testOnTopicEvent_Unhandled() { + when(state.shouldHandle(change)).thenReturn(false); + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, change); + + verify(state, never()).updateInternalState(any(PdpStateChange.class)); + verify(client, never()).send(any()); + } + + @Test + public void testOnTopicEvent_SendFailed() { + when(client.send(status)).thenReturn(false); + + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, change); + + verify(state).updateInternalState(change); + verify(client).send(status); + } + + @Test + public void testOnTopicEvent_SendOk() { + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, change); + + verify(state).updateInternalState(change); + verify(client).send(status); + } + +} diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListenerTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListenerTest.java new file mode 100644 index 00000000..73870d05 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListenerTest.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pdpx.main.comm.listeners; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.pdpx.main.XacmlState; +import org.onap.policy.pdpx.main.comm.XacmlPdpHearbeatPublisher; +import org.onap.policy.pdpx.main.comm.XacmlPdpUpdatePublisher; +import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpUpdateListener; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; +import org.powermock.reflect.Whitebox; + +public class XacmlPdpUpdateListenerTest { + private static final String EXPECTED_EXCEPTION = "expected exception"; + private static final String TOPIC = "my-topic"; + private static final long HB_INTERVAL = 100L; + + @Mock + private TopicSinkClient client; + + @Mock + private XacmlState state; + + @Mock + private XacmlPdpHearbeatPublisher heartbeat; + + @Mock + private XacmlPdpApplicationManager appmgr; + + @Mock + private XacmlPdpUpdatePublisher publisher; + + private PdpUpdate update; + + private XacmlPdpUpdateListener listener; + + /** + * Initializes objects, including the listener. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + listener = new MyListener(client, state, heartbeat, appmgr); + update = new PdpUpdate(); + + when(state.shouldHandle(update)).thenReturn(true); + + update.setPdpHeartbeatIntervalMs(HB_INTERVAL); + } + + @Test + public void testOnTopicEvent_Unhandled() { + when(state.shouldHandle(update)).thenReturn(false); + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, update); + + verify(publisher, never()).handlePdpUpdate(any()); + verify(heartbeat, never()).restart(anyLong()); + } + + @Test + public void testOnTopicEvent_SendOk() { + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, update); + + verify(publisher).handlePdpUpdate(update); + verify(heartbeat).restart(HB_INTERVAL); + } + + @Test + public void testOnTopicEvent_SendEx() { + doThrow(new RuntimeException(EXPECTED_EXCEPTION)).when(publisher).handlePdpUpdate(update); + + listener.onTopicEvent(CommInfrastructure.NOOP, TOPIC, null, update); + + verify(publisher).handlePdpUpdate(update); + verify(heartbeat, never()).restart(anyLong()); + } + + @Test + public void testMakePublisher() { + // create a plain listener to test the "real" makePublisher() method + listener = new XacmlPdpUpdateListener(client, state, heartbeat, appmgr); + assertNotNull(Whitebox.getInternalState(listener, "publisher")); + } + + private class MyListener extends XacmlPdpUpdateListener { + + public MyListener(TopicSinkClient client, XacmlState state, XacmlPdpHearbeatPublisher heartbeat, + XacmlPdpApplicationManager appManager) { + super(client, state, heartbeat, appManager); + } + + @Override + protected XacmlPdpUpdatePublisher makePublisher(TopicSinkClient client, XacmlState state, + XacmlPdpApplicationManager appManager) { + return publisher; + } + } +}