Add notification tracking classes 94/116794/1
authorJim Hahn <jrh3@att.com>
Wed, 13 Jan 2021 15:40:01 +0000 (10:40 -0500)
committerJim Hahn <jrh3@att.com>
Wed, 13 Jan 2021 15:41:39 +0000 (10:41 -0500)
When PAP is made stateless, a new mechanism will be needed to track and
generate notifications.  Added some classes to facilitate that.

Issue-ID: POLICY-2648
Change-Id: Ib7b707f68a557e7b306dfdd1c6e6e9abd4671ec1
Signed-off-by: Jim Hahn <jrh3@att.com>
main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java [new file with mode: 0644]
main/src/main/java/org/onap/policy/pap/main/notification/StatusAction.java [new file with mode: 0644]
main/src/main/java/org/onap/policy/pap/main/notification/StatusKey.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pap/main/notification/DeploymentTrackerTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pap/main/notification/StatusActionTest.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pap/main/notification/StatusKeyTest.java [new file with mode: 0644]

diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java
new file mode 100644 (file)
index 0000000..cef70a3
--- /dev/null
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.onap.policy.models.pap.concepts.PolicyNotification;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Tracks policy status so that notifications can be generated.
+ */
+public class DeploymentTracker {
+    public final Map<ToscaConceptIdentifier, PolicyStatus> deployMap = new HashMap<>();
+    public final Map<ToscaConceptIdentifier, PolicyStatus> undeployMap = new HashMap<>();
+
+
+    /**
+     * Gets the status of all deployments.
+     *
+     * @return the status of all deployments
+     */
+    public Collection<PolicyStatus> getDeploymentStatus() {
+        return deployMap.values();
+    }
+
+    /**
+     * Gets the status of all undeployments.
+     *
+     * @return the status of all undeployments
+     */
+    public Collection<PolicyStatus> getUndeploymentStatus() {
+        return undeployMap.values();
+    }
+
+    /**
+     * Compares this tracking data with new tracking data, adding new policy status to a
+     * notification based on the differences.
+     *
+     * @param notif notification to which to add policy status
+     * @param newTracker new tracking data
+     */
+    public void addNotifications(PolicyNotification notif, DeploymentTracker newTracker) {
+        merge(notif.getAdded(), deployMap, newTracker.deployMap);
+        merge(notif.getDeleted(), undeployMap, newTracker.undeployMap);
+
+        // include those that no longer exist
+        addMissing(notif, newTracker);
+    }
+
+    /**
+     * Merges original tracking data with new tracking data, adding new policy status to
+     * the given list.
+     *
+     * @param list list to which to add policy status
+     * @param originalMap original tracking data
+     * @param newMap new tracking data
+     */
+    private void merge(List<PolicyStatus> list, Map<ToscaConceptIdentifier, PolicyStatus> originalMap,
+                    Map<ToscaConceptIdentifier, PolicyStatus> newMap) {
+
+        for (Entry<ToscaConceptIdentifier, PolicyStatus> entry : newMap.entrySet()) {
+            ToscaConceptIdentifier policy = entry.getKey();
+            PolicyStatus newStat = entry.getValue();
+            PolicyStatus oldStat = originalMap.get(policy);
+
+            if (needNotification(oldStat, newStat)) {
+                list.add(newStat);
+            }
+        }
+    }
+
+    /**
+     * Determines if a notification is needed.
+     *
+     * @param oldStat original status, or {@code null}
+     * @param newStat new status
+     * @return {@code true} if a notification is needed for the policy, {@code false}
+     *         otherwise
+     */
+    protected boolean needNotification(PolicyStatus oldStat, PolicyStatus newStat) {
+        if (oldStat == null) {
+            // new policy - need notification if it's complete now
+            return (newStat.getIncompleteCount() == 0);
+        }
+
+        if (newStat.getIncompleteCount() == 0) {
+            // don't care if the success count changes (i.e., new PDPs can be added
+            // without requiring a notification)
+            return (oldStat.getIncompleteCount() > 0 || newStat.getFailureCount() != oldStat.getFailureCount());
+        }
+
+        // something is incomplete - only notify if it was previously complete
+        return (oldStat.getIncompleteCount() == 0);
+    }
+
+    /**
+     * Adds notifications for previously deployed policies that are missing from the new
+     * tracker.
+     *
+     * @param notif notification to which to add policy status
+     * @param newTracker new tracking data
+     */
+    private void addMissing(PolicyNotification notif, DeploymentTracker newTracker) {
+        Map<ToscaConceptIdentifier, PolicyStatus> newDeployMap = newTracker.deployMap;
+
+        for (Entry<ToscaConceptIdentifier, PolicyStatus> entry : deployMap.entrySet()) {
+            if (entry.getValue().getIncompleteCount() != 0 || newDeployMap.containsKey(entry.getKey())) {
+                /*
+                 * This policy deployment was previously incomplete, or it still exists in
+                 * the new tracker. Either way, it needs no notification.
+                 */
+                continue;
+            }
+
+            // no longer deployed
+            PolicyStatus status = entry.getValue();
+
+            // create a status with counts that are all zero
+            PolicyStatus newStatus = new PolicyStatus();
+            newStatus.setPolicyId(status.getPolicyId());
+            newStatus.setPolicyVersion(status.getPolicyVersion());
+            newStatus.setPolicyTypeId(status.getPolicyTypeId());
+            newStatus.setPolicyTypeVersion(status.getPolicyTypeVersion());
+
+            notif.getAdded().add(newStatus);
+        }
+    }
+
+    /**
+     * Adds status to the tracking data. Assumes the associated PDP/policy pair has not be
+     * added before.
+     *
+     * @param status status to be added
+     */
+    public void add(StatusAction status) {
+        if (status.getAction() == StatusAction.Action.DELETED) {
+            return;
+        }
+
+        add(status.getStatus());
+    }
+
+    /**
+     * Adds status to the tracking data. Assumes the associated PDP/policy pair has not be
+     * added before.
+     *
+     * @param status status to be added
+     */
+    public void add(PdpPolicyStatus status) {
+
+        ToscaConceptIdentifier policy = status.getPolicy();
+
+        // get the entry from the relevant map, creating an entry if necessary
+        Map<ToscaConceptIdentifier, PolicyStatus> map = (status.isDeploy() ? deployMap : undeployMap);
+
+        PolicyStatus newStat = map.computeIfAbsent(policy, key -> {
+            PolicyStatus value = new PolicyStatus();
+            value.setPolicyId(policy.getName());
+            value.setPolicyVersion(policy.getVersion());
+            value.setPolicyTypeId(status.getPolicyType().getName());
+            value.setPolicyTypeVersion(status.getPolicyType().getVersion());
+            return value;
+        });
+
+        // bump the relevant count
+        switch (status.getState()) {
+            case SUCCESS:
+                newStat.setSuccessCount(newStat.getSuccessCount() + 1);
+                break;
+            case FAILURE:
+                newStat.setFailureCount(newStat.getFailureCount() + 1);
+                break;
+            default:
+                newStat.setIncompleteCount(newStat.getIncompleteCount() + 1);
+                break;
+        }
+    }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/StatusAction.java b/main/src/main/java/org/onap/policy/pap/main/notification/StatusAction.java
new file mode 100644 (file)
index 0000000..c2f1edc
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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 lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+
+@Getter
+@AllArgsConstructor
+public class StatusAction {
+    public enum Action {
+        // existing record; matches what is in the DB
+        UNCHANGED,
+        // new record; to be added to the DB
+        CREATED,
+        // existing record; to be updated
+        UPDATED,
+        // existing record; to be deleted
+        DELETED,
+    }
+
+    @Setter
+    private Action action;
+
+    private PdpPolicyStatus status;
+
+    /**
+     * Sets the action to indicate that a field within the contained status has changed.
+     */
+    public void setChanged() {
+        /*
+         * if it's a new record (i.e., action=CREATED), then it should remain new. In all
+         * other cases (even action=DELETED), it should be marked for update
+         */
+        if (action != Action.CREATED) {
+            action = Action.UPDATED;
+        }
+    }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/StatusKey.java b/main/src/main/java/org/onap/policy/pap/main/notification/StatusKey.java
new file mode 100644 (file)
index 0000000..27a33b0
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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 lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Unique key for a Policy status record.
+ */
+@Getter
+@EqualsAndHashCode
+@AllArgsConstructor
+public class StatusKey {
+    private String pdpId;
+    private ToscaConceptIdentifier policy;
+
+    public StatusKey(PdpPolicyStatus status) {
+        pdpId = status.getPdpId();
+        policy = status.getPolicy();
+    }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/DeploymentTrackerTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/DeploymentTrackerTest.java
new file mode 100644 (file)
index 0000000..22eb878
--- /dev/null
@@ -0,0 +1,273 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.models.pap.concepts.PolicyNotification;
+import org.onap.policy.models.pap.concepts.PolicyStatus;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus.PdpPolicyStatusBuilder;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus.State;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+public class DeploymentTrackerTest {
+    private static final String VERSION = "1.2.3";
+    private static final String MY_GROUP = "MyGroup";
+    private static final String MY_PDP_TYPE = "MyPdpType";
+    private static final ToscaConceptIdentifier POLICY_A = new ToscaConceptIdentifier("PolicyA", VERSION);
+    private static final ToscaConceptIdentifier POLICY_B = new ToscaConceptIdentifier("PolicyB", VERSION);
+    private static final ToscaConceptIdentifier POLICY_TYPE = new ToscaConceptIdentifier("MyPolicyType", VERSION);
+    private static final String PDP_A = "pdpA";
+    private static final String PDP_B = "pdpB";
+
+    private DeploymentTracker tracker;
+    private PdpPolicyStatusBuilder builder;
+
+    /**
+     * Sets up test objects.
+     */
+    @Before
+    public void setUp() {
+        tracker = new DeploymentTracker();
+        builder = PdpPolicyStatus.builder().deploy(true).state(State.SUCCESS).pdpGroup(MY_GROUP).pdpType(MY_PDP_TYPE)
+                        .policy(POLICY_A).policyType(POLICY_TYPE).pdpId(PDP_A);
+    }
+
+    @Test
+    public void testGetDeploymentStatus() {
+        assertThat(tracker.getDeploymentStatus()).isEmpty();
+
+        tracker.add(builder.build());
+        tracker.add(builder.policy(POLICY_B).build());
+        assertThat(tracker.getDeploymentStatus()).hasSize(2);
+
+        assertThat(tracker.getUndeploymentStatus()).isEmpty();
+    }
+
+    @Test
+    public void testGetUndeploymentStatus() {
+        builder.deploy(false);
+
+        assertThat(tracker.getUndeploymentStatus()).isEmpty();
+
+        tracker.add(builder.build());
+        tracker.add(builder.policy(POLICY_B).build());
+        assertThat(tracker.getUndeploymentStatus()).hasSize(2);
+
+        assertThat(tracker.getDeploymentStatus()).isEmpty();
+    }
+
+    @Test
+    public void testAddNotifications() {
+        DeploymentTracker newTracker = new DeploymentTracker();
+
+        newTracker.add(builder.build());
+        newTracker.add(builder.policy(POLICY_B).deploy(false).build());
+
+        PolicyNotification notif = new PolicyNotification();
+        tracker.addNotifications(notif, newTracker);
+
+        assertThat(notif.getAdded()).hasSize(1);
+        assertThat(notif.getAdded().get(0).getPolicy()).isEqualTo(POLICY_A);
+
+        assertThat(notif.getDeleted()).hasSize(1);
+        assertThat(notif.getDeleted().get(0).getPolicy()).isEqualTo(POLICY_B);
+    }
+
+    @Test
+    public void testMerge() {
+        DeploymentTracker newTracker = new DeploymentTracker();
+
+        // appears in both
+        tracker.add(builder.build());
+        newTracker.add(builder.build());
+
+        // only appears in the new tracker
+        newTracker.add(builder.policy(POLICY_B).build());
+
+        PolicyNotification notif = new PolicyNotification();
+        tracker.addNotifications(notif, newTracker);
+
+        assertThat(notif.getDeleted()).isEmpty();
+
+        // only policy B should appear
+        assertThat(notif.getAdded()).hasSize(1);
+        assertThat(notif.getAdded().get(0).getPolicy()).isEqualTo(POLICY_B);
+    }
+
+    @Test
+    public void testNeedNotification() {
+        final PolicyStatus oldStat = new PolicyStatus();
+        final PolicyStatus newStat = new PolicyStatus();
+
+        // new, complete policy - notify
+        assertThat(tracker.needNotification(null, newStat)).isTrue();
+
+        // new, incomplete policy - don't notify
+        newStat.setIncompleteCount(1);
+        assertThat(tracker.needNotification(null, newStat)).isFalse();
+        newStat.setIncompleteCount(0);
+
+        // unchanged - don't notify
+        assertThat(tracker.needNotification(oldStat, newStat)).isFalse();
+
+        // was incomplete, now complete - notify
+        oldStat.setIncompleteCount(1);
+        assertThat(tracker.needNotification(oldStat, newStat)).isTrue();
+        oldStat.setIncompleteCount(0);
+
+        // was failed, now ok - notify
+        oldStat.setFailureCount(1);
+        assertThat(tracker.needNotification(oldStat, newStat)).isTrue();
+        oldStat.setFailureCount(0);
+
+        // was failed & incomplete, now complete - notify
+        oldStat.setIncompleteCount(1);
+        oldStat.setFailureCount(1);
+        assertThat(tracker.needNotification(oldStat, newStat)).isTrue();
+        oldStat.setIncompleteCount(0);
+        oldStat.setFailureCount(0);
+
+        // was complete, now incomplete - notify
+        newStat.setIncompleteCount(1);
+        assertThat(tracker.needNotification(oldStat, newStat)).isTrue();
+        newStat.setIncompleteCount(0);
+
+        // was incomplete, still incomplete - don't notify
+        newStat.setIncompleteCount(1);
+        oldStat.setIncompleteCount(1);
+        assertThat(tracker.needNotification(oldStat, newStat)).isFalse();
+        newStat.setIncompleteCount(0);
+        oldStat.setIncompleteCount(0);
+    }
+
+    @Test
+    public void testAddMissing() {
+        DeploymentTracker newTracker = new DeploymentTracker();
+
+        // appears in both, not waiting
+        tracker.add(builder.build());
+        newTracker.add(builder.build());
+
+        // appears only in the tracker, not waiting
+        tracker.add(builder.policy(POLICY_B).build());
+
+        // appears in both, waiting
+        tracker.add(builder.policy(new ToscaConceptIdentifier("PolicyX", VERSION)).state(State.WAITING).build());
+        newTracker.add(builder.build());
+
+        // appears only in the tracker, waiting
+        tracker.add(builder.policy(new ToscaConceptIdentifier("PolicyY", VERSION)).state(State.WAITING).build());
+
+        // now extract the notifications
+        PolicyNotification notif = new PolicyNotification();
+        tracker.addNotifications(notif, newTracker);
+
+        assertThat(notif.getDeleted()).isEmpty();
+
+        // only policy B should appear
+        assertThat(notif.getAdded()).hasSize(1);
+        assertThat(notif.getAdded().get(0).getPolicy()).isEqualTo(POLICY_B);
+    }
+
+    @Test
+    public void testAddStatusAction() {
+        tracker.add(new StatusAction(StatusAction.Action.DELETED, builder.build()));
+        assertThat(tracker.getDeploymentStatus()).isEmpty();
+
+        tracker.add(new StatusAction(StatusAction.Action.UNCHANGED, builder.build()));
+        tracker.add(new StatusAction(StatusAction.Action.CREATED, builder.build()));
+        tracker.add(new StatusAction(StatusAction.Action.UPDATED, builder.build()));
+
+        Collection<PolicyStatus> result = tracker.getDeploymentStatus();
+        assertThat(result).hasSize(1);
+        PolicyStatus status = result.iterator().next();
+        assertThat(status.getSuccessCount()).isEqualTo(3);
+    }
+
+    @Test
+    public void testAddPdpPolicyStatus() {
+        tracker.add(builder.build());
+        Collection<PolicyStatus> result = tracker.getDeploymentStatus();
+        assertThat(result).hasSize(1);
+        PolicyStatus status = result.iterator().next();
+
+        assertThat(status.getFailureCount()).isZero();
+        assertThat(status.getIncompleteCount()).isZero();
+        assertThat(status.getSuccessCount()).isEqualTo(1);
+        assertThat(status.getPolicy()).isEqualTo(POLICY_A);
+        assertThat(status.getPolicyType()).isEqualTo(POLICY_TYPE);
+
+        // add another, failed
+        tracker.add(builder.pdpId(PDP_B).state(State.FAILURE).build());
+        result = tracker.getDeploymentStatus();
+        assertThat(result).hasSize(1);
+        status = result.iterator().next();
+
+        assertThat(status.getFailureCount()).isEqualTo(1);
+        assertThat(status.getIncompleteCount()).isZero();
+        assertThat(status.getSuccessCount()).isEqualTo(1);
+
+        // add another, waiting
+        tracker.add(builder.pdpId(PDP_A).state(State.WAITING).build());
+        result = tracker.getDeploymentStatus();
+        assertThat(result).hasSize(1);
+        status = result.iterator().next();
+
+        assertThat(status.getFailureCount()).isEqualTo(1);
+        assertThat(status.getIncompleteCount()).isEqualTo(1);
+        assertThat(status.getSuccessCount()).isEqualTo(1);
+
+        // different policy
+        tracker.add(builder.policy(POLICY_B).pdpId(PDP_A).state(State.WAITING).build());
+        result = tracker.getDeploymentStatus();
+        assertThat(result).hasSize(2);
+
+        List<PolicyStatus> list = new ArrayList<>(result);
+        Collections.sort(list, (rec1, rec2) -> rec1.getPolicy().compareTo(rec2.getPolicy()));
+        Iterator<PolicyStatus> iter = list.iterator();
+
+        status = iter.next();
+        assertThat(status.getPolicy()).isEqualTo(POLICY_A);
+        assertThat(status.getFailureCount()).isEqualTo(1);
+        assertThat(status.getIncompleteCount()).isEqualTo(1);
+        assertThat(status.getSuccessCount()).isEqualTo(1);
+
+        status = iter.next();
+        assertThat(status.getPolicy()).isEqualTo(POLICY_B);
+        assertThat(status.getFailureCount()).isZero();
+        assertThat(status.getIncompleteCount()).isEqualTo(1);
+        assertThat(status.getSuccessCount()).isZero();
+
+        // add undeployment record
+        tracker.add(builder.deploy(false).build());
+        assertThat(tracker.getDeploymentStatus()).hasSize(2);
+        assertThat(tracker.getUndeploymentStatus()).hasSize(1);
+    }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/StatusActionTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/StatusActionTest.java
new file mode 100644 (file)
index 0000000..3303a9b
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+/**
+ * Only test the methods that are not generated by lombok.
+ */
+public class StatusActionTest {
+
+    @Test
+    public void testSetChanged() {
+        StatusAction status = new StatusAction(StatusAction.Action.UNCHANGED, null);
+
+        // new records should always remain new - action should not change
+        status.setAction(StatusAction.Action.CREATED);
+        status.setChanged();
+        assertThat(status.getAction()).isEqualTo(StatusAction.Action.CREATED);
+
+        // all other actions should change
+
+        status.setAction(StatusAction.Action.UNCHANGED);
+        status.setChanged();
+        assertThat(status.getAction()).isEqualTo(StatusAction.Action.UPDATED);
+
+        status.setAction(StatusAction.Action.DELETED);
+        status.setChanged();
+        assertThat(status.getAction()).isEqualTo(StatusAction.Action.UPDATED);
+
+        status.setAction(StatusAction.Action.UPDATED);
+        status.setChanged();
+        assertThat(status.getAction()).isEqualTo(StatusAction.Action.UPDATED);
+    }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/notification/StatusKeyTest.java b/main/src/test/java/org/onap/policy/pap/main/notification/StatusKeyTest.java
new file mode 100644 (file)
index 0000000..558c6bc
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 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.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Only test the methods that are not generated by lombok.
+ */
+public class StatusKeyTest {
+
+    @Test
+    public void testStatusKeyPdpPolicyStatus() {
+        ToscaConceptIdentifier myPolicy = new ToscaConceptIdentifier();
+
+        StatusKey key = new StatusKey(PdpPolicyStatus.builder().pdpId("myPdp").policy(myPolicy).build());
+
+        assertThat(key.getPdpId()).isEqualTo("myPdp");
+        assertThat(key.getPolicy()).isSameAs(myPolicy);
+    }
+}