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