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