2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2021, 2023 Nordix Foundation.
7 * Modifications Copyright (C) 2022 Bell Canada. All rights reserved.
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.rest;
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
27 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
28 import static org.assertj.core.api.Assertions.assertThatThrownBy;
29 import static org.junit.jupiter.api.Assertions.assertEquals;
30 import static org.junit.jupiter.api.Assertions.assertFalse;
31 import static org.junit.jupiter.api.Assertions.assertNull;
32 import static org.junit.jupiter.api.Assertions.assertSame;
33 import static org.junit.jupiter.api.Assertions.assertTrue;
34 import static org.mockito.ArgumentMatchers.any;
35 import static org.mockito.ArgumentMatchers.anyBoolean;
36 import static org.mockito.Mockito.mock;
37 import static org.mockito.Mockito.never;
38 import static org.mockito.Mockito.times;
39 import static org.mockito.Mockito.verify;
40 import static org.mockito.Mockito.when;
42 import jakarta.ws.rs.core.Response.Status;
43 import java.util.ArrayList;
44 import java.util.Collection;
45 import java.util.Collections;
46 import java.util.Comparator;
47 import java.util.Iterator;
48 import java.util.List;
49 import org.apache.commons.lang3.tuple.Pair;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52 import org.mockito.ArgumentCaptor;
53 import org.onap.policy.models.base.PfModelException;
54 import org.onap.policy.models.pap.concepts.PolicyNotification;
55 import org.onap.policy.models.pdp.concepts.PdpGroup;
56 import org.onap.policy.models.pdp.concepts.PdpStateChange;
57 import org.onap.policy.models.pdp.concepts.PdpUpdate;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
59 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifierOptVersion;
60 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
61 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
62 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
63 import org.onap.policy.pap.main.notification.DeploymentStatus;
64 import org.onap.policy.pap.main.service.PolicyStatusService;
66 class TestSessionData extends ProviderSuper {
67 private static final String GROUP_NAME = "groupA";
68 private static final String PDP_TYPE = "MySubGroup";
69 private static final String PDP1 = "pdp_1";
70 private static final String PDP2 = "pdp_2";
71 private static final String PDP3 = "pdp_3";
72 private static final String POLICY_VERSION_PREFIX = "1.2.";
73 private static final String POLICY_NAME = "myPolicy";
74 private static final String POLICY_VERSION = POLICY_VERSION_PREFIX + "3";
75 private static final String POLICY_TYPE = "myType";
76 private static final String POLICY_TYPE_VERSION = "10.20.30";
77 private static final String EXPECTED_EXCEPTION = "expected exception";
79 private SessionData session;
80 private ToscaConceptIdentifierOptVersion ident;
81 private ToscaConceptIdentifier type;
82 private ToscaConceptIdentifier type2;
83 private PdpGroup group1;
84 private PdpGroup group2;
87 * Initializes mocks and a session.
89 * @throws Exception if an error occurs
93 public void setUp() throws Exception {
96 ident = new ToscaConceptIdentifierOptVersion(POLICY_NAME, POLICY_VERSION);
97 type = new ToscaConceptIdentifier(POLICY_TYPE, POLICY_TYPE_VERSION);
98 type2 = new ToscaConceptIdentifier(POLICY_TYPE, POLICY_TYPE_VERSION + "0");
99 group1 = loadGroup("group1.json");
100 group2 = loadGroup("group2.json");
102 session = new SessionData(DEFAULT_USER, toscaService, pdpGroupService, policyStatusService, policyAuditService);
106 void testGetPolicyType() throws Exception {
107 ToscaPolicyType policy1 = makePolicyType(POLICY_TYPE, POLICY_TYPE_VERSION);
108 when(toscaService.getPolicyTypeList(POLICY_TYPE, POLICY_TYPE_VERSION)).thenReturn(List.of(policy1));
110 assertSame(policy1, session.getPolicyType(type));
112 // retrieve a second time - should use cache
113 assertSame(policy1, session.getPolicyType(type));
117 void testGetPolicyType_NotFound() throws Exception {
118 when(toscaService.getPolicyTypeList(any(), any())).thenReturn(Collections.emptyList());
120 assertNull(session.getPolicyType(type));
124 void testGetPolicyType_DaoEx() throws Exception {
125 PfModelException ex = new PfModelException(Status.INTERNAL_SERVER_ERROR, EXPECTED_EXCEPTION);
126 when(toscaService.getPolicyTypeList(POLICY_TYPE, POLICY_TYPE_VERSION)).thenThrow(ex);
128 assertThatThrownBy(() -> session.getPolicyType(type)).isSameAs(ex);
132 void testGetPolicy_NullVersion() throws Exception {
133 ToscaPolicy policy1 = makePolicy(POLICY_NAME, POLICY_VERSION);
134 when(toscaService.getFilteredPolicyList(any())).thenReturn(List.of(policy1));
136 ident.setVersion(null);
137 assertSame(policy1, session.getPolicy(ident));
139 ToscaTypedEntityFilter<ToscaPolicy> filter = getPolicyFilter();
140 assertEquals(POLICY_NAME, filter.getName());
141 assertEquals(ToscaTypedEntityFilter.LATEST_VERSION, filter.getVersion());
142 assertNull(filter.getVersionPrefix());
144 // retrieve a second time using full version - should use cache
145 assertSame(policy1, session.getPolicy(new ToscaConceptIdentifierOptVersion(policy1.getIdentifier())));
146 verify(toscaService).getFilteredPolicyList(any());
150 void testGetPolicy_MajorVersion() throws Exception {
151 ToscaPolicy policy1 = makePolicy(POLICY_NAME, POLICY_VERSION);
152 when(toscaService.getFilteredPolicyList(any())).thenReturn(List.of(policy1));
154 ident.setVersion("1");
155 assertSame(policy1, session.getPolicy(ident));
157 ToscaTypedEntityFilter<ToscaPolicy> filter = getPolicyFilter();
158 assertEquals(POLICY_NAME, filter.getName());
159 assertEquals(ToscaTypedEntityFilter.LATEST_VERSION, filter.getVersion());
160 assertEquals("1.", filter.getVersionPrefix());
162 // retrieve a second time using full version - should use cache
163 assertSame(policy1, session.getPolicy(new ToscaConceptIdentifierOptVersion(policy1.getIdentifier())));
164 verify(toscaService).getFilteredPolicyList(any());
168 void testGetPolicy_MajorMinorVersion() throws Exception {
169 ToscaPolicy policy1 = makePolicy(POLICY_NAME, POLICY_VERSION);
170 when(toscaService.getFilteredPolicyList(any())).thenReturn(List.of(policy1));
172 ident.setVersion(POLICY_VERSION);
173 assertSame(policy1, session.getPolicy(ident));
175 ToscaTypedEntityFilter<ToscaPolicy> filter = getPolicyFilter();
176 assertEquals(POLICY_NAME, filter.getName());
177 assertEquals(POLICY_VERSION, filter.getVersion());
178 assertNull(filter.getVersionPrefix());
180 // retrieve a second time using full version - should use cache
181 assertSame(policy1, session.getPolicy(new ToscaConceptIdentifierOptVersion(policy1.getIdentifier())));
182 verify(toscaService).getFilteredPolicyList(any());
186 void testGetPolicy_NotFound() throws Exception {
187 when(toscaService.getFilteredPolicyList(any())).thenReturn(Collections.emptyList());
189 assertNull(session.getPolicy(ident));
193 void testGetPolicy_DaoEx() throws Exception {
194 PfModelException ex = new PfModelException(Status.INTERNAL_SERVER_ERROR, EXPECTED_EXCEPTION);
195 when(toscaService.getFilteredPolicyList(any())).thenThrow(ex);
197 assertThatThrownBy(() -> session.getPolicy(ident)).isSameAs(ex);
201 void testIsVersionPrefix() {
202 assertTrue(SessionData.isVersionPrefix("1"));
203 assertTrue(SessionData.isVersionPrefix("12"));
204 assertTrue(SessionData.isVersionPrefix("1.2"));
205 assertTrue(SessionData.isVersionPrefix("1.23"));
207 assertFalse(SessionData.isVersionPrefix("1."));
208 assertFalse(SessionData.isVersionPrefix("1.2."));
209 assertFalse(SessionData.isVersionPrefix("1.2.3"));
210 assertFalse(SessionData.isVersionPrefix("1.2.3."));
211 assertFalse(SessionData.isVersionPrefix("1.2.3.4"));
215 void testAddRequests_testGetPdpStateChanges_testGetPdpUpdates() {
216 // pre-load with a update and state-change for other PDPs
217 PdpUpdate update2 = makeUpdate(PDP2);
218 session.addUpdate(update2);
220 PdpStateChange change3 = makeStateChange(PDP3);
221 session.addStateChange(change3);
224 PdpUpdate update = makeUpdate(PDP1);
225 PdpStateChange change = makeStateChange(PDP1);
226 session.addRequests(update, change);
227 verifyRequests(update, update2, change, change3);
230 * repeat with a new pair
232 update = makeUpdate(PDP1);
233 change = makeStateChange(PDP1);
234 session.addRequests(update, change);
235 verifyRequests(update, update2, change, change3);
237 // just make an update this time
238 update = makeUpdate(PDP1);
239 session.addUpdate(update);
240 verifyRequests(update, update2, change, change3);
243 private void verifyRequests(PdpUpdate update, PdpUpdate update2, PdpStateChange change, PdpStateChange change3) {
244 List<Pair<PdpUpdate, PdpStateChange>> requests = sort(session.getPdpRequests(), this::compare);
245 assertEquals(3, requests.size());
247 System.out.println(requests);
248 System.out.println(update);
250 Iterator<Pair<PdpUpdate, PdpStateChange>> reqiter = requests.iterator();
251 Pair<PdpUpdate, PdpStateChange> pair = reqiter.next();
252 assertSame(update, pair.getLeft());
253 assertSame(change, pair.getRight());
255 pair = reqiter.next();
256 assertSame(update2, pair.getLeft());
257 assertSame(null, pair.getRight());
259 pair = reqiter.next();
260 assertSame(null, pair.getLeft());
261 assertSame(change3, pair.getRight());
263 // verify individual lists
264 List<PdpUpdate> updates = List.of(update, update2);
265 assertEquals(sort(updates, this::compare), sort(session.getPdpUpdates(), this::compare));
267 List<PdpStateChange> changes = List.of(change, change3);
268 assertEquals(sort(changes, this::compare), sort(session.getPdpStateChanges(), this::compare));
272 void testAddRequests_MismatchedNames() {
273 PdpUpdate update = makeUpdate(PDP1);
274 PdpStateChange change = makeStateChange(PDP2);
275 assertThatIllegalArgumentException().isThrownBy(() -> session.addRequests(update, change))
276 .withMessage("PDP name mismatch pdp_1, pdp_2");
280 void testAddUpdate_testGetPdpUpdates() {
281 // several different updates, but one duplicate
282 PdpUpdate update1 = makeUpdate(PDP1);
283 session.addUpdate(update1);
285 PdpUpdate update2 = makeUpdate(PDP2);
286 session.addUpdate(update2);
288 PdpUpdate update3 = makeUpdate(PDP3);
289 session.addUpdate(update3);
291 List<PdpUpdate> lst = sort(getUpdateRequests(), this::compare);
292 assertEquals(List.of(update1, update2, update3).toString(), lst.toString());
295 update2 = makeUpdate(PDP2);
296 session.addUpdate(update2);
298 lst = sort(getUpdateRequests(), this::compare);
299 assertEquals(List.of(update1, update2, update3).toString(), lst.toString());
303 void testAddStateChange_testGetPdpStateChanges() {
304 // several different changes, but one duplicate
305 PdpStateChange change1 = makeStateChange(PDP1);
306 session.addStateChange(change1);
308 PdpStateChange change2 = makeStateChange(PDP2);
309 session.addStateChange(change2);
311 PdpStateChange change3 = makeStateChange(PDP3);
312 session.addStateChange(change3);
314 List<PdpStateChange> lst = sort(getStateChangeRequests(), this::compare);
315 assertEquals(List.of(change1, change2, change3).toString(), lst.toString());
318 change2 = makeStateChange(PDP2);
319 session.addStateChange(change2);
321 lst = sort(getStateChangeRequests(), this::compare);
322 assertEquals(List.of(change1, change2, change3).toString(), lst.toString());
325 private ToscaPolicyType makePolicyType(String name, String version) {
326 ToscaPolicyType type = new ToscaPolicyType();
329 type.setVersion(version);
334 private ToscaPolicy makePolicy(String name, String version) {
335 ToscaPolicy policy = new ToscaPolicy();
337 policy.setName(name);
338 policy.setVersion(version);
344 void testCreate() throws Exception {
345 assertTrue(session.isUnchanged());
347 session.create(group1);
348 assertSame(group1, session.getGroup(group1.getName()));
349 assertFalse(session.isUnchanged());
352 session.create(group2);
353 assertSame(group1, session.getGroup(group1.getName()));
354 assertSame(group2, session.getGroup(group2.getName()));
355 assertFalse(session.isUnchanged());
358 assertThatIllegalStateException().isThrownBy(() -> session.create(group1))
359 .withMessage("group already cached: groupA");
364 assertTrue(session.isUnchanged());
366 // force the groups into the cache
367 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1, group2));
368 session.getActivePdpGroupsByPolicyType(type);
373 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1));
374 PdpGroup newgrp = new PdpGroup(group1);
375 session.update(newgrp);
376 assertFalse(session.isUnchanged());
379 newgrp = new PdpGroup(group1);
380 session.update(newgrp);
381 assertFalse(session.isUnchanged());
386 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group2));
387 newgrp = new PdpGroup(group2);
388 session.update(newgrp);
389 assertFalse(session.isUnchanged());
392 newgrp = new PdpGroup(group2);
393 session.update(newgrp);
394 assertFalse(session.isUnchanged());
398 void testUpdate_NotInCache() {
399 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1));
401 assertThatIllegalStateException().isThrownBy(() -> session.update(new PdpGroup(group1)))
402 .withMessage("group not cached: groupA");
406 void testGetGroup() throws Exception {
407 when(pdpGroupService.getPdpGroups(GROUP_NAME)).thenReturn(List.of(group1));
409 assertSame(group1, session.getGroup(GROUP_NAME));
410 verify(pdpGroupService).getPdpGroups(any(String.class));
413 assertSame(group1, session.getGroup(GROUP_NAME));
415 // should not access dao again
416 verify(pdpGroupService, times(1)).getPdpGroups(any(String.class));
420 void testGetGroup_NotFound() throws Exception {
421 when(pdpGroupService.getPdpGroups(GROUP_NAME)).thenReturn(Collections.emptyList());
423 assertNull(session.getGroup(GROUP_NAME));
424 verify(pdpGroupService).getPdpGroups(any(String.class));
427 assertNull(session.getGroup(GROUP_NAME));
429 // SHOULD access dao again
430 verify(pdpGroupService, times(2)).getPdpGroups(GROUP_NAME);
433 when(pdpGroupService.getPdpGroups(GROUP_NAME)).thenReturn(List.of(group1));
434 assertSame(group1, session.getGroup(GROUP_NAME));
435 verify(pdpGroupService, times(3)).getPdpGroups(GROUP_NAME);
439 void testGetActivePdpGroupsByPolicyType() {
440 List<PdpGroup> groups = List.of(group1, group2);
441 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(groups);
444 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type));
445 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type));
446 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type));
448 // only invoked once - should have used the cache for the rest
449 verify(pdpGroupService, times(1)).getFilteredPdpGroups(any());
453 void testAddGroup() {
454 List<PdpGroup> groups = List.of(group1, group2);
455 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(groups);
457 // query by each type
458 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type));
459 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type2));
461 // invoked once for each type
462 verify(pdpGroupService, times(2)).getFilteredPdpGroups(any());
464 // repeat - should be no more invocations
465 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type));
466 assertEquals(groups, session.getActivePdpGroupsByPolicyType(type2));
467 verify(pdpGroupService, times(2)).getFilteredPdpGroups(any());
471 void testUpdateDb() {
472 // force the groups into the cache
473 PdpGroup group3 = loadGroup("group3.json");
474 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1, group2, group3));
475 session.getActivePdpGroupsByPolicyType(type);
477 // create groups 4 & 5
478 PdpGroup group4 = loadGroup("group4.json");
479 session.create(group4);
481 PdpGroup group5 = loadGroup("group5.json");
482 session.create(group5);
485 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1));
486 PdpGroup newgrp1 = new PdpGroup(group1);
487 session.update(newgrp1);
490 newgrp1 = new PdpGroup(newgrp1);
491 session.update(newgrp1);
494 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group3));
495 PdpGroup newgrp3 = new PdpGroup(group3);
496 session.update(newgrp3);
499 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group5));
500 PdpGroup newgrp5 = new PdpGroup(group5);
501 session.update(newgrp5);
503 // push the changes to the DB
504 PolicyNotification notif = new PolicyNotification();
505 session.updateDb(notif);
506 assertThat(notif.getAdded()).isEmpty();
508 // expect one create for groups 4 & 5 (group5 replaced by newgrp5)
509 List<PdpGroup> creates = getGroupCreates();
510 assertEquals(2, creates.size());
511 assertSame(group4, creates.get(0));
512 assertSame(newgrp5, creates.get(1));
514 // expect one update for groups 1 & 3
515 List<PdpGroup> updates = getGroupUpdates();
516 assertEquals(2, updates.size());
517 assertSame(newgrp1, updates.get(0));
518 assertSame(newgrp3, updates.get(1));
522 void testUpdateDb_Empty() {
523 // force data into the cache
524 when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(List.of(group1, group2));
525 session.getActivePdpGroupsByPolicyType(type);
527 PolicyNotification notif = new PolicyNotification();
528 session.updateDb(notif);
529 assertThat(notif.getAdded()).isEmpty();
531 verify(pdpGroupService, never()).createPdpGroups(any());
532 verify(pdpGroupService, never()).updatePdpGroups(any());
536 void testDeleteGroupFromDb() {
537 session.deleteGroupFromDb(group1);
539 verify(pdpGroupService).deletePdpGroup(group1.getName());
543 void testTrackDeploy() throws PfModelException {
548 void testTrackUndeploy() throws PfModelException {
552 protected void testTrack(boolean deploy) throws PfModelException {
554 DeploymentStatus status = mock(DeploymentStatus.class);
557 new SessionData(DEFAULT_USER, toscaService, pdpGroupService, policyStatusService, policyAuditService) {
559 protected DeploymentStatus makeDeploymentStatus(PolicyStatusService policyStatusService) {
564 ToscaPolicy policy = makePolicy(POLICY_NAME, POLICY_VERSION);
565 policy.setType(POLICY_TYPE);
566 policy.setTypeVersion(POLICY_TYPE_VERSION);
568 when(toscaService.getFilteredPolicyList(any())).thenReturn(List.of(policy));
570 ToscaConceptIdentifier policyId = new ToscaConceptIdentifier(POLICY_NAME, POLICY_VERSION);
571 List<String> pdps = List.of(PDP1, PDP2);
573 ToscaPolicy testPolicy = session.getPolicy(new ToscaConceptIdentifierOptVersion(policyId));
576 session.trackDeploy(testPolicy, pdps, GROUP_NAME, PDP_TYPE);
577 assertThat(session.getPoliciesToBeDeployed()).contains(testPolicy);
579 session.trackUndeploy(policyId, pdps, GROUP_NAME, PDP_TYPE);
580 assertThat(session.getPoliciesToBeUndeployed()).contains(policyId);
583 // should be called just once
584 verify(status).deleteDeployment(any(), anyBoolean());
585 verify(status, times(1)).deleteDeployment(policyId, !deploy);
587 // should be called for each PDP
588 verify(status, times(2)).deploy(any(), any(), any(), any(), any(), anyBoolean());
589 verify(status).deploy(PDP1, policyId, policy.getTypeIdentifier(), GROUP_NAME, PDP_TYPE, deploy);
590 verify(status).deploy(PDP2, policyId, policy.getTypeIdentifier(), GROUP_NAME, PDP_TYPE, deploy);
593 private PdpUpdate makeUpdate(String pdpName) {
594 PdpUpdate update = new PdpUpdate();
596 update.setName(pdpName);
601 private PdpStateChange makeStateChange(String pdpName) {
602 PdpStateChange change = new PdpStateChange();
604 change.setName(pdpName);
609 private ToscaTypedEntityFilter<ToscaPolicy> getPolicyFilter() throws Exception {
610 @SuppressWarnings("unchecked")
611 ArgumentCaptor<ToscaTypedEntityFilter<ToscaPolicy>> captor =
612 ArgumentCaptor.forClass(ToscaTypedEntityFilter.class);
613 verify(toscaService).getFilteredPolicyList(captor.capture());
615 return captor.getValue();
618 private List<PdpUpdate> getUpdateRequests() {
619 return session.getPdpUpdates();
622 private List<PdpStateChange> getStateChangeRequests() {
623 return session.getPdpStateChanges();
626 private <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
627 List<T> lst = new ArrayList<>(collection);
628 lst.sort(comparator);
633 private int compare(Pair<PdpUpdate, PdpStateChange> left, Pair<PdpUpdate, PdpStateChange> right) {
634 return getName(left).compareTo(getName(right));
637 private int compare(PdpUpdate left, PdpUpdate right) {
638 return left.getName().compareTo(right.getName());
641 private int compare(PdpStateChange left, PdpStateChange right) {
642 return left.getName().compareTo(right.getName());
645 private String getName(Pair<PdpUpdate, PdpStateChange> pair) {
646 return (pair.getKey() != null ? pair.getKey().getName() : pair.getValue().getName());