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