2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2022 Bell Canada. All rights reserved.
7 * Modifications Copyright (C) 2023 Nordix Foundation.
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.pap.main.notification;
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.mockito.ArgumentMatchers.anyString;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
30 import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
31 import java.util.HashMap;
32 import java.util.List;
35 import lombok.NonNull;
36 import org.apache.commons.lang3.builder.CompareToBuilder;
37 import org.junit.jupiter.api.AfterAll;
38 import org.junit.jupiter.api.AfterEach;
39 import org.junit.jupiter.api.BeforeAll;
40 import org.junit.jupiter.api.BeforeEach;
41 import org.junit.jupiter.api.Test;
42 import org.mockito.ArgumentCaptor;
43 import org.mockito.Captor;
44 import org.mockito.Mock;
45 import org.mockito.MockitoAnnotations;
46 import org.onap.policy.common.utils.services.Registry;
47 import org.onap.policy.models.pap.concepts.PolicyNotification;
48 import org.onap.policy.models.pap.concepts.PolicyStatus;
49 import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
50 import org.onap.policy.models.pdp.concepts.PdpPolicyStatus.PdpPolicyStatusBuilder;
51 import org.onap.policy.models.pdp.concepts.PdpPolicyStatus.State;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
53 import org.onap.policy.pap.main.PapConstants;
54 import org.onap.policy.pap.main.notification.StatusAction.Action;
55 import org.onap.policy.pap.main.service.PolicyStatusService;
57 public class DeploymentStatusTest {
59 private static final String VERSION = "1.2.3";
60 private static final @NonNull String GROUP_A = "groupA";
61 private static final String PDP_A = "pdpA";
62 private static final String PDP_B = "pdpB";
63 private static final String PDP_C = "pdpC";
64 private static final String PDP_D = "pdpD";
65 private static final String PDP_TYPE = "MyPdpType";
66 private static final ToscaConceptIdentifier POLICY_A = new ToscaConceptIdentifier("MyPolicyA", VERSION);
67 private static final ToscaConceptIdentifier POLICY_B = new ToscaConceptIdentifier("MyPolicyB", VERSION);
68 private static final ToscaConceptIdentifier POLICY_C = new ToscaConceptIdentifier("MyPolicyC", VERSION);
69 private static final ToscaConceptIdentifier POLICY_D = new ToscaConceptIdentifier("MyPolicyD", VERSION);
70 private static final ToscaConceptIdentifier POLICY_TYPE = new ToscaConceptIdentifier("MyPolicyType", VERSION);
72 private PdpPolicyStatusBuilder builder;
75 private ArgumentCaptor<List<PdpPolicyStatus>> created;
77 private ArgumentCaptor<List<PdpPolicyStatus>> updated;
79 private ArgumentCaptor<List<PdpPolicyStatus>> deleted;
82 private PolicyStatusService policyStatusService;
84 private DeploymentStatus tracker;
86 AutoCloseable autoCloseable;
89 * Set up the meter registry for tests.
92 public static void setUpBeforeClass() {
93 Registry.registerOrReplace(PapConstants.REG_METER_REGISTRY, new SimpleMeterRegistry());
97 * Tear down the meter registry after tests.
100 public static void tearDownAfterClass() {
101 Registry.unregister(PapConstants.REG_METER_REGISTRY);
108 public void setUp() {
109 autoCloseable = MockitoAnnotations.openMocks(this);
110 tracker = new DeploymentStatus(policyStatusService);
113 builder = PdpPolicyStatus.builder()
118 .policyType(POLICY_TYPE)
120 .state(State.SUCCESS);
126 void tearDown() throws Exception {
127 autoCloseable.close();
131 void testAddNotifications() {
132 PdpPolicyStatus create = builder.pdpId("created").state(State.FAILURE).build();
133 PdpPolicyStatus update = builder.pdpId("updated").state(State.SUCCESS).build();
134 PdpPolicyStatus delete = builder.pdpId("deleted").state(State.SUCCESS).build();
135 PdpPolicyStatus unchange = builder.pdpId("unchanged").state(State.FAILURE).build();
138 tracker.getRecordMap().putAll(makeMap(
139 Action.CREATED, create,
140 Action.UPDATED, update,
141 Action.DELETED, delete,
142 Action.UNCHANGED, unchange
146 PolicyNotification notif = new PolicyNotification();
148 tracker.addNotifications(notif);
149 assertThat(notif.getAdded()).hasSize(1);
150 assertThat(notif.getDeleted()).isEmpty();
152 PolicyStatus status = notif.getAdded().get(0);
153 assertThat(status.getFailureCount()).isEqualTo(2);
154 assertThat(status.getIncompleteCount()).isZero();
155 assertThat(status.getSuccessCount()).isEqualTo(1);
156 assertThat(status.getPolicy()).isEqualTo(POLICY_A);
157 assertThat(status.getPolicyType()).isEqualTo(POLICY_TYPE);
160 * repeat - should be no notifications
162 notif = new PolicyNotification();
163 tracker.addNotifications(notif);
164 assertThat(notif.getAdded()).isEmpty();
165 assertThat(notif.getDeleted()).isEmpty();
169 void testLoadByGroup() {
170 PdpPolicyStatus status1 = builder.build();
171 PdpPolicyStatus status2 = builder.policy(POLICY_B).build();
172 PdpPolicyStatus status3 = builder.policy(POLICY_A).pdpId(PDP_B).build();
174 when(policyStatusService.getGroupPolicyStatus(GROUP_A)).thenReturn(List.of(status1, status2, status3));
176 tracker.loadByGroup(GROUP_A);
179 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
180 Action.UNCHANGED, status1,
181 Action.UNCHANGED, status2,
182 Action.UNCHANGED, status3
186 // try again - should not reload
187 tracker.loadByGroup(GROUP_A);
188 verify(policyStatusService).getGroupPolicyStatus(anyString());
192 void testFlushPdpNotification() {
193 PdpPolicyStatus create = builder.pdpId("created").state(State.FAILURE).build();
194 tracker.getRecordMap().putAll(makeMap(Action.CREATED, create));
196 PolicyNotification notif = new PolicyNotification();
198 tracker.flush(notif);
200 assertThat(notif.getAdded()).hasSize(1);
201 assertThat(notif.getDeleted()).isEmpty();
206 PdpPolicyStatus create1 = builder.pdpId("createA").build();
207 PdpPolicyStatus create2 = builder.pdpId("createB").build();
208 PdpPolicyStatus update1 = builder.pdpId("updateA").build();
209 PdpPolicyStatus update2 = builder.pdpId("updateB").build();
210 PdpPolicyStatus delete1 = builder.pdpId("deleteA").build();
211 PdpPolicyStatus delete2 = builder.pdpId("deleteB").build();
212 PdpPolicyStatus unchange1 = builder.pdpId("unchangeA").build();
213 PdpPolicyStatus unchange2 = builder.pdpId("unchangeB").build();
216 tracker.getRecordMap().putAll(makeMap(
217 Action.CREATED, create1,
218 Action.CREATED, create2,
219 Action.UPDATED, update1,
220 Action.UPDATED, update2,
221 Action.DELETED, delete1,
222 Action.DELETED, delete2,
223 Action.UNCHANGED, unchange1,
224 Action.UNCHANGED, unchange2
230 verify(policyStatusService).cudPolicyStatus(created.capture(), updated.capture(), deleted.capture());
232 assertThat(sort(created.getValue())).isEqualTo(List.of(create1, create2));
233 assertThat(sort(updated.getValue())).isEqualTo(List.of(update1, update2));
234 assertThat(sort(deleted.getValue())).isEqualTo(List.of(delete1, delete2));
237 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
238 Action.UNCHANGED, create1,
239 Action.UNCHANGED, create2,
240 Action.UNCHANGED, update1,
241 Action.UNCHANGED, update2,
242 Action.UNCHANGED, unchange1,
243 Action.UNCHANGED, unchange2
249 void testDeleteUndeployments() {
250 builder.deploy(true);
251 PdpPolicyStatus delete = builder.policy(POLICY_A).build();
252 PdpPolicyStatus deployedComplete = builder.policy(POLICY_B).build();
254 builder.deploy(false);
255 PdpPolicyStatus undepComplete1 = builder.policy(POLICY_C).build();
256 PdpPolicyStatus undepIncomplete1 = builder.policy(POLICY_D).build();
258 builder.pdpId(PDP_B);
259 PdpPolicyStatus undepComplete2 = builder.policy(POLICY_C).build();
260 PdpPolicyStatus undepIncomplete2 = builder.policy(POLICY_D).state(State.WAITING).build();
263 Map<StatusKey, StatusAction> map = makeMap(
264 Action.DELETED, delete,
265 Action.UNCHANGED, deployedComplete,
266 Action.UNCHANGED, undepComplete1,
267 Action.UNCHANGED, undepComplete2,
268 Action.UNCHANGED, undepIncomplete1,
269 Action.UNCHANGED, undepIncomplete2
273 tracker.getRecordMap().putAll(map);
275 tracker.deleteUndeployments();
277 // the completed undeployments should now be marked DELETED
280 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
281 Action.DELETED, delete,
282 Action.UNCHANGED, deployedComplete,
283 Action.DELETED, undepComplete1,
284 Action.DELETED, undepComplete2,
285 Action.UNCHANGED, undepIncomplete1,
286 Action.UNCHANGED, undepIncomplete2
292 void testDeleteDeploymentString() {
293 PdpPolicyStatus statusaa = builder.pdpId(PDP_A).policy(POLICY_A).build();
294 PdpPolicyStatus statusab = builder.pdpId(PDP_A).policy(POLICY_B).build();
295 PdpPolicyStatus statusba = builder.pdpId(PDP_B).policy(POLICY_A).build();
296 PdpPolicyStatus statuscb = builder.pdpId(PDP_C).policy(POLICY_B).build();
299 tracker.getRecordMap().putAll(makeMap(
300 Action.UNCHANGED, statusaa,
301 Action.UNCHANGED, statusab,
302 Action.UNCHANGED, statusba,
303 Action.UNCHANGED, statuscb
307 tracker.deleteDeployment(PDP_A);
310 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
311 Action.DELETED, statusaa,
312 Action.DELETED, statusab,
313 Action.UNCHANGED, statusba,
314 Action.UNCHANGED, statuscb
320 void testDeleteDeploymentToscaConceptIdentifierBoolean() {
321 PdpPolicyStatus deploy1A = builder.policy(POLICY_A).build();
322 PdpPolicyStatus deploy2A = builder.policy(POLICY_A).pdpId(PDP_B).build();
323 PdpPolicyStatus deployB = builder.policy(POLICY_B).pdpId(PDP_A).build();
325 builder.deploy(false);
326 PdpPolicyStatus undeployA = builder.policy(POLICY_A).build();
327 PdpPolicyStatus undeployB = builder.policy(POLICY_B).build();
330 tracker.getRecordMap().putAll(makeMap(
331 Action.UNCHANGED, deploy1A,
332 Action.UNCHANGED, deploy2A,
333 Action.UNCHANGED, deployB,
334 Action.UNCHANGED, undeployA,
335 Action.UNCHANGED, undeployB
339 tracker.deleteDeployment(POLICY_A, true);
342 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
343 Action.DELETED, deploy1A,
344 Action.DELETED, deploy2A,
345 Action.UNCHANGED, deployB,
346 Action.UNCHANGED, undeployA,
347 Action.UNCHANGED, undeployB
351 tracker.deleteDeployment(POLICY_B, false);
354 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
355 Action.DELETED, deploy1A,
356 Action.DELETED, deploy2A,
357 Action.UNCHANGED, deployB,
358 Action.UNCHANGED, undeployA,
359 Action.DELETED, undeployB
365 void testDeleteDeploymentBiPredicateOfStatusKeyStatusAction() {
366 PdpPolicyStatus create1 = builder.pdpId(PDP_A).build();
367 PdpPolicyStatus delete = builder.pdpId(PDP_B).build();
368 PdpPolicyStatus update = builder.pdpId(PDP_C).build();
369 PdpPolicyStatus unchange = builder.pdpId(PDP_D).build();
371 PdpPolicyStatus create2 = builder.pdpId(PDP_B).build();
374 tracker.getRecordMap().putAll(makeMap(
375 Action.CREATED, create1,
376 Action.CREATED, create2,
377 Action.DELETED, delete,
378 Action.UPDATED, update,
379 Action.UNCHANGED, unchange
383 tracker.deleteDeployment(POLICY_A, true);
386 assertThat(tracker.getRecordMap()).isEqualTo(makeMap(
387 Action.DELETED, delete,
388 Action.DELETED, update,
389 Action.DELETED, unchange
396 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, true);
398 assertThat(tracker.getRecordMap()).hasSize(1);
400 StatusAction status2 = tracker.getRecordMap().values().iterator().next();
402 assertThat(status2.getAction()).isEqualTo(Action.CREATED);
403 assertThat(status2.getStatus().getState()).isEqualTo(State.WAITING);
404 assertThat(status2.getStatus().isDeploy()).isTrue();
407 * repeat - should be the same status
409 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, true);
411 assertThat(tracker.getRecordMap()).hasSize(1);
412 assertThat(tracker.getRecordMap().values().iterator().next()).isSameAs(status2);
413 assertThat(status2.getAction()).isEqualTo(Action.CREATED);
414 assertThat(status2.getStatus().getState()).isEqualTo(State.WAITING);
415 assertThat(status2.getStatus().isDeploy()).isTrue();
418 * repeat, with different values - should be unchanged
420 status2.setAction(Action.UNCHANGED);
421 status2.getStatus().setDeploy(true);
422 status2.getStatus().setState(State.SUCCESS);
424 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, true);
426 assertThat(tracker.getRecordMap()).hasSize(1);
427 assertThat(tracker.getRecordMap().values().iterator().next()).isSameAs(status2);
428 assertThat(status2.getAction()).isEqualTo(Action.UNCHANGED);
429 assertThat(status2.getStatus().getState()).isEqualTo(State.SUCCESS);
430 assertThat(status2.getStatus().isDeploy()).isTrue();
433 * incorrect "deploy" value - should update it
435 status2.setAction(Action.UNCHANGED);
436 status2.getStatus().setDeploy(true);
438 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, false);
440 assertThat(status2.getAction()).isEqualTo(Action.UPDATED);
441 assertThat(status2.getStatus().getState()).isEqualTo(State.WAITING);
442 assertThat(status2.getStatus().isDeploy()).isFalse();
445 * marked for deletion - should reinstate it
447 status2.setAction(Action.DELETED);
448 status2.getStatus().setState(State.FAILURE);
449 status2.getStatus().setDeploy(false);
451 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, false);
453 assertThat(status2.getAction()).isEqualTo(Action.UPDATED);
454 assertThat(status2.getStatus().getState()).isEqualTo(State.FAILURE);
455 assertThat(status2.getStatus().isDeploy()).isFalse();
459 void testCompleteDeploy() {
460 tracker.deploy(PDP_A, POLICY_A, POLICY_TYPE, GROUP_A, PDP_TYPE, true);
461 assertThat(tracker.getRecordMap()).hasSize(1);
463 // deployed, but not expected to be deployed - record should be left as is
464 checkCompleteDeploy(true, Set.of(), Set.of(), Action.UNCHANGED, State.WAITING);
465 checkCompleteDeploy(true, Set.of(), Set.of(POLICY_A), Action.UNCHANGED, State.WAITING);
467 // expected, but not actually deployed - failure
468 checkCompleteDeploy(true, Set.of(POLICY_A), Set.of(), Action.UPDATED, State.FAILURE);
470 // expected and actually deployed - success
471 checkCompleteDeploy(true, Set.of(POLICY_A), Set.of(POLICY_A), Action.UPDATED, State.SUCCESS);
472 checkCompleteDeploy(true, Set.of(POLICY_A, POLICY_B), Set.of(POLICY_A), Action.UPDATED, State.SUCCESS);
474 // not expected and not actually deployed - success
475 checkCompleteDeploy(false, Set.of(), Set.of(), Action.UPDATED, State.SUCCESS);
477 // not expected, but actually deployed - failure
478 checkCompleteDeploy(false, Set.of(), Set.of(POLICY_A), Action.UPDATED, State.FAILURE);
480 // undeployed, but expected to be deployed - record should be left as is
481 checkCompleteDeploy(false, Set.of(POLICY_A), Set.of(), Action.UNCHANGED, State.WAITING);
482 checkCompleteDeploy(false, Set.of(POLICY_A), Set.of(POLICY_A), Action.UNCHANGED, State.WAITING);
483 checkCompleteDeploy(false, Set.of(POLICY_A, POLICY_B), Set.of(POLICY_A), Action.UNCHANGED, State.WAITING);
486 * Try a case where the state is already correct.
488 StatusAction status = tracker.getRecordMap().values().iterator().next();
489 status.getStatus().setDeploy(false);
490 status.setAction(Action.UNCHANGED);
491 status.getStatus().setState(State.SUCCESS);
493 tracker.completeDeploy(PDP_A, Set.of(), Set.of());
495 assertThat(status.getAction()).isEqualTo(Action.UNCHANGED);
496 assertThat(status.getStatus().getState()).isEqualTo(State.SUCCESS);
499 * Try a case where the PDP does not match the record.
501 status.getStatus().setDeploy(false);
502 status.setAction(Action.UNCHANGED);
503 status.getStatus().setState(State.WAITING);
505 tracker.completeDeploy(PDP_B, Set.of(), Set.of());
507 assertThat(status.getAction()).isEqualTo(Action.UNCHANGED);
508 assertThat(status.getStatus().getState()).isEqualTo(State.WAITING);
511 private void checkCompleteDeploy(boolean deploy, Set<ToscaConceptIdentifier> expected,
512 Set<ToscaConceptIdentifier> actual, Action action, State state) {
514 StatusAction status = tracker.getRecordMap().values().iterator().next();
515 status.getStatus().setDeploy(deploy);
516 status.setAction(Action.UNCHANGED);
517 status.getStatus().setState(State.WAITING);
519 tracker.completeDeploy(PDP_A, expected, actual);
521 assertThat(status.getAction()).isEqualTo(action);
522 assertThat(status.getStatus().getState()).isEqualTo(state);
525 private List<PdpPolicyStatus> sort(List<PdpPolicyStatus> list) {
527 list.sort((rec1, rec2) -> {
530 return new CompareToBuilder()
531 .append(rec1.getPdpId(), rec2.getPdpId())
532 .append(rec1.getPolicy(), rec2.getPolicy())
543 * @param data pairs of (Action, PdpPolicyStatus)
544 * @return a new map containing the given data
546 private Map<StatusKey, StatusAction> makeMap(Object... data) {
547 Map<StatusKey, StatusAction> map = new HashMap<>();
549 assert (data.length % 2 == 0);
551 for (int idata = 0; idata < data.length; idata += 2) {
552 Action action = (Action) data[idata];
553 PdpPolicyStatus status = (PdpPolicyStatus) data[idata + 1];
554 map.put(new StatusKey(status), new StatusAction(action, status));