14de34d1c9935ebd584e664618f1ef1e434a3b03
[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.supervision.comm;
23
24 import static org.assertj.core.api.Assertions.assertThatCode;
25
26 import java.time.Instant;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.UUID;
32 import org.junit.jupiter.api.AfterAll;
33 import org.junit.jupiter.api.BeforeAll;
34 import org.junit.jupiter.api.Test;
35 import org.mockito.Mockito;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
37 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantDefinition;
38 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider;
39 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
40 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
41 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider;
42 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister;
43 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck;
44 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
45 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck;
46 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
47 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
48 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
49 import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
50 import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider;
51 import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler;
52 import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData;
53 import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController;
54 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
55 import org.onap.policy.common.endpoints.event.comm.TopicSink;
56 import org.onap.policy.common.utils.coder.Coder;
57 import org.onap.policy.common.utils.coder.CoderException;
58 import org.onap.policy.common.utils.coder.StandardCoder;
59 import org.onap.policy.common.utils.coder.YamlJsonTranslator;
60 import org.onap.policy.common.utils.resources.ResourceUtils;
61 import org.onap.policy.models.base.PfModelException;
62 import org.onap.policy.models.provider.PolicyModelsProvider;
63 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
64 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
66
67 class SupervisionMessagesTest extends CommonRestController {
68
69     private static final String TOSCA_SERVICE_TEMPLATE_YAML =
70             "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml";
71     private static final Object lockit = new Object();
72     private static final CommInfrastructure INFRA = CommInfrastructure.NOOP;
73     private static final String TOPIC = "my-topic";
74     private static SupervisionHandler supervisionHandler;
75     private static CommissioningProvider commissioningProvider;
76     private static ControlLoopProvider clProvider;
77     private static PolicyModelsProvider modelsProvider;
78     private static ParticipantProvider participantProvider;
79     private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
80     private static final String CONTROL_LOOP_ELEMENT = "org.onap.policy.clamp.controlloop.ControlLoopElement";
81     private static final Coder CODER = new StandardCoder();
82
83     /**
84      * setup Db Provider Parameters.
85      *
86      * @throws PfModelException if an error occurs
87      */
88     @BeforeAll
89     public static void setupDbProviderParameters() throws PfModelException {
90         ClRuntimeParameterGroup controlLoopParameters = CommonTestData.geParameterGroup("instantproviderdb");
91
92         modelsProvider = CommonTestData.getPolicyModelsProvider(controlLoopParameters.getDatabaseProviderParameters());
93         clProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters());
94         participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters());
95
96         var participantStatisticsProvider =
97                 new ParticipantStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters());
98         var clElementStatisticsProvider =
99                 new ClElementStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters());
100         commissioningProvider = new CommissioningProvider(modelsProvider, clProvider, null, participantProvider);
101         var monitoringProvider =
102                 new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider);
103         var participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters());
104         var controlLoopUpdatePublisher = Mockito.mock(ControlLoopUpdatePublisher.class);
105         var controlLoopStateChangePublisher = Mockito.mock(ControlLoopStateChangePublisher.class);
106         var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class);
107         var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class);
108         var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class);
109         supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider,
110                 controlLoopUpdatePublisher, controlLoopStateChangePublisher, participantRegisterAckPublisher,
111                 participantDeregisterAckPublisher, participantUpdatePublisher);
112     }
113
114     @AfterAll
115     public static void closeDbProvider() throws PfModelException {
116         clProvider.close();
117         modelsProvider.close();
118     }
119
120     @Test
121     void testReceiveParticipantRegister() throws Exception {
122         final ParticipantRegister participantRegisterMsg = new ParticipantRegister();
123         participantRegisterMsg.setParticipantId(getParticipantId());
124         participantRegisterMsg.setTimestamp(Instant.now());
125         participantRegisterMsg.setParticipantType(getParticipantType());
126
127         synchronized (lockit) {
128             ParticipantRegisterListener participantRegisterListener =
129                     new ParticipantRegisterListener(supervisionHandler);
130             ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml(
131                     ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class);
132
133             // List<ToscaNodeTemplate> listOfTemplates = commissioningProvider.getControlLoopDefinitions(null, null);
134             commissioningProvider.createControlLoopDefinitions(serviceTemplate);
135             assertThatCode(() -> participantRegisterListener.onTopicEvent(INFRA, TOPIC, null, participantRegisterMsg))
136                             .doesNotThrowAnyException();
137         }
138     }
139
140     @Test
141     void testSendParticipantRegisterAck() throws Exception {
142         final ParticipantRegisterAck participantRegisterAckMsg = new ParticipantRegisterAck();
143         participantRegisterAckMsg.setMessage("ParticipantRegisterAck message");
144         participantRegisterAckMsg.setResponseTo(UUID.randomUUID());
145         participantRegisterAckMsg.setResult(true);
146
147         synchronized (lockit) {
148             ParticipantRegisterAckPublisher clRegisterAckPublisher = new ParticipantRegisterAckPublisher();
149             clRegisterAckPublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class)));
150             assertThatCode(() -> clRegisterAckPublisher.send(participantRegisterAckMsg)).doesNotThrowAnyException();
151         }
152     }
153
154     @Test
155     void testReceiveParticipantDeregister() throws Exception {
156         final ParticipantDeregister participantDeregisterMsg = new ParticipantDeregister();
157         participantDeregisterMsg.setParticipantId(getParticipantId());
158         participantDeregisterMsg.setTimestamp(Instant.now());
159         participantDeregisterMsg.setParticipantType(getParticipantType());
160
161         synchronized (lockit) {
162             ParticipantDeregisterListener participantDeregisterListener =
163                             new ParticipantDeregisterListener(supervisionHandler);
164             assertThatCode(() -> participantDeregisterListener.onTopicEvent(INFRA, TOPIC, null,
165                             participantDeregisterMsg)).doesNotThrowAnyException();
166         }
167     }
168
169     @Test
170     void testSendParticipantDeregisterAck() throws Exception {
171         final ParticipantDeregisterAck participantDeregisterAckMsg = new ParticipantDeregisterAck();
172         participantDeregisterAckMsg.setMessage("ParticipantDeregisterAck message");
173         participantDeregisterAckMsg.setResponseTo(UUID.randomUUID());
174         participantDeregisterAckMsg.setResult(true);
175
176         synchronized (lockit) {
177             ParticipantDeregisterAckPublisher clDeregisterAckPublisher = new ParticipantDeregisterAckPublisher();
178             clDeregisterAckPublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class)));
179             assertThatCode(() -> clDeregisterAckPublisher.send(participantDeregisterAckMsg)).doesNotThrowAnyException();
180         }
181     }
182
183     @Test
184     void testSendParticipantUpdate() throws Exception {
185         final ParticipantUpdate participantUpdateMsg = new ParticipantUpdate();
186         participantUpdateMsg.setParticipantId(getParticipantId());
187         participantUpdateMsg.setTimestamp(Instant.now());
188         participantUpdateMsg.setParticipantType(getParticipantType());
189         participantUpdateMsg.setTimestamp(Instant.ofEpochMilli(3000));
190         participantUpdateMsg.setMessageId(UUID.randomUUID());
191
192         ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getToscaServiceTemplate(null, null);
193         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
194         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
195             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
196             if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
197                 ToscaConceptIdentifier clParticipantType;
198                 try {
199                     clParticipantType = CODER.decode(
200                             toscaInputEntry.getValue().getProperties().get("participantType").toString(),
201                             ToscaConceptIdentifier.class);
202                 } catch (CoderException e) {
203                     throw new RuntimeException("cannot get ParticipantType from toscaNodeTemplate", e);
204                 }
205                 prepareParticipantDefinitionUpdate(clParticipantType, toscaInputEntry.getKey(),
206                     toscaInputEntry.getValue(), participantDefinitionUpdates);
207             }
208         }
209
210         participantUpdateMsg.setParticipantDefinitionUpdates(participantDefinitionUpdates);
211         synchronized (lockit) {
212             ParticipantUpdatePublisher participantUpdatePublisher =
213                 new ParticipantUpdatePublisher(modelsProvider);
214             participantUpdatePublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class)));
215             assertThatCode(() -> participantUpdatePublisher.send(participantUpdateMsg)).doesNotThrowAnyException();
216         }
217     }
218
219     private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
220             ToscaServiceTemplate toscaServiceTemplate) {
221         if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
222             return true;
223         } else {
224             var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
225             if (nodeType != null) {
226                 var derivedFrom = nodeType.getDerivedFrom();
227                 if (derivedFrom != null) {
228                     return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
229                 }
230             }
231         }
232         return false;
233     }
234
235     private void prepareParticipantDefinitionUpdate(ToscaConceptIdentifier clParticipantType, String entryKey,
236         ToscaNodeTemplate entryValue, List<ParticipantDefinition> participantDefinitionUpdates) {
237
238         var clDefinition = new ControlLoopElementDefinition();
239         clDefinition.setClElementDefinitionId(new ToscaConceptIdentifier(
240             entryKey, entryValue.getVersion()));
241         clDefinition.setControlLoopElementToscaNodeTemplate(entryValue);
242         List<ControlLoopElementDefinition> controlLoopElementDefinitionList = new ArrayList<>();
243
244         if (participantDefinitionUpdates.isEmpty()) {
245             participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
246                 controlLoopElementDefinitionList));
247         } else {
248             boolean participantExists = false;
249             for (ParticipantDefinition participantDefinitionUpdate : participantDefinitionUpdates) {
250                 if (participantDefinitionUpdate.getParticipantType().equals(clParticipantType)) {
251                     participantDefinitionUpdate.getControlLoopElementDefinitionList().add(clDefinition);
252                     participantExists = true;
253                 }
254             }
255             if (!participantExists) {
256                 participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
257                     controlLoopElementDefinitionList));
258             }
259         }
260     }
261
262     private ParticipantDefinition getParticipantDefinition(ControlLoopElementDefinition clDefinition,
263         ToscaConceptIdentifier clParticipantType,
264         List<ControlLoopElementDefinition> controlLoopElementDefinitionList) {
265         ParticipantDefinition participantDefinition = new ParticipantDefinition();
266         participantDefinition.setParticipantType(clParticipantType);
267         controlLoopElementDefinitionList.add(clDefinition);
268         participantDefinition.setControlLoopElementDefinitionList(controlLoopElementDefinitionList);
269         return participantDefinition;
270     }
271
272     @Test
273     void testReceiveParticipantUpdateAckMessage() throws Exception {
274         final ParticipantUpdateAck participantUpdateAckMsg = new ParticipantUpdateAck();
275         participantUpdateAckMsg.setMessage("ParticipantUpdateAck message");
276         participantUpdateAckMsg.setResponseTo(UUID.randomUUID());
277         participantUpdateAckMsg.setResult(true);
278         participantUpdateAckMsg.setParticipantId(getParticipantId());
279         participantUpdateAckMsg.setParticipantType(getParticipantType());
280
281         synchronized (lockit) {
282             ParticipantUpdateAckListener participantUpdateAckListener =
283                             new ParticipantUpdateAckListener(supervisionHandler);
284             assertThatCode(() -> participantUpdateAckListener.onTopicEvent(INFRA, TOPIC, null, participantUpdateAckMsg))
285                             .doesNotThrowAnyException();
286         }
287     }
288
289     private ToscaConceptIdentifier getParticipantId() {
290         return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
291     }
292
293     private ToscaConceptIdentifier getParticipantType() {
294         return new ToscaConceptIdentifier("org.onap.policy.controlloop.PolicyControlLoopParticipant", "2.3.1");
295     }
296 }