d1aaddc5a916e1ab1b85405787d4a8e22a3e113c
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.runtime.instantiation;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatThrownBy;
25
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import org.junit.jupiter.api.AfterAll;
29 import org.junit.jupiter.api.AfterEach;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.mockito.Mockito;
34 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
35 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
37 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
38 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider;
39 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
40 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
41 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider;
42 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
43 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse;
44 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
45 import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
46 import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider;
47 import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler;
48 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher;
49 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher;
50 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantDeregisterAckPublisher;
51 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantRegisterAckPublisher;
52 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
53 import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData;
54 import org.onap.policy.common.utils.coder.YamlJsonTranslator;
55 import org.onap.policy.common.utils.resources.ResourceUtils;
56 import org.onap.policy.models.base.PfModelException;
57 import org.onap.policy.models.provider.PolicyModelsProvider;
58 import org.onap.policy.models.provider.PolicyModelsProviderFactory;
59 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
60 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
61 import org.springframework.beans.factory.annotation.Autowired;
62
63 /**
64  * Class to perform unit test of {@link ControlLoopInstantiationProvider}}.
65  *
66  */
67 class ControlLoopInstantiationProviderTest {
68
69     private static final String CL_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/controlloops/ControlLoops.json";
70     private static final String CL_INSTANTIATION_UPDATE_JSON =
71             "src/test/resources/rest/controlloops/ControlLoopsUpdate.json";
72     private static final String CL_INSTANTIATION_CHANGE_STATE_JSON =
73             "src/test/resources/rest/controlloops/PassiveCommand.json";
74     private static final String CL_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON =
75             "src/test/resources/rest/controlloops/ControlLoopElementsNotFound.json";
76     private static final String CL_INSTANTIATION_CONTROLLOOP_DEFINITION_NOT_FOUND_JSON =
77             "src/test/resources/rest/controlloops/ControlLoopsNotFound.json";
78     private static final String TOSCA_TEMPLATE_YAML =
79             "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml";
80     private static final String CONTROL_LOOP_NOT_FOUND = "Control Loop not found";
81     private static final String DELETE_BAD_REQUEST = "Control Loop State is still %s";
82     private static final String ORDERED_STATE_INVALID = "ordered state invalid or not specified on command";
83     private static final String CONTROLLOOP_ELEMENT_NAME_NOT_FOUND =
84             "\"ControlLoops\" INVALID, item has status INVALID\n"
85                     + "  \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n"
86                     + "    \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n"
87                     + "  \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n"
88                     + "    \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n";
89
90     private static final String CONTROLLOOP_DEFINITION_NOT_FOUND = "\"ControlLoops\" INVALID, item has status INVALID\n"
91             + "  \"entry org.onap.domain.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n"
92             + "    item \"ControlLoop\" value \"org.onap.domain.PMSHControlLoopDefinition\" INVALID,"
93             + " Commissioned control loop definition not FOUND\n"
94             + "  \"entry org.onap.domain.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n"
95             + "    item \"ControlLoop\" value \"org.onap.domain.PMSHControlLoopDefinition\" INVALID,"
96             + " Commissioned control loop definition not FOUND\n";
97
98     private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
99
100     private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
101
102     private static SupervisionHandler supervisionHandler;
103     private static CommissioningProvider commissioningProvider;
104     private static ControlLoopProvider clProvider;
105     private static PolicyModelsProvider modelsProvider;
106     private static ParticipantProvider participantProvider;
107
108     @BeforeAll
109     public static void setUpBeforeClass() throws Exception {
110         serviceTemplate = yamlTranslator.fromYaml(ResourceUtils.getResourceAsString(TOSCA_TEMPLATE_YAML),
111             ToscaServiceTemplate.class);
112     }
113
114     /**
115      * setup Db Provider Parameters.
116      *
117      * @throws PfModelException if an error occurs
118      */
119     @BeforeAll
120     public static void setupDbProviderParameters() throws PfModelException {
121         ClRuntimeParameterGroup controlLoopParameters = CommonTestData.geParameterGroup("instantproviderdb");
122
123         modelsProvider =
124                 CommonTestData.getPolicyModelsProvider(controlLoopParameters.getDatabaseProviderParameters());
125         clProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters());
126         participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters());
127
128         var participantStatisticsProvider =
129                 new ParticipantStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters());
130         var clElementStatisticsProvider =
131                 new ClElementStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters());
132         commissioningProvider = new CommissioningProvider(modelsProvider, clProvider, null, participantProvider);
133         var monitoringProvider =
134                 new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider);
135         var participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters());
136         var controlLoopUpdatePublisher = Mockito.mock(ControlLoopUpdatePublisher.class);
137         var controlLoopStateChangePublisher = Mockito.mock(ControlLoopStateChangePublisher.class);
138         var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class);
139         var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class);
140         var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class);
141         supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider,
142                         controlLoopUpdatePublisher, controlLoopStateChangePublisher,
143                         participantRegisterAckPublisher, participantDeregisterAckPublisher, participantUpdatePublisher);
144     }
145
146     @BeforeEach
147     public void populateDb() throws Exception {
148         createEntryInDB();
149     }
150
151     @AfterAll
152     public static void closeDbProvider() throws PfModelException {
153         clProvider.close();
154         modelsProvider.close();
155     }
156
157     @AfterEach
158     public void cleanDatabase() throws Exception {
159         deleteEntryInDB(serviceTemplate.getName(), serviceTemplate.getVersion());
160     }
161
162     @Test
163     void testInstantiationCrud() throws Exception {
164
165         ControlLoops controlLoopsCreate =
166                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Crud");
167         ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
168         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
169         var instantiationProvider =
170                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
171         InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate);
172         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate);
173
174         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
175         assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty();
176         assertThat(controlLoopsCreate).isEqualTo(controlLoopsDb);
177
178         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
179             ControlLoops controlLoopsGet =
180                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
181             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
182             assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0));
183         }
184
185         ControlLoops controlLoopsUpdate =
186                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Crud");
187         assertThat(controlLoopsUpdate).isNotEqualTo(controlLoopsDb);
188
189         instantiationResponse = instantiationProvider.updateControlLoops(controlLoopsUpdate);
190         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsUpdate);
191
192         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
193         assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty();
194         assertThat(controlLoopsUpdate).isEqualTo(controlLoopsDb);
195
196         InstantiationCommand instantiationCommand =
197                 InstantiationUtils.getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Crud");
198         instantiationResponse = instantiationProvider.issueControlLoopCommand(instantiationCommand);
199         InstantiationUtils.assertInstantiationResponse(instantiationResponse, instantiationCommand);
200
201         for (ToscaConceptIdentifier toscaConceptIdentifier : instantiationCommand.getControlLoopIdentifierList()) {
202             ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(toscaConceptIdentifier.getName(),
203                     toscaConceptIdentifier.getVersion());
204             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
205             assertThat(instantiationCommand.getOrderedState())
206                     .isEqualTo(controlLoopsGet.getControlLoopList().get(0).getOrderedState());
207         }
208
209         // in order to delete a controlLoop the state must be UNINITIALISED
210         controlLoopsCreate.getControlLoopList().forEach(cl -> cl.setState(ControlLoopState.UNINITIALISED));
211         instantiationProvider.updateControlLoops(controlLoopsCreate);
212
213         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
214             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
215         }
216
217         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
218         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
219     }
220
221     private ControlLoops getControlLoopsFromDb(ControlLoops controlLoopsSource) throws Exception {
222
223         ControlLoops controlLoopsDb = new ControlLoops();
224         controlLoopsDb.setControlLoopList(new ArrayList<>());
225
226         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider,
227             commissioningProvider, supervisionHandler);
228
229         for (ControlLoop controlLoop : controlLoopsSource.getControlLoopList()) {
230             ControlLoops controlLoopsFromDb =
231                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
232             controlLoopsDb.getControlLoopList().addAll(controlLoopsFromDb.getControlLoopList());
233         }
234         return controlLoopsDb;
235     }
236
237     @Test
238     void testInstantiationDelete() throws Exception {
239
240         ControlLoops controlLoops =
241                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Delete");
242         assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty();
243
244         ControlLoop controlLoop0 = controlLoops.getControlLoopList().get(0);
245
246         var instantiationProvider =
247                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
248
249         assertThatThrownBy(
250                 () -> instantiationProvider.deleteControlLoop(controlLoop0.getName(), controlLoop0.getVersion()))
251                         .hasMessageMatching(CONTROL_LOOP_NOT_FOUND);
252
253         InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoops),
254                 controlLoops);
255
256         for (ControlLoopState state : ControlLoopState.values()) {
257             if (!ControlLoopState.UNINITIALISED.equals(state)) {
258                 assertThatDeleteThrownBy(controlLoops, state);
259             }
260         }
261
262         controlLoop0.setState(ControlLoopState.UNINITIALISED);
263         instantiationProvider.updateControlLoops(controlLoops);
264
265         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
266             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
267         }
268
269         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
270             ControlLoops controlLoopsGet =
271                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
272             assertThat(controlLoopsGet.getControlLoopList()).isEmpty();
273         }
274     }
275
276     private void assertThatDeleteThrownBy(ControlLoops controlLoops, ControlLoopState state) throws Exception {
277         ControlLoop controlLoop = controlLoops.getControlLoopList().get(0);
278
279         controlLoop.setState(state);
280
281         var instantiationProvider =
282                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
283
284         instantiationProvider.updateControlLoops(controlLoops);
285         assertThatThrownBy(
286                 () -> instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion()))
287                         .hasMessageMatching(String.format(DELETE_BAD_REQUEST, state));
288     }
289
290     @Test
291     void testCreateControlLoops_NoDuplicates() throws Exception {
292
293         ControlLoops controlLoopsCreate =
294                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "NoDuplicates");
295
296         ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
297         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
298
299         var instantiationProvider =
300                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
301
302         InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate);
303         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate);
304
305         assertThatThrownBy(() -> instantiationProvider.createControlLoops(controlLoopsCreate)).hasMessageMatching(
306                 controlLoopsCreate.getControlLoopList().get(0).getKey().asIdentifier() + " already defined");
307
308         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
309             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
310         }
311     }
312
313     @Test
314     void testCreateControlLoops_CommissionedClElementNotFound() throws Exception {
315
316         ControlLoops controlLoops = InstantiationUtils
317                 .getControlLoopsFromResource(CL_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON, "ClElementNotFound");
318
319         var provider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
320
321         // to validate control Loop, it needs to define ToscaServiceTemplate
322         //        InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider);
323
324         assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty();
325
326         assertThatThrownBy(() -> provider.createControlLoops(controlLoops))
327                 .hasMessageMatching(CONTROLLOOP_ELEMENT_NAME_NOT_FOUND);
328     }
329
330     @Test
331     void testCreateControlLoops_CommissionedClNotFound() throws Exception {
332         ControlLoops controlLoops = InstantiationUtils
333                 .getControlLoopsFromResource(CL_INSTANTIATION_CONTROLLOOP_DEFINITION_NOT_FOUND_JSON, "ClNotFound");
334
335         assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty();
336
337         var provider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
338         assertThatThrownBy(() -> provider.createControlLoops(controlLoops))
339                 .hasMessageMatching(CONTROLLOOP_DEFINITION_NOT_FOUND);
340     }
341
342     @Test
343     void testIssueControlLoopCommand_OrderedStateInvalid() throws ControlLoopRuntimeException, IOException {
344         var instantiationProvider =
345                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
346         assertThatThrownBy(() -> instantiationProvider.issueControlLoopCommand(new InstantiationCommand()))
347                 .hasMessageMatching(ORDERED_STATE_INVALID);
348     }
349
350     @Test
351     void testInstantiationVersions() throws Exception {
352         // create controlLoops V1
353         ControlLoops controlLoopsV1 =
354                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "V1");
355         assertThat(getControlLoopsFromDb(controlLoopsV1).getControlLoopList()).isEmpty();
356
357         var instantiationProvider =
358                 new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler);
359
360         InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoopsV1),
361                 controlLoopsV1);
362
363         // create controlLoops V2
364         ControlLoops controlLoopsV2 =
365                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "V2");
366         assertThat(getControlLoopsFromDb(controlLoopsV2).getControlLoopList()).isEmpty();
367         InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoopsV2),
368                 controlLoopsV2);
369
370         // GET controlLoops V2
371         for (ControlLoop controlLoop : controlLoopsV2.getControlLoopList()) {
372             ControlLoops controlLoopsGet =
373                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
374             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
375             assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0));
376         }
377
378         // DELETE controlLoops V1
379         for (ControlLoop controlLoop : controlLoopsV1.getControlLoopList()) {
380             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
381         }
382
383         // GET controlLoops V1 is not available
384         for (ControlLoop controlLoop : controlLoopsV1.getControlLoopList()) {
385             ControlLoops controlLoopsGet =
386                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
387             assertThat(controlLoopsGet.getControlLoopList()).isEmpty();
388         }
389
390         // GET controlLoops V2 is still available
391         for (ControlLoop controlLoop : controlLoopsV2.getControlLoopList()) {
392             ControlLoops controlLoopsGet =
393                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
394             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
395             assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0));
396         }
397
398         // DELETE controlLoops V2
399         for (ControlLoop controlLoop : controlLoopsV2.getControlLoopList()) {
400             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
401         }
402
403         // GET controlLoops V2 is not available
404         for (ControlLoop controlLoop : controlLoopsV2.getControlLoopList()) {
405             ControlLoops controlLoopsGet =
406                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
407             assertThat(controlLoopsGet.getControlLoopList()).isEmpty();
408         }
409     }
410
411     private synchronized void deleteEntryInDB(String name, String version) throws Exception {
412         if (!modelsProvider.getServiceTemplateList(null, null).isEmpty()) {
413             modelsProvider.deleteServiceTemplate(name, version);
414         }
415     }
416
417     private synchronized void createEntryInDB() throws Exception {
418         try {
419             deleteEntryInDB(serviceTemplate.getName(), serviceTemplate.getVersion());
420             modelsProvider.createServiceTemplate(serviceTemplate);
421         } catch (Exception e) {
422             e.printStackTrace();
423         }
424     }
425 }