aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-10-24 11:17:14 -0400
committerJim Hahn <jrh3@att.com>2019-10-24 11:31:58 -0400
commit1e896c1a2d599c02a4494e868cac5fe5399f819f (patch)
tree89b9038e36a7f3545b45782c13f936aaf867451e /main
parent215177cff14cb70d62f104abca9273c349bd118f (diff)
Add trackers for generating notifications
Issue-ID: POLICY-1841 Signed-off-by: Jim Hahn <jrh3@att.com> Change-Id: I7d6fe29707685e4711120b6a1e8448f25870a0ef Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'main')
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java202
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java54
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java53
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonSupport.java94
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonTrackerTest.java297
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/notification/PolicyDeployTrackerTest.java120
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/notification/PolicyUndeployTrackerTest.java118
7 files changed, 938 insertions, 0 deletions
diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java
new file mode 100644
index 00000000..0404e1fe
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.BiPredicate;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+
+/**
+ * Common super class for deploy and undeploy trackers.
+ */
+public abstract class PolicyCommonTracker {
+
+ /**
+ * Maps a policy id to its deployment data. The subclass determines when an entry is
+ * removed.
+ *
+ * <p/>
+ * Use a LinkedHashMap, because we'll be doing lots of iteration over the map, and
+ * iteration over a LinkedHashMap is faster than over a plain HashMap.
+ */
+ private final Map<ToscaPolicyIdentifier, PolicyTrackerData> policy2data = new LinkedHashMap<>();
+
+
+ /**
+ * Constructs the object.
+ */
+ public PolicyCommonTracker() {
+ super();
+ }
+
+ /**
+ * Adds data to the tracker.
+ *
+ * @param data data to be added to the tracker
+ */
+ public void addData(PolicyPdpNotificationData data) {
+ policy2data.computeIfAbsent(data.getPolicyId(), policyId -> new PolicyTrackerData(data.getPolicyType()))
+ .addPdps(data.getPdps());
+ }
+
+ /**
+ * Removes a set of PDPs from all policies within the tracker.
+ *
+ * @param notifyData data identifying the policy and the PDPs to be removed from it
+ * @param statusList status messages are added here if policies become complete as a
+ * result of this operation
+ */
+ public void removeData(PolicyPdpNotificationData notifyData, List<PolicyStatus> statusList) {
+
+ policy2data.computeIfPresent(notifyData.getPolicyId(), (policyId, data) -> {
+
+ if (!data.removePdps(notifyData.getPdps())) {
+ // not complete yet
+ return data;
+ }
+
+ // this policy is complete - notify
+ statusList.add(makeStatus(policyId, data));
+
+ return (shouldRemove(data) ? null : data);
+ });
+ }
+
+ /**
+ * Removes a PDP from all policies within the tracker.
+ *
+ * @param pdp PDP to be removed
+ * @param statusList status messages are added here if policies become complete as a
+ * result of this operation
+ */
+ public void removePdp(String pdp, List<PolicyStatus> statusList) {
+ updateMap(statusList, (policyId, data) -> data.removePdp(pdp));
+ }
+
+ /**
+ * Processes a response from a PDP.
+ *
+ * @param pdp PDP of interest
+ * @param activePolicies policies that are still active on the PDP, as specified in
+ * the response
+ * @param statusList status messages are added here if policies become complete as a
+ * result of this operation
+ */
+ public void processResponse(String pdp, Collection<ToscaPolicyIdentifier> activePolicies,
+ List<PolicyStatus> statusList) {
+ processResponse(pdp, new HashSet<>(activePolicies), statusList);
+ }
+
+ /**
+ * Processes a response from a PDP.
+ *
+ * @param pdp PDP of interest
+ * @param activePolicies policies that are still active on the PDP, as specified in
+ * the response
+ * @param statusList status messages are added here if policies become complete as a
+ * result of this operation
+ */
+ public void processResponse(String pdp, Set<ToscaPolicyIdentifier> activePolicies, List<PolicyStatus> statusList) {
+ updateMap(statusList, (policyId, data) -> updateData(pdp, data, activePolicies.contains(policyId)));
+ }
+
+ /**
+ * Updates the map.
+ *
+ * <p/>
+ * Note: this iterates through the whole map. While it may be more efficient to
+ * iterate through just the policies relevant to the PDP, that would complicate the
+ * code and complicate the testing. In addition, this should still perform well
+ * enough, but if not, it can always be enhanced.
+ *
+ * @param statusList status messages are added here if policies become complete as a
+ * result of this operation
+ * @param updater function to update a policy's data. Returns {@code true} if the
+ * policy is complete (i.e., no longer awaiting any responses)
+ */
+ private void updateMap(List<PolicyStatus> statusList,
+ BiPredicate<ToscaPolicyIdentifier, PolicyTrackerData> updater) {
+
+ Iterator<Entry<ToscaPolicyIdentifier, PolicyTrackerData>> iter = policy2data.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry<ToscaPolicyIdentifier, PolicyTrackerData> ent = iter.next();
+
+ ToscaPolicyIdentifier policyId = ent.getKey();
+ PolicyTrackerData data = ent.getValue();
+
+ if (!updater.test(policyId, data)) {
+ // not complete yet
+ continue;
+ }
+
+ // this policy is complete - notify
+ statusList.add(makeStatus(policyId, data));
+
+ if (shouldRemove(data)) {
+ iter.remove();
+ }
+ }
+ }
+
+ /**
+ * Updates the policy data, based on a response from a PDP.
+ *
+ * @param pdp PDP whose response was just received
+ * @param data data associated with the policy of interest
+ * @param stillActive {@code true} if the policy is still active for the PDP,
+ * {@code false} otherwise
+ * @return {@code true} if the policy is complete (i.e., no longer awaiting any
+ * responses), {@code false} otherwise
+ */
+ protected abstract boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive);
+
+ /**
+ * Determines if a policy should be removed from the tracker, based on the state of
+ * its data.
+ *
+ * @param data data associated with the policy of interest
+ * @return {@code true} if the policy should be removed from the tracker,
+ * {@code false} otherwise
+ */
+ protected abstract boolean shouldRemove(PolicyTrackerData data);
+
+ /**
+ * Makes a status notification for the given policy.
+ *
+ * @param policyId policy ID
+ * @param data data to be used to set the status fields
+ * @return a new status notification
+ */
+ private synchronized PolicyStatus makeStatus(ToscaPolicyIdentifier policyId, PolicyTrackerData data) {
+
+ PolicyStatus status = new PolicyStatus(data.getPolicyType(), policyId);
+ data.putValuesInto(status);
+ return status;
+ }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java
new file mode 100644
index 00000000..17a5e211
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+/**
+ * Tracker for policy deployments to PDPs.
+ *
+ * <p/>
+ * Policies are not removed from the internal map until all of the sets contained within
+ * the data are empty. This may be the result of a PDP being removed from the system
+ * because it is no longer responsive, or because the PDP Subgroup that contained it is
+ * deleted.
+ */
+public class PolicyDeployTracker extends PolicyCommonTracker {
+
+ /**
+ * Constructs the object.
+ */
+ public PolicyDeployTracker() {
+ super();
+ }
+
+ @Override
+ protected boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive) {
+ return (stillActive ? data.success(pdp) : data.fail(pdp));
+ }
+
+ /**
+ * Returns {@code true} only when the data is <i>completely empty</i> (i.e., it has no
+ * more PDPs)
+ */
+ @Override
+ protected boolean shouldRemove(PolicyTrackerData data) {
+ return data.isEmpty();
+ }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java
new file mode 100644
index 00000000..964ff44d
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+/**
+ * Tracker for policy undeployments from PDPs.
+ *
+ * <p/>
+ * Policies are removed from the internal map when they are no longer waiting for
+ * responses from any PDPs.
+ */
+public class PolicyUndeployTracker extends PolicyCommonTracker {
+
+ /**
+ * Constructs the object.
+ */
+ public PolicyUndeployTracker() {
+ super();
+ }
+
+ @Override
+ protected boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive) {
+ // note: still active means the policy wasn't undeployed, thus it's a failure
+ return (stillActive ? data.fail(pdp) : data.success(pdp));
+ }
+
+ /**
+ * Returns {@code true} only when the data is "complete" (i.e., not awaiting responses
+ * from any other PDPs).
+ */
+ @Override
+ protected boolean shouldRemove(PolicyTrackerData data) {
+ return data.isComplete();
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonSupport.java b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonSupport.java
new file mode 100644
index 00000000..14f3055c
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonSupport.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+
+/**
+ * Super class for policy notification test classes.
+ */
+public class PolicyCommonSupport {
+ protected static final String MAP_FIELD = "policy2data";
+ protected static final String PDP1 = "pdp-1";
+ protected static final String PDP2 = "pdp-2";
+ protected static final String PDP3 = "pdp-3";
+ protected static final String PDP4 = "pdp-4";
+
+ protected ToscaPolicyTypeIdentifier type;
+ protected ToscaPolicyIdentifier policy1;
+ protected ToscaPolicyIdentifier policy2;
+ protected ToscaPolicyIdentifier policy3;
+ protected ToscaPolicyIdentifier policy4;
+
+ /**
+ * Creates various objects.
+ */
+ @Before
+ public void setUp() {
+ type = new ToscaPolicyTypeIdentifier("my-type", "3.2.1");
+ policy1 = new ToscaPolicyIdentifier("my-id-a", "1.2.0");
+ policy2 = new ToscaPolicyIdentifier("my-id-b", "1.2.1");
+ policy3 = new ToscaPolicyIdentifier("my-id-c", "1.2.2");
+ policy4 = new ToscaPolicyIdentifier("my-id-d", "1.2.3");
+ }
+
+ /**
+ * Makes notification data.
+ *
+ * @param policyId ID of the policy with which the data should be associated
+ * @param pdps PDPs to be included within the data
+ * @return a new notification data structure
+ */
+ protected PolicyPdpNotificationData makeData(ToscaPolicyIdentifier policyId, String... pdps) {
+ PolicyPdpNotificationData data = new PolicyPdpNotificationData(policyId, type);
+ data.addAll(Arrays.asList(pdps));
+ return data;
+ }
+
+ /**
+ * Extracts the counts from the sets contained within tracker data.
+ *
+ * @param data data from which to extract the sets
+ * @return a list containing the number of successes, failures, and incomplete PDPs,
+ * in that order
+ */
+ protected List<Integer> getCounts(PolicyTrackerData data) {
+ PolicyStatus status = new PolicyStatus();
+ data.putValuesInto(status);
+ return getCounts(status);
+ }
+
+ /**
+ * Extracts the counts from within a status notification.
+ *
+ * @param status status from which to extract the counts
+ * @return a list containing the number of successes, failures, and incomplete PDPs,
+ * in that order
+ */
+ protected List<Integer> getCounts(PolicyStatus status) {
+ return Arrays.asList(status.getSuccessCount(), status.getFailureCount(), status.getIncompleteCount());
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonTrackerTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonTrackerTest.java
new file mode 100644
index 00000000..cfcf4471
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonTrackerTest.java
@@ -0,0 +1,297 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.powermock.reflect.Whitebox;
+
+public class PolicyCommonTrackerTest extends PolicyCommonSupport {
+
+ private MyTracker tracker;
+ private Map<ToscaPolicyIdentifier, PolicyTrackerData> map;
+
+ /**
+ * Creates various objects, including {@link #tracker}.
+ */
+ @Before
+ public void setUp() {
+ super.setUp();
+
+ tracker = new MyTracker();
+ }
+
+ @Test
+ public void testAddData() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+ assertEquals(1, map.size());
+
+ PolicyTrackerData data = map.get(policy1);
+ assertNotNull(data);
+ assertFalse(data.isComplete());
+
+ // add same policy - should still have the same data object
+ tracker.addData(makeData(policy1, PDP1, PDP3));
+ assertEquals(1, map.size());
+ assertSame(data, map.get(policy1));
+ assertFalse(data.isComplete());
+
+ // add another policy
+ tracker.addData(makeData(policy2, PDP2));
+ assertEquals(2, map.size());
+
+ // data for policy 1 is unchanged
+ assertSame(data, map.get(policy1));
+ assertFalse(data.isComplete());
+
+ // policy 2 should have its own data
+ assertTrue(map.get(policy2) != data);
+ data = map.get(policy2);
+ assertNotNull(data);
+ assertFalse(data.isComplete());
+ }
+
+ /**
+ * Tests removeData() when the policy isn't in the map.
+ */
+ @Test
+ public void testRemoveDataUnknownPolicy() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+
+ // remove a policy that isn't in the map
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.removeData(makeData(policy3, PDP1), statusList);
+ assertTrue(statusList.isEmpty());
+ assertEquals(2, map.size());
+ }
+
+ /**
+ * Tests removeData() when only some PDPs are removed from the policy.
+ */
+ @Test
+ public void testRemoveDataRemoveSomePdps() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+
+ // remove some PDPs from a policy - no notifications and no changes to the map
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.removeData(makeData(policy2, PDP1), statusList);
+ assertTrue(statusList.isEmpty());
+ assertTrue(map.containsKey(policy1));
+ assertTrue(map.containsKey(policy2));
+ }
+
+ /**
+ * Tests removeData() when the subclass indicates that the policy should NOT be removed.
+ */
+ @Test
+ public void testRemoveDataDoNotRemovePolicy() {
+ tracker = new MyTracker() {
+ @Override
+ protected boolean shouldRemove(PolicyTrackerData data) {
+ return false;
+ }
+ };
+
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+
+ // remove all the PDPs from one policy, but do NOT remove the policy
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.removeData(makeData(policy2, PDP1, PDP3), statusList);
+ assertEquals(1, statusList.size());
+ assertEquals(policy2, statusList.get(0).getPolicy());
+ assertTrue(map.containsKey(policy1));
+ assertTrue(map.containsKey(policy2));
+ }
+
+ /**
+ * Tests removeData() when the subclass indicates that the policy should be removed.
+ */
+ @Test
+ public void testRemoveDataRemovePolicy() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+
+ // remove all the PDPs from one policy, and remove the policy
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.removeData(makeData(policy1, PDP1, PDP2, PDP3), statusList);
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+ assertFalse(map.containsKey(policy1));
+ assertTrue(map.containsKey(policy2));
+ }
+
+ @Test
+ public void testRemovePdp() {
+ tracker.addData(makeData(policy1, PDP1));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+ tracker.addData(makeData(policy3, PDP1, PDP2, PDP3));
+ tracker.addData(makeData(policy4, PDP4, PDP2, PDP3));
+
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.removePdp(PDP1, statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+
+ assertEquals(3, map.size());
+ assertFalse(map.containsKey(policy1));
+ assertEquals("[0, 0, 1]", getCounts(map.get(policy2)).toString());
+ assertEquals("[0, 0, 2]", getCounts(map.get(policy3)).toString());
+ assertEquals("[0, 0, 3]", getCounts(map.get(policy4)).toString());
+ }
+
+ @Test
+ public void testProcessResponse() {
+ tracker.addData(makeData(policy1, PDP1));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+ tracker.addData(makeData(policy3, PDP1, PDP2, PDP3));
+ tracker.addData(makeData(policy4, PDP4, PDP2, PDP3));
+
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Arrays.asList(policy3), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+
+ assertEquals(3, map.size());
+ assertFalse(map.containsKey(policy1));
+ assertEquals("[0, 1, 1]", getCounts(map.get(policy2)).toString());
+ assertEquals("[1, 0, 2]", getCounts(map.get(policy3)).toString());
+ assertEquals("[0, 0, 3]", getCounts(map.get(policy4)).toString());
+ }
+
+ @Test
+ public void testUpdateMap() {
+ tracker.addData(makeData(policy1, PDP1));
+ tracker.addData(makeData(policy2, PDP1, PDP3));
+ tracker.addData(makeData(policy3, PDP1, PDP2, PDP3));
+ tracker.addData(makeData(policy4, PDP4, PDP2, PDP3));
+
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Arrays.asList(policy3), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+
+ assertEquals(3, map.size());
+ assertFalse(map.containsKey(policy1));
+ assertEquals("[0, 1, 1]", getCounts(map.get(policy2)).toString());
+ assertEquals("[1, 0, 2]", getCounts(map.get(policy3)).toString());
+ assertEquals("[0, 0, 3]", getCounts(map.get(policy4)).toString());
+ }
+
+ /**
+ * Tests updateMap() when the policy should NOT be removed.
+ */
+ @Test
+ public void testUpdateMapDoNotRemove() {
+ tracker = new MyTracker() {
+ @Override
+ protected boolean shouldRemove(PolicyTrackerData data) {
+ return false;
+ }
+ };
+
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+
+ // indicate that PDP2 has succeeded
+ tracker.processResponse(PDP2, Arrays.asList(policy1), new ArrayList<>(0));
+
+ // indicate that PDP1 has succeeded
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Arrays.asList(policy1), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+
+ assertEquals(1, map.size());
+ assertTrue(map.containsKey(policy1));
+ assertEquals("[2, 0, 0]", getCounts(map.get(policy1)).toString());
+ }
+
+ /**
+ * Tests updateMap() when the policy SHOULD be removed.
+ */
+ @Test
+ public void testUpdateMapRemovePolicy() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+
+ // indicate that PDP2 has succeeded
+ tracker.processResponse(PDP2, Arrays.asList(policy1), new ArrayList<>(0));
+
+ // indicate that PDP1 has succeeded
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Arrays.asList(policy1), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+ assertEquals("[2, 0, 0]", getCounts(statusList.get(0)).toString());
+
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void testMakeStatus() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+
+ // indicate that PDP2 has succeeded
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP2, Arrays.asList(policy1), statusList);
+ assertTrue(statusList.isEmpty());
+
+ // indicate that PDP1 has failed
+ tracker.processResponse(PDP1, Arrays.asList(policy2), statusList);
+ assertEquals(1, statusList.size());
+ assertEquals("[1, 1, 0]", getCounts(statusList.get(0)).toString());
+ }
+
+ private class MyTracker extends PolicyCommonTracker {
+
+ public MyTracker() {
+ map = Whitebox.getInternalState(this, MAP_FIELD);
+ }
+
+ @Override
+ protected boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive) {
+ return (stillActive ? data.success(pdp) : data.fail(pdp));
+ }
+
+ @Override
+ protected boolean shouldRemove(PolicyTrackerData data) {
+ return data.isComplete();
+ }
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/PolicyDeployTrackerTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyDeployTrackerTest.java
new file mode 100644
index 00000000..bd093141
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyDeployTrackerTest.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+
+public class PolicyDeployTrackerTest extends PolicyCommonSupport {
+
+ @Mock
+ private PolicyTrackerData data;
+
+ private PolicyDeployTracker tracker;
+
+ /**
+ * Creates various objects, including {@link #tracker}.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ super.setUp();
+
+ tracker = new PolicyDeployTracker();
+ }
+
+ @Test
+ public void test() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+
+ // indicate that PDP2 has succeeded
+ tracker.processResponse(PDP2, Arrays.asList(policy1), new ArrayList<>(0));
+
+ // indicate that PDP1 has succeeded
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Arrays.asList(policy1), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+ assertEquals("[2, 0, 0]", getCounts(statusList.get(0)).toString());
+
+ // indicate that PDP1 has failed - should get a notification, if still in the map
+ statusList.clear();
+ tracker.processResponse(PDP1, Collections.emptyList(), statusList);
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+ assertEquals("[1, 1, 0]", getCounts(statusList.get(0)).toString());
+ }
+
+ @Test
+ public void testUpdateData() {
+ // when success returns false
+ assertFalse(tracker.updateData(PDP1, data, true));
+ verify(data).success(PDP1);
+ verify(data, never()).fail(any());
+
+ // when inactive
+ assertFalse(tracker.updateData(PDP1, data, false));
+ verify(data).success(PDP1);
+ verify(data).fail(any());
+
+ // when success & fail return true
+ when(data.success(PDP1)).thenReturn(true);
+ when(data.fail(PDP1)).thenReturn(true);
+ assertTrue(tracker.updateData(PDP1, data, true));
+ verify(data, times(2)).success(PDP1);
+ verify(data, times(1)).fail(PDP1);
+
+ // when inactive
+ assertTrue(tracker.updateData(PDP1, data, false));
+ verify(data, times(2)).success(PDP1);
+ verify(data, times(2)).fail(PDP1);
+ }
+
+ @Test
+ public void testShouldRemove() {
+ // when data is complete, but not empty
+ when(data.isComplete()).thenReturn(true);
+ when(data.isEmpty()).thenReturn(false);
+ assertFalse(tracker.shouldRemove(data));
+
+ // when data is empty
+ when(data.isEmpty()).thenReturn(true);
+ assertTrue(tracker.shouldRemove(data));
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/PolicyUndeployTrackerTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyUndeployTrackerTest.java
new file mode 100644
index 00000000..d837cbad
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/notification/PolicyUndeployTrackerTest.java
@@ -0,0 +1,118 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.pap.main.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+
+public class PolicyUndeployTrackerTest extends PolicyCommonSupport {
+
+ @Mock
+ private PolicyTrackerData data;
+
+ private PolicyUndeployTracker tracker;
+
+ /**
+ * Creates various objects, including {@link #tracker}.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ super.setUp();
+
+ tracker = new PolicyUndeployTracker();
+ }
+
+ @Test
+ public void test() {
+ tracker.addData(makeData(policy1, PDP1, PDP2));
+
+ // indicate that PDP2 has been undeployed
+ tracker.processResponse(PDP2, Collections.emptyList(), new ArrayList<>(0));
+
+ // indicate that PDP1 has been undeployed
+ List<PolicyStatus> statusList = new ArrayList<>();
+ tracker.processResponse(PDP1, Collections.emptyList(), statusList);
+
+ assertEquals(1, statusList.size());
+ assertEquals(policy1, statusList.get(0).getPolicy());
+ assertEquals("[2, 0, 0]", getCounts(statusList.get(0)).toString());
+
+ // indicate that PDP1 has been re-deployed - should not get a notification,
+ // because policy
+ // is gone
+ statusList.clear();
+ tracker.processResponse(PDP1, Arrays.asList(policy1), statusList);
+ assertTrue(statusList.isEmpty());
+ }
+
+ @Test
+ public void testUpdateData() {
+ // when success returns false
+ assertFalse(tracker.updateData(PDP1, data, false));
+ verify(data).success(PDP1);
+ verify(data, never()).fail(any());
+
+ // when inactive
+ assertFalse(tracker.updateData(PDP1, data, true));
+ verify(data).success(PDP1);
+ verify(data).fail(any());
+
+ // when success & fail return true
+ when(data.success(PDP1)).thenReturn(true);
+ when(data.fail(PDP1)).thenReturn(true);
+ assertTrue(tracker.updateData(PDP1, data, false));
+ verify(data, times(2)).success(PDP1);
+ verify(data, times(1)).fail(PDP1);
+
+ // when inactive
+ assertTrue(tracker.updateData(PDP1, data, true));
+ verify(data, times(2)).success(PDP1);
+ verify(data, times(2)).fail(PDP1);
+ }
+
+ @Test
+ public void testShouldRemove() {
+ // when data is not complete
+ assertFalse(tracker.shouldRemove(data));
+
+ // when data is complete
+ when(data.isComplete()).thenReturn(true);
+ assertTrue(tracker.shouldRemove(data));
+ }
+}