Merge "S3P Stability and Performance Tests"
authorPamela Dragosh <pdragosh@research.att.com>
Wed, 24 Jul 2019 13:21:28 +0000 (13:21 +0000)
committerGerrit Code Review <gerrit@onap.org>
Wed, 24 Jul 2019 13:21:28 +0000 (13:21 +0000)
13 files changed:
applications/common/pom.xml
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/operationshistory/CountRecentOperationsPipTest.java
lombok.config [new file with mode: 0644]
main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java
main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java
main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java [deleted file]
main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java
main/src/test/java/org/onap/policy/pdpx/main/XacmlStateTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpPapRegistrationTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListenerTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListenerTest.java [new file with mode: 0644]

index 1c7adf8..bb6f3b1 100644 (file)
             <artifactId>junit</artifactId>
             <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>
index 10b9d89..b01fa70 100644 (file)
@@ -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.
 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<PIPResponse> responses;
+    private Queue<String> 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 (file)
index 0000000..7a21e88
--- /dev/null
@@ -0,0 +1 @@
+lombok.addLombokGeneratedAnnotation = true
index 2904474..3177c09 100644 (file)
 
 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);
+    }
 }
index 2a8ef99..64ffded 100644 (file)
@@ -55,7 +55,7 @@ public class XacmlPdpUpdateListener extends ScoListener<PdpUpdate> {
         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<PdpUpdate> {
 
     }
 
+    // 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 (file)
index a6213da..0000000
+++ /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<HttpServletServer> 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();
-    }
-
-}
index eb3ac23..70253c0 100644 (file)
@@ -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 (file)
index 0000000..20136bf
--- /dev/null
@@ -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 (file)
index 0000000..a1f5077
--- /dev/null
@@ -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<ScheduledFuture<?>> 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 (file)
index 0000000..c05e099
--- /dev/null
@@ -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 (file)
index 0000000..31bec51
--- /dev/null
@@ -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<ToscaPolicy, XacmlApplicationServiceProvider> 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<ToscaPolicy> 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 (file)
index 0000000..b49f4e2
--- /dev/null
@@ -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 (file)
index 0000000..73870d0
--- /dev/null
@@ -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;
+        }
+    }
+}