Java 17 / Spring 6 / Spring Boot 3 Upgrade
[policy/pap.git] / main / src / test / java / org / onap / policy / pap / main / rest / TestPdpGroupDeployProvider.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP PAP
4  * ================================================================================
5  * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2021, 2023 Nordix Foundation.
7  * Modifications Copyright (C) 2021-2023 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22
23 package org.onap.policy.pap.main.rest;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatCode;
27 import static org.assertj.core.api.Assertions.assertThatThrownBy;
28 import static org.junit.jupiter.api.Assertions.assertEquals;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.Mockito.never;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33
34 import jakarta.ws.rs.core.Response.Status;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.List;
39 import java.util.stream.Collectors;
40 import org.junit.jupiter.api.AfterAll;
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43 import org.onap.policy.common.utils.services.Registry;
44 import org.onap.policy.models.base.PfModelException;
45 import org.onap.policy.models.base.PfModelRuntimeException;
46 import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
47 import org.onap.policy.models.pdp.concepts.DeploymentGroup;
48 import org.onap.policy.models.pdp.concepts.DeploymentGroups;
49 import org.onap.policy.models.pdp.concepts.DeploymentSubGroup;
50 import org.onap.policy.models.pdp.concepts.DeploymentSubGroup.Action;
51 import org.onap.policy.models.pdp.concepts.PdpGroup;
52 import org.onap.policy.models.pdp.concepts.PdpGroups;
53 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
54 import org.onap.policy.models.pdp.concepts.PdpUpdate;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
57
58 public class TestPdpGroupDeployProvider extends ProviderSuper {
59
60     private static final String EXPECTED_EXCEPTION = "expected exception";
61     private static final String POLICY2_NAME = "policyB";
62     private static final String POLICY3_NAME = "policyC";
63     private static final String POLICY1_VERSION = "1.2.3";
64     private static final String POLICY2_VERSION = "1.2.3";
65     private static final String POLICY3_VERSION = "1.2.3";
66     private static final String GROUP1_NAME = "groupA";
67     private static final String PDP1_TYPE = "pdpTypeA";
68     private static final String PDP2_TYPE = "pdpTypeB";
69     private static final String PDP4_TYPE = "pdpTypeD";
70     private static final String PDP2 = "pdpB";
71     private static final String PDP4 = "pdpD";
72
73     private PdpGroupDeployProvider prov;
74
75     @AfterAll
76     public static void tearDownAfterClass() {
77         Registry.newRegistry();
78     }
79
80     /**
81      * Configures mocks and objects.
82      *
83      * @throws Exception if an error occurs
84      */
85     @Override
86     @BeforeEach
87     public void setUp() throws Exception {
88
89         super.setUp();
90         prov = new PdpGroupDeployProvider();
91         super.initialize(prov);
92
93         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyList2.json"));
94         when(toscaService.getPolicyTypeList("typeA", "100.2.3"))
95             .thenReturn(List.of(loadPolicyType("daoPolicyType.json")));
96     }
97
98     /**
99      * Tests updateGroupPolicies when policies are being added.
100      */
101     @Test
102     void testUpdateGroupPoliciesAdd() throws Exception {
103         PdpGroups groups = loadPdpGroups("deployGroups.json");
104         PdpGroup newgrp = groups.getGroups().get(0);
105         PdpGroup dbgroup = new PdpGroup(newgrp);
106         when(pdpGroupService.getPdpGroups(dbgroup.getName())).thenReturn(List.of(dbgroup));
107
108         // add new policies
109         List<ToscaConceptIdentifier> policies = newgrp.getPdpSubgroups().get(0).getPolicies();
110         policies.add(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION));
111         policies.add(new ToscaConceptIdentifier(POLICY3_NAME, POLICY3_VERSION));
112
113         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("createGroupNewPolicy.json"))
114                 .thenReturn(loadPolicies("createGroupNewPolicy2.json")).thenReturn(loadPolicies("daoPolicyList.json"));
115
116         // add = POST
117         DeploymentGroups depgroups = toDeploymentGroups(groups);
118         depgroups.getGroups().get(0).getDeploymentSubgroups().get(0).setAction(Action.POST);
119
120         prov.updateGroupPolicies(depgroups, DEFAULT_USER);
121
122         assertEquals(newgrp.toString(), dbgroup.toString());
123         assertGroupUpdate(dbgroup, dbgroup.getPdpSubgroups().get(0));
124     }
125
126     /**
127      * Tests updateGroupPolicies when policies are being deleted.
128      */
129     @Test
130     void testUpdateGroupPoliciesDelete() throws Exception {
131         PdpGroups groups = loadPdpGroups("deployGroups.json");
132         PdpGroup newgrp = groups.getGroups().get(0);
133
134         // additional policies in the DB that will be removed
135         List<ToscaConceptIdentifier> policies = newgrp.getPdpSubgroups().get(0).getPolicies();
136         policies.add(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION));
137         policies.add(new ToscaConceptIdentifier(POLICY3_NAME, POLICY3_VERSION));
138
139         PdpGroup dbgroup = new PdpGroup(newgrp);
140         when(pdpGroupService.getPdpGroups(dbgroup.getName())).thenReturn(List.of(dbgroup));
141
142         // policy that should be left
143         final ToscaConceptIdentifier policyId1 = policies.remove(0);
144
145         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("createGroupNewPolicy.json"))
146                 .thenReturn(loadPolicies("createGroupNewPolicy2.json")).thenReturn(loadPolicies("daoPolicyList.json"));
147
148         DeploymentGroups depgroups = toDeploymentGroups(groups);
149         depgroups.getGroups().get(0).getDeploymentSubgroups().get(0).setAction(Action.DELETE);
150
151         prov.updateGroupPolicies(depgroups, DEFAULT_USER);
152
153         // only the first policy should remain
154         policies.clear();
155         policies.add(policyId1);
156
157         assertEquals(newgrp.toString(), dbgroup.toString());
158         assertGroupUpdate(dbgroup, dbgroup.getPdpSubgroups().get(0));
159     }
160
161     /**
162      * Tests updateGroupPolicies when policies are being added and deleted in the same
163      * subgroup.
164      */
165     @Test
166     void testUpdateGroupPoliciesAddAndDelete() throws Exception {
167         PdpGroups groups = loadPdpGroups("deployGroups.json");
168         PdpGroup newgrp = groups.getGroups().get(0);
169         PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
170
171         // put policy3 into db subgroup
172         subgrp.getPolicies().add(new ToscaConceptIdentifier(POLICY3_NAME, POLICY3_VERSION));
173         PdpGroup dbgroup = new PdpGroup(newgrp);
174         when(pdpGroupService.getPdpGroups(dbgroup.getName())).thenReturn(List.of(dbgroup));
175
176         // now make the subgrp reflect our final expectation
177         subgrp.getPolicies().remove(1);
178         subgrp.getPolicies().add(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION));
179
180         // indicate policy2 being added and policy3 being deleted
181         DeploymentSubGroup depsub1 = new DeploymentSubGroup();
182         depsub1.setAction(Action.POST);
183         depsub1.setPdpType(subgrp.getPdpType());
184         depsub1.setPolicies(List.of(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION)));
185
186         DeploymentSubGroup depsub2 = new DeploymentSubGroup();
187         depsub2.setAction(Action.DELETE);
188         depsub2.setPdpType(subgrp.getPdpType());
189         depsub2.setPolicies(List.of(new ToscaConceptIdentifier(POLICY3_NAME, POLICY3_VERSION)));
190
191         DeploymentGroup depgroup = new DeploymentGroup();
192         depgroup.setName(newgrp.getName());
193         depgroup.setDeploymentSubgroups(Arrays.asList(depsub1, depsub2));
194
195         DeploymentGroups depgroups = new DeploymentGroups();
196         depgroups.setGroups(List.of(depgroup));
197
198         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("createGroupNewPolicy.json"))
199                 .thenReturn(loadPolicies("daoPolicyList.json")).thenReturn(loadPolicies("createGroupNewPolicy2.json"));
200
201         prov.updateGroupPolicies(depgroups, DEFAULT_USER);
202
203         assertEquals(newgrp.toString(), dbgroup.toString());
204         assertGroupUpdate(dbgroup, dbgroup.getPdpSubgroups().get(0));
205     }
206
207     @Test
208     void testUpdateGroupPolicies() throws Exception {
209         PdpGroups groups = loadPdpGroups("deployGroups.json");
210         PdpGroup newgrp = groups.getGroups().get(0);
211         PdpGroup group = new PdpGroup(newgrp);
212         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
213
214         // something different in this subgroup
215         group.getPdpSubgroups().get(0).getPolicies().add(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION));
216
217         prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER);
218
219         assertEquals(newgrp.toString(), group.toString());
220         assertGroupUpdate(group, group.getPdpSubgroups().get(0));
221     }
222
223     @Test
224     void testUpdateGroupPolicies_EmptyRequest() throws Exception {
225         prov.updateGroupPolicies(toDeploymentGroups(loadPdpGroups("emptyGroups.json")), DEFAULT_USER);
226
227         // no groups, so no action should have been taken
228         assertNoGroupAction();
229     }
230
231     @Test
232     void testUpdateGroupPolicies_InvalidRequest() throws Exception {
233         assertThatThrownBy(() -> prov.updateGroupPolicies(new DeploymentGroups(), DEFAULT_USER))
234                 .isInstanceOf(PfModelException.class).hasMessageContaining("is null");
235
236         assertNoGroupAction();
237     }
238
239     @Test
240     void testUpdateGroup_UnknownGroup() throws Exception {
241         PdpGroups groups = loadPdpGroups("deployGroups.json");
242
243         String groupName = groups.getGroups().get(0).getName();
244
245         // group not found
246         when(pdpGroupService.getPdpGroups(groupName)).thenReturn(Collections.emptyList());
247
248         assertThatThrownBy(() -> prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER))
249                 .isInstanceOf(PfModelException.class).hasMessageContaining(groupName)
250                 .hasMessageContaining("unknown group");
251
252         assertNoGroupAction();
253     }
254
255     @Test
256     void testUpdateGroup() throws Exception {
257         PdpGroups groups = loadPdpGroups("deployGroups.json");
258
259         // DB group = new group
260         PdpGroup group = new PdpGroup(groups.getGroups().get(0));
261         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
262
263         prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER);
264
265         assertNoGroupAction();
266     }
267
268     @Test
269     void testUpdateGroup_NewSubGroup() throws Exception {
270         PdpGroups groups = loadPdpGroups("createGroupsNewSub.json");
271         PdpGroup group = loadPdpGroups("deployGroups.json").getGroups().get(0);
272         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
273
274         assertThatThrownBy(() -> prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER))
275                 .isInstanceOf(PfModelException.class).hasMessageContaining("pdpTypeB")
276                 .hasMessageContaining("unknown subgroup");
277
278         assertNoGroupAction();
279     }
280
281     @Test
282     void testUpdateGroup_UpdatedSubGroup() throws Exception {
283         PdpGroups groups = loadPdpGroups("deployGroups.json");
284         PdpGroup newgrp = groups.getGroups().get(0);
285         PdpGroup group = new PdpGroup(newgrp);
286         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
287
288         // something different in this subgroup
289         group.getPdpSubgroups().get(0).getPolicies().add(new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION));
290
291         prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER);
292
293         assertEquals(newgrp.toString(), group.toString());
294         assertGroupUpdate(group, group.getPdpSubgroups().get(0));
295     }
296
297     @Test
298     void testUpdateSubGroup_Invalid() throws Exception {
299         PdpGroups groups = loadPdpGroups("deployGroups.json");
300         PdpGroup newgrp = groups.getGroups().get(0);
301         PdpGroup group = new PdpGroup(newgrp);
302
303         // group has no policies yet
304         group.getPdpSubgroups().get(0).getPolicies().clear();
305         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
306
307         // unknown policy
308         when(toscaService.getFilteredPolicyList(any())).thenReturn(Collections.emptyList());
309
310         assertThatThrownBy(() -> prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER))
311                 .isInstanceOf(PfModelException.class)
312                 .hasMessageContaining(newgrp.getPdpSubgroups().get(0).getPolicies().get(0).getName())
313                 .hasMessageContaining("unknown policy");
314
315         assertNoGroupAction();
316     }
317
318     @Test
319     void testUpdateSubGroup_Policies() throws Exception {
320         PdpGroups groups = loadPdpGroups("deployGroups.json");
321         PdpGroup newgrp = groups.getGroups().get(0);
322
323         // add a second subgroup, which will be left unchanged
324         PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
325         PdpSubGroup subgrp2 = new PdpSubGroup(subgrp);
326         subgrp2.setPdpType(PDP2_TYPE);
327         newgrp.getPdpSubgroups().add(subgrp2);
328
329         PdpGroup group = new PdpGroup(newgrp);
330         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
331
332         // add two new policies
333         ToscaConceptIdentifier policyId2 = new ToscaConceptIdentifier(POLICY2_NAME, POLICY2_VERSION);
334         subgrp.getPolicies().add(policyId2);
335
336         ToscaConceptIdentifier policyId3 = new ToscaConceptIdentifier(POLICY3_NAME, POLICY3_VERSION);
337         subgrp.getPolicies().add(policyId3);
338
339         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("createGroupNewPolicy.json"))
340                 .thenReturn(loadPolicies("createGroupNewPolicy2.json")).thenReturn(loadPolicies("daoPolicyList.json"));
341
342         prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER);
343
344         Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies());
345         Collections.sort(group.getPdpSubgroups().get(0).getPolicies());
346
347         assertEquals(newgrp.toString(), group.toString());
348
349         // nothing is complete - notification should be empty
350         checkEmptyNotification();
351
352         // this requires a PDP UPDATE message
353         assertGroupUpdate(newgrp, subgrp);
354     }
355
356     @Test
357     void testUpdateSubGroup_PolicyVersionPrefix() throws Exception {
358         PdpGroups groups = loadPdpGroups("deployGroups.json");
359         PdpGroup newgrp = groups.getGroups().get(0);
360
361         PdpGroup group = new PdpGroup(newgrp);
362         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
363
364         // use version prefix
365         PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
366         ToscaConceptIdentifier ident = subgrp.getPolicies().get(0);
367         String version = ident.getVersion();
368         ident.setVersion("1");
369
370         prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER);
371
372         // restore full type before comparing
373         ident.setVersion(version);
374
375         Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies());
376         Collections.sort(group.getPdpSubgroups().get(0).getPolicies());
377
378         assertEquals(newgrp.toString(), group.toString());
379
380         assertNoGroupAction();
381     }
382
383     @Test
384     void testUpdateSubGroup_PolicyVersionPrefixMismatch() throws Exception {
385         PdpGroups groups = loadPdpGroups("deployGroups.json");
386         PdpGroup newgrp = groups.getGroups().get(0);
387
388         PdpGroup group = new PdpGroup(newgrp);
389         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
390
391         // use incorrect version prefix
392         newgrp.getPdpSubgroups().get(0).getPolicies().get(0).setVersion("9");
393
394         assertThatThrownBy(() -> prov.updateGroupPolicies(toDeploymentGroups(groups), DEFAULT_USER))
395                 .isInstanceOf(PfModelException.class).hasMessageContaining("different version already deployed");
396
397         assertNoGroupAction();
398     }
399
400     @Test
401     void testUpdateSubGroup_Unchanged() throws Exception {
402         PdpGroups dbgroups = loadPdpGroups("deployGroups.json");
403         PdpGroup newgrp = dbgroups.getGroups().get(0);
404         PdpGroup group = new PdpGroup(newgrp);
405         when(pdpGroupService.getPdpGroups(group.getName())).thenReturn(List.of(group));
406
407         prov.updateGroupPolicies(toDeploymentGroups(dbgroups), DEFAULT_USER);
408
409         Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies());
410         Collections.sort(group.getPdpSubgroups().get(0).getPolicies());
411
412         assertEquals(newgrp.toString(), group.toString());
413
414         // no notifications
415         checkEmptyNotification();
416
417         // no group updates
418         assertNoGroupAction();
419     }
420
421     @Test
422     void testUpdateSubGroup_PolicyVersionMismatch() throws Exception {
423         PdpGroups dbgroups = loadPdpGroups("deployGroups.json");
424         PdpGroup newgrp = dbgroups.getGroups().get(0);
425         PdpGroup dbgroup = new PdpGroup(newgrp);
426         when(pdpGroupService.getPdpGroups(dbgroup.getName())).thenReturn(List.of(dbgroup));
427
428         // arrange for DB policy version to be different
429         PdpSubGroup dbsubgrp = dbgroup.getPdpSubgroups().get(0);
430         dbsubgrp.getPolicies().get(0).setVersion("9.9.9");
431
432         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyList.json"));
433
434         assertThatThrownBy(() -> prov.updateGroupPolicies(toDeploymentGroups(dbgroups), DEFAULT_USER))
435                 .isInstanceOf(PfModelException.class).hasMessageContaining("different version already deployed");
436
437         assertNoGroupAction();
438     }
439
440     @Test
441     void testUpdateSubGroup_UnsupportedType() throws Exception {
442         PdpGroups dbgroups = loadPdpGroups("deployGroups.json");
443         PdpGroup newgrp = dbgroups.getGroups().get(0);
444         PdpGroup dbgroup = new PdpGroup(newgrp);
445         when(pdpGroupService.getPdpGroups(dbgroup.getName())).thenReturn(List.of(dbgroup));
446
447         final DeploymentGroups groups = toDeploymentGroups(dbgroups);
448
449         PdpSubGroup dbsubgrp = dbgroup.getPdpSubgroups().get(0);
450
451         // DB has no policies
452         dbsubgrp.getPolicies().clear();
453
454         // DB has a different supported type
455         dbsubgrp.getSupportedPolicyTypes().get(0).setName("some-other-type");
456
457         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyList.json"));
458
459         assertThatThrownBy(() -> prov.updateGroupPolicies(groups, DEFAULT_USER)).isInstanceOf(PfModelException.class)
460                 .hasMessageContaining(newgrp.getPdpSubgroups().get(0).getPolicies().get(0).getName())
461                 .hasMessageContaining("not a supported policy for the subgroup");
462
463         assertNoGroupAction();
464     }
465
466     @Test
467     void testDeployPolicies() {
468         assertThatCode(() -> prov.deployPolicies(loadEmptyRequest(), DEFAULT_USER)).doesNotThrowAnyException();
469     }
470
471     /**
472      * Tests deployPolicies() when the policies are invalid.
473      */
474     @Test
475     void testDeployPoliciesInvalidPolicies() {
476         // valid list
477         PdpDeployPolicies policies0 = loadFile("PapPoliciesList.json", PdpDeployPolicies.class);
478         assertThatCode(() -> prov.deployPolicies(policies0, DEFAULT_USER)).doesNotThrowAnyException();
479
480         // null list
481         PdpDeployPolicies policies = new PdpDeployPolicies();
482         assertThatThrownBy(() -> prov.deployPolicies(policies, DEFAULT_USER)).isInstanceOf(PfModelException.class)
483                 .hasMessageContaining("policies");
484
485         // list containing null item
486         PdpDeployPolicies policies2 = loadFile("PapPoliciesNullItem.json", PdpDeployPolicies.class);
487         assertThatThrownBy(() -> prov.deployPolicies(policies2, DEFAULT_USER)).isInstanceOf(PfModelException.class)
488                 .hasMessageContaining("policies").hasMessageContaining("null");
489
490         // list containing a policy with a null name
491         PdpDeployPolicies policies3 = loadFile("PapPoliciesNullPolicyName.json", PdpDeployPolicies.class);
492         assertThatThrownBy(() -> prov.deployPolicies(policies3, DEFAULT_USER)).isInstanceOf(PfModelException.class)
493                 .hasMessageContaining("policies").hasMessageContaining("policy-id").hasMessageContaining("null")
494                 .hasMessageNotContaining("\"value\"");
495
496         // list containing a policy with an invalid name
497         PdpDeployPolicies policies4 = loadFile("PapPoliciesInvalidPolicyName.json", PdpDeployPolicies.class);
498         assertThatThrownBy(() -> prov.deployPolicies(policies4, DEFAULT_USER)).isInstanceOf(PfModelException.class)
499                 .hasMessageContaining("policies").hasMessageContaining("policy-id").hasMessageContaining("$ abc")
500                 .hasMessageNotContaining("version");
501
502         // list containing a policy with an invalid version
503         PdpDeployPolicies policies5 = loadFile("PapPoliciesInvalidPolicyVersion.json", PdpDeployPolicies.class);
504         assertThatThrownBy(() -> prov.deployPolicies(policies5, DEFAULT_USER)).isInstanceOf(PfModelException.class)
505                 .hasMessageContaining("policies").hasMessageContaining("version").hasMessageContaining("abc123")
506                 .hasMessageNotContaining("policy-id");
507     }
508
509     /**
510      * Tests deployPolicies() when the supported policy type uses a wild-card.
511      *
512      * @throws Exception if an error occurs
513      */
514     @Test
515     void testDeployPoliciesWildCard() throws Exception {
516         when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(loadGroups("deployPoliciesWildCard.json"));
517         when(toscaService.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyListWildCard.json"));
518         when(toscaService.getPolicyTypeList(any(), any())).thenReturn(Collections.emptyList());
519
520         policy1.setName("policy.some");
521         policy1.setVersion(POLICY1_VERSION);
522         policy1.setType("some.type");
523         policy1.setTypeVersion("100.2.3");
524
525         PdpDeployPolicies depreq = loadRequest();
526         depreq.getPolicies().get(0).setName("policy.some");
527
528         prov.deployPolicies(depreq, DEFAULT_USER);
529
530         assertGroup(getGroupUpdates(), GROUP1_NAME);
531
532         List<PdpUpdate> requests = getUpdateRequests(1);
533         assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2);
534
535         // nothing is complete - notification should be empty
536         checkEmptyNotification();
537     }
538
539     @Test
540     void testDeploySimplePolicies() {
541         assertThatCode(() -> prov.deployPolicies(loadEmptyRequest(), DEFAULT_USER)).doesNotThrowAnyException();
542     }
543
544     @Test
545     void testDeploySimplePolicies_PfRtEx() {
546         PfModelRuntimeException exc = new PfModelRuntimeException(Status.BAD_REQUEST, EXPECTED_EXCEPTION);
547         when(pdpGroupService.getFilteredPdpGroups(any())).thenThrow(exc);
548
549         assertThatThrownBy(() -> prov.deployPolicies(loadRequest(), DEFAULT_USER)).isSameAs(exc);
550     }
551
552     @Test
553     void testDeploySimplePolicies_RuntimeEx() throws Exception {
554         RuntimeException exc = new RuntimeException(EXPECTED_EXCEPTION);
555         when(toscaService.getFilteredPolicyList(any())).thenThrow(exc);
556
557         assertThatThrownBy(() -> prov.deployPolicies(loadRequest(), DEFAULT_USER)).isInstanceOf(PfModelException.class)
558                 .hasCause(exc);
559     }
560
561     @Test
562     void testDeploySimplePolicies_NoGroups() {
563         when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(loadGroups("emptyGroups.json"));
564
565         assertThatThrownBy(() -> prov.deployPolicies(loadRequest(), DEFAULT_USER)).isInstanceOf(PfModelException.class)
566                 .hasMessage("policy not supported by any PDP group: policyA 1.2.3");
567     }
568
569     @Test
570     void testMakeUpdater() throws Exception {
571         /*
572          * Each subgroup has a different PDP type and name.
573          *
574          * Type is not supported by the first subgroup.
575          *
576          * Second subgroup matches.
577          *
578          * Third subgroup already contains the policy.
579          *
580          * Last subgroup matches.
581          */
582
583         when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroupDao.json"));
584
585         prov.deployPolicies(loadRequest(), DEFAULT_USER);
586
587         assertGroup(getGroupUpdates(), GROUP1_NAME);
588
589         List<PdpUpdate> requests = getUpdateRequests(2);
590         assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2);
591         assertUpdate(requests, GROUP1_NAME, PDP4_TYPE, PDP4);
592
593         // nothing is complete - notification should be empty
594         checkEmptyNotification();
595     }
596
597     @Test
598     void testMakeUpdater_PolicyVersionMismatch() {
599
600         // subgroup has a different version of the Policy
601         when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroupDao_DiffVers.json"));
602
603         PdpDeployPolicies req = loadRequest();
604         assertThatThrownBy(() -> prov.deployPolicies(req, DEFAULT_USER)).isInstanceOf(PfModelRuntimeException.class)
605                 .hasMessageContaining("pdpTypeC").hasMessageContaining("different version already deployed");
606
607         verify(pdpGroupService, never()).createPdpGroups(any());
608         verify(pdpGroupService, never()).updatePdpGroups(any());
609         verify(reqmap, never()).addRequest(any(PdpUpdate.class));
610     }
611
612     @Test
613     void testMakeUpdater_NoPdps() {
614
615         // subgroup has no PDPs
616         when(pdpGroupService.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroup_NoPdpsDao.json"));
617
618         PdpDeployPolicies req = loadRequest();
619         assertThatThrownBy(() -> prov.deployPolicies(req, DEFAULT_USER)).isInstanceOf(PfModelRuntimeException.class)
620                 .hasMessage("group " + GROUP1_NAME + " subgroup " + PDP1_TYPE + " has no active PDPs");
621
622         verify(pdpGroupService, never()).createPdpGroups(any());
623         verify(pdpGroupService, never()).updatePdpGroups(any());
624         verify(reqmap, never()).addRequest(any(PdpUpdate.class));
625     }
626
627     protected void assertUpdate(List<PdpUpdate> updates, String groupName, String pdpType, String pdpName) {
628
629         PdpUpdate update = updates.remove(0);
630
631         assertEquals(groupName, update.getPdpGroup());
632         assertEquals(pdpType, update.getPdpSubgroup());
633         assertEquals(pdpName, update.getName());
634         assertThat(update.getPoliciesToBeDeployed()).contains(policy1);
635     }
636
637     private void assertNoGroupAction() {
638         verify(pdpGroupService, never()).createPdpGroups(any());
639         verify(pdpGroupService, never()).updatePdpGroups(any());
640         verify(reqmap, never()).addRequest(any(), any());
641     }
642
643     private void assertGroupUpdate(PdpGroup group, PdpSubGroup subgrp) {
644         verify(pdpGroupService, never()).createPdpGroups(any());
645
646         assertEquals(0, getStateChangeRequests(1).size());
647
648         List<PdpUpdate> pdpUpdates = getUpdateRequests(1);
649         assertEquals(1, pdpUpdates.size());
650
651         PdpUpdate pdpUpdate = pdpUpdates.get(0);
652         assertEquals("pdpA", pdpUpdate.getName());
653         assertEquals(group.getName(), pdpUpdate.getPdpGroup());
654
655         assertEquals(subgrp.getPdpType(), pdpUpdate.getPdpSubgroup());
656
657         List<ToscaConceptIdentifier> pdpPolicies = pdpUpdate.getPoliciesToBeDeployed().stream()
658             .map(ToscaPolicy::getIdentifier).sorted().collect(Collectors.toList());
659
660         assertThat(subgrp.getPolicies()).containsAll(pdpPolicies);
661
662         List<PdpGroup> updates = getGroupUpdates();
663         assertEquals(List.of(group), updates);
664     }
665
666     /**
667      * Loads a standard request.
668      *
669      * @return a standard request
670      */
671     protected PdpDeployPolicies loadRequest() {
672         return loadRequest("request.json");
673     }
674
675     /**
676      * Loads a request from a JSON file.
677      *
678      * @param fileName name of the file from which to load
679      * @return the request that was loaded
680      */
681     protected PdpDeployPolicies loadRequest(String fileName) {
682         return loadFile(fileName, PdpDeployPolicies.class);
683     }
684
685     /**
686      * Loads an empty request.
687      *
688      * @return an empty request
689      */
690     protected PdpDeployPolicies loadEmptyRequest() {
691         return loadRequest("emptyRequest.json");
692     }
693
694     private DeploymentGroups toDeploymentGroups(PdpGroups dbgroups) {
695         DeploymentGroups groups = new DeploymentGroups();
696
697         groups.setGroups(dbgroups.getGroups().stream().map(this::toDeploymentGroup).collect(Collectors.toList()));
698
699         return groups;
700     }
701
702     private DeploymentGroup toDeploymentGroup(PdpGroup dbgroup) {
703         DeploymentGroup group = new DeploymentGroup();
704
705         group.setName(dbgroup.getName());
706         group.setDeploymentSubgroups(
707                 dbgroup.getPdpSubgroups().stream().map(this::toDeploymentSubGroup).collect(Collectors.toList()));
708
709         return group;
710     }
711
712     private DeploymentSubGroup toDeploymentSubGroup(PdpSubGroup dbsubgrp) {
713         DeploymentSubGroup subgrp = new DeploymentSubGroup();
714
715         subgrp.setAction(Action.PATCH);
716         subgrp.setPdpType(dbsubgrp.getPdpType());
717         subgrp.setPolicies(new ArrayList<>(dbsubgrp.getPolicies()));
718
719         return subgrp;
720     }
721 }