From 77d4dd1668c290abfd5f2c6d4b1866416c313033 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Mon, 22 Jul 2019 10:57:57 -0400 Subject: [PATCH] Add junit coverage to xacml-pdp Change-Id: I9b59dcd27705e40c424b6a76420e0395adbe44bb Issue-ID: POLICY-1772 Signed-off-by: Jim Hahn --- applications/common/pom.xml | 5 + .../CountRecentOperationsPipTest.java | 235 ++++++++++++++++----- lombok.config | 1 + .../pdpx/main/comm/XacmlPdpHearbeatPublisher.java | 13 +- .../comm/listeners/XacmlPdpUpdateListener.java | 8 +- .../org/onap/policy/pdpx/main/XacmlStateTest.java | 164 ++++++++++++++ .../main/comm/XacmlPdpHearbeatPublisherTest.java | 185 ++++++++++++++++ .../main/comm/XacmlPdpPapRegistrationTest.java | 71 +++++++ .../main/comm/XacmlPdpUpdatePublisherTest.java | 181 ++++++++++++++++ .../listeners/XacmlPdpStateChangeListenerTest.java | 98 +++++++++ .../comm/listeners/XacmlPdpUpdateListenerTest.java | 131 ++++++++++++ 11 files changed, 1041 insertions(+), 51 deletions(-) create mode 100644 lombok.config create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/XacmlStateTest.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpPapRegistrationTest.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListenerTest.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListenerTest.java 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..c160c1da 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 @@ -22,6 +22,7 @@ package org.onap.policy.pdpx.main.comm; import java.util.Timer; import java.util.TimerTask; +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; @@ -29,6 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class XacmlPdpHearbeatPublisher extends TimerTask { + public static final int DEFAULT_INTERVAL_MS = 60000; private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpHearbeatPublisher.class); @@ -42,7 +44,8 @@ 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; @@ -99,8 +102,14 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { */ public synchronized void start() { if (timer == null) { - timer = new Timer(true); + timer = makeTimer(); timer.scheduleAtFixedRate(this, 0, this.intervalMs); } } + + // these may be overridden by junit tests + + protected Timer makeTimer() { + return new Timer(true); + } } 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/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..34bb0fa3 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisherTest.java @@ -0,0 +1,185 @@ +/*- + * ============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.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.Timer; +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 Timer timer1; + + @Mock + private Timer 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)); + + 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(); + + verify(timer1, never()).cancel(); + verify(timer2, never()).cancel(); + + + // now start it and then try again + publisher.start(); + publisher.terminate(); + + verify(timer1).cancel(); + + // timer2 should still be in the queue + assertSame(timer2, timers.peek()); + + + // repeat - nothing more should happen + publisher.terminate(); + + verify(timer1, times(1)).cancel(); + + // 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(timer1).scheduleAtFixedRate(publisher, 0, INTERVAL1); + + // null interval - no changes + publisher.restart(null); + verify(timer1, times(1)).scheduleAtFixedRate(any(), anyLong(), anyLong()); + assertSame(timer2, timers.peek()); + + // same interval - no changes + publisher.restart(INTERVAL1); + verify(timer1, times(1)).scheduleAtFixedRate(any(), anyLong(), anyLong()); + assertSame(timer2, timers.peek()); + + // invalid interval - no changes + publisher.restart(INTERVAL_INVALID); + verify(timer1, times(1)).scheduleAtFixedRate(any(), anyLong(), anyLong()); + assertSame(timer2, timers.peek()); + + // new interval - old timer should be cancelled and new started + publisher.restart(INTERVAL2); + verify(timer1).cancel(); + verify(timer2).scheduleAtFixedRate(publisher, 0, INTERVAL2); + } + + @Test + public void testStart() { + publisher.start(); + + verify(timer1).scheduleAtFixedRate(publisher, 0, XacmlPdpHearbeatPublisher.DEFAULT_INTERVAL_MS); + + // repeat - nothing more should happen + publisher.start(); + verify(timer1, times(1)).scheduleAtFixedRate(any(), anyLong(), anyLong()); + verify(timer1, never()).cancel(); + } + + @Test + public void testMakeTimer() { + // create a plain listener to test the "real" makeTimer() method + publisher = new XacmlPdpHearbeatPublisher(client, state); + + publisher.start(); + publisher.terminate(); + } + + private class MyPublisher extends XacmlPdpHearbeatPublisher { + + public MyPublisher(TopicSinkClient topicSinkClient, XacmlState state) { + super(topicSinkClient, state); + } + + @Override + protected Timer makeTimer() { + return timers.remove(); + } + } +} 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; + } + } +} -- 2.16.6