d8892c8b9673f50e6261ef37a16e8fc7d6c69b1b
[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         var modelsProvider = Mockito.mock(PolicyModelsProvider.class);
137
138         supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider, modelsProvider,
139                 controlLoopUpdatePublisher, controlLoopStateChangePublisher, participantRegisterAckPublisher,
140                 participantDeregisterAckPublisher, participantUpdatePublisher);
141     }
142
143     @BeforeEach
144     public void populateDb() throws Exception {
145         createEntryInDB();
146     }
147
148     @AfterAll
149     public static void closeDbProvider() throws PfModelException {
150         clProvider.close();
151         modelsProvider.close();
152     }
153
154     @AfterEach
155     public void cleanDatabase() throws Exception {
156         deleteEntryInDB(serviceTemplate.getName(), serviceTemplate.getVersion());
157     }
158
159     @Test
160     void testInstantiationCrud() throws Exception {
161         participantProvider.createParticipants(CommonTestData.createParticipants());
162
163         ControlLoops controlLoopsCreate =
164                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Crud");
165         ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
166         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
167         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
168                 supervisionHandler, participantProvider);
169         InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate);
170         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate);
171
172         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
173         assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty();
174         assertThat(controlLoopsCreate).isEqualTo(controlLoopsDb);
175
176         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
177             ControlLoops controlLoopsGet =
178                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
179             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
180             assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0));
181         }
182
183         ControlLoops controlLoopsUpdate =
184                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Crud");
185         assertThat(controlLoopsUpdate).isNotEqualTo(controlLoopsDb);
186
187         instantiationResponse = instantiationProvider.updateControlLoops(controlLoopsUpdate);
188         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsUpdate);
189
190         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
191         assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty();
192         assertThat(controlLoopsUpdate).isEqualTo(controlLoopsDb);
193
194         InstantiationCommand instantiationCommand =
195                 InstantiationUtils.getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Crud");
196         instantiationResponse = instantiationProvider.issueControlLoopCommand(instantiationCommand);
197         InstantiationUtils.assertInstantiationResponse(instantiationResponse, instantiationCommand);
198
199         for (ToscaConceptIdentifier toscaConceptIdentifier : instantiationCommand.getControlLoopIdentifierList()) {
200             ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(toscaConceptIdentifier.getName(),
201                     toscaConceptIdentifier.getVersion());
202             assertThat(controlLoopsGet.getControlLoopList()).hasSize(1);
203             assertThat(instantiationCommand.getOrderedState())
204                     .isEqualTo(controlLoopsGet.getControlLoopList().get(0).getOrderedState());
205         }
206
207         // in order to delete a controlLoop the state must be UNINITIALISED
208         controlLoopsCreate.getControlLoopList().forEach(cl -> cl.setState(ControlLoopState.UNINITIALISED));
209         instantiationProvider.updateControlLoops(controlLoopsCreate);
210
211         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
212             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
213         }
214
215         controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
216         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
217     }
218
219     private ControlLoops getControlLoopsFromDb(ControlLoops controlLoopsSource) throws Exception {
220
221         ControlLoops controlLoopsDb = new ControlLoops();
222         controlLoopsDb.setControlLoopList(new ArrayList<>());
223
224         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
225                 supervisionHandler, participantProvider);
226
227         for (ControlLoop controlLoop : controlLoopsSource.getControlLoopList()) {
228             ControlLoops controlLoopsFromDb =
229                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
230             controlLoopsDb.getControlLoopList().addAll(controlLoopsFromDb.getControlLoopList());
231         }
232         return controlLoopsDb;
233     }
234
235     @Test
236     void testInstantiationDelete() throws Exception {
237
238         ControlLoops controlLoops =
239                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Delete");
240         assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty();
241
242         ControlLoop controlLoop0 = controlLoops.getControlLoopList().get(0);
243
244         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
245                 supervisionHandler, participantProvider);
246
247         assertThatThrownBy(
248                 () -> instantiationProvider.deleteControlLoop(controlLoop0.getName(), controlLoop0.getVersion()))
249                         .hasMessageMatching(CONTROL_LOOP_NOT_FOUND);
250
251         InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoops),
252                 controlLoops);
253
254         for (ControlLoopState state : ControlLoopState.values()) {
255             if (!ControlLoopState.UNINITIALISED.equals(state)) {
256                 assertThatDeleteThrownBy(controlLoops, state);
257             }
258         }
259
260         controlLoop0.setState(ControlLoopState.UNINITIALISED);
261         instantiationProvider.updateControlLoops(controlLoops);
262
263         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
264             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
265         }
266
267         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
268             ControlLoops controlLoopsGet =
269                     instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion());
270             assertThat(controlLoopsGet.getControlLoopList()).isEmpty();
271         }
272     }
273
274     private void assertThatDeleteThrownBy(ControlLoops controlLoops, ControlLoopState state) throws Exception {
275         ControlLoop controlLoop = controlLoops.getControlLoopList().get(0);
276
277         controlLoop.setState(state);
278
279         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
280                 supervisionHandler, participantProvider);
281
282         instantiationProvider.updateControlLoops(controlLoops);
283         assertThatThrownBy(
284                 () -> instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion()))
285                         .hasMessageMatching(String.format(DELETE_BAD_REQUEST, state));
286     }
287
288     @Test
289     void testCreateControlLoops_NoDuplicates() throws Exception {
290
291         ControlLoops controlLoopsCreate =
292                 InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "NoDuplicates");
293
294         ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate);
295         assertThat(controlLoopsDb.getControlLoopList()).isEmpty();
296
297         var instantiationProvider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
298                 supervisionHandler, participantProvider);
299
300         InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate);
301         InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate);
302
303         assertThatThrownBy(() -> instantiationProvider.createControlLoops(controlLoopsCreate)).hasMessageMatching(
304                 controlLoopsCreate.getControlLoopList().get(0).getKey().asIdentifier() + " already defined");
305
306         for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) {
307             instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion());
308         }
309     }
310
311     @Test
312     void testCreateControlLoops_CommissionedClElementNotFound() throws Exception {
313
314         ControlLoops controlLoops = InstantiationUtils
315                 .getControlLoopsFromResource(CL_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON, "ClElementNotFound");
316
317         var provider = new ControlLoopInstantiationProvider(clProvider, commissioningProvider, supervisionHandler,
318                 participantProvider);
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                 participantProvider);
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 = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
345                 supervisionHandler, participantProvider);
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 = new ControlLoopInstantiationProvider(clProvider, commissioningProvider,
358                 supervisionHandler, participantProvider);
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 }