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