2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.acm.participant.intermediary.handler;
23 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.Mockito.clearInvocations;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
33 import java.util.List;
35 import java.util.UUID;
36 import org.junit.jupiter.api.Test;
37 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
38 import org.onap.policy.clamp.acm.participant.intermediary.handler.cache.AcDefinition;
39 import org.onap.policy.clamp.acm.participant.intermediary.handler.cache.CacheProvider;
40 import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
41 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
42 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
43 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
44 import org.onap.policy.clamp.models.acm.concepts.DeployState;
45 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
46 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
47 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
48 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
49 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
50 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
51 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
52 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
55 class AutomationCompositionHandlerTest {
58 void handleAutomationCompositionStateChangeNullTest() {
59 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
60 var cacheProvider = mock(CacheProvider.class);
62 new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, mock(ThreadHandler.class));
64 var automationCompositionStateChange = new AutomationCompositionStateChange();
65 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
67 automationCompositionStateChange.setAutomationCompositionId(UUID.randomUUID());
68 automationCompositionStateChange.setDeployOrderedState(DeployOrder.DELETE);
69 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
70 verify(participantMessagePublisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
72 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
73 automationCompositionStateChange.setAutomationCompositionId(automationComposition.getInstanceId());
74 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
75 .thenReturn(automationComposition);
76 automationCompositionStateChange.setDeployOrderedState(DeployOrder.UPDATE);
77 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
81 void handleAutomationCompositionStateChangeUndeployTest() {
82 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
83 var cacheProvider = mock(CacheProvider.class);
84 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
85 .thenReturn(automationComposition);
86 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
88 var acDefinition = new AcDefinition();
89 acDefinition.setCompositionId(automationComposition.getCompositionId());
90 for (var element : automationComposition.getElements().values()) {
91 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
93 when(cacheProvider.getAcElementsDefinitions())
94 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
95 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
96 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
98 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
99 var listener = mock(ThreadHandler.class);
100 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
101 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
102 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
103 for (var element : automationComposition.getElements().values()) {
104 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
107 clearInvocations(listener);
108 automationCompositionStateChange.setStartPhase(2);
109 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
110 verify(listener, times(0)).undeploy(any(), any(), any());
114 void handleAutomationCompositionStateChangeDeleteTest() {
115 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
116 var cacheProvider = mock(CacheProvider.class);
117 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
118 .thenReturn(automationComposition);
119 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
121 var acDefinition = new AcDefinition();
122 acDefinition.setCompositionId(automationComposition.getCompositionId());
123 for (var element : automationComposition.getElements().values()) {
124 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
126 when(cacheProvider.getAcElementsDefinitions())
127 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
128 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
129 automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
130 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
131 var listener = mock(ThreadHandler.class);
132 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
133 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
134 verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
135 for (var element : automationComposition.getElements().values()) {
136 assertEquals(DeployState.DELETING, element.getDeployState());
139 clearInvocations(listener);
140 automationCompositionStateChange.setStartPhase(2);
141 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
142 verify(listener, times(0)).delete(any(), any(), any());
146 void handleAcPropertyUpdateTest() {
147 var cacheProvider = mock(CacheProvider.class);
148 var listener = mock(ThreadHandler.class);
149 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
150 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
152 var updateMsg = new PropertiesUpdate();
153 assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
155 updateMsg.setParticipantId(CommonTestData.getParticipantId());
156 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
157 var participantDeploy = new ParticipantDeploy();
158 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
159 updateMsg.getParticipantUpdatesList().add(participantDeploy);
161 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
162 updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
163 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
164 .thenReturn(automationComposition);
165 var acElementDeploy = new AcElementDeploy();
166 acElementDeploy.setProperties(Map.of());
167 acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
168 participantDeploy.getAcElementList().add(acElementDeploy);
170 var acDefinition = new AcDefinition();
171 acDefinition.setCompositionId(automationComposition.getCompositionId());
172 for (var element : automationComposition.getElements().values()) {
173 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
175 when(cacheProvider.getAcElementsDefinitions())
176 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
177 ach.handleAcPropertyUpdate(updateMsg);
178 verify(listener).update(any(), any(), any(), any());
182 void handleAutomationCompositionDeployTest() {
183 var cacheProvider = mock(CacheProvider.class);
184 var listener = mock(ThreadHandler.class);
185 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
186 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
188 var deployMsg = new AutomationCompositionDeploy();
189 assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
191 deployMsg.setParticipantId(CommonTestData.getParticipantId());
192 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
193 var participantDeploy = new ParticipantDeploy();
194 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
195 deployMsg.getParticipantUpdatesList().add(participantDeploy);
197 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
198 deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
199 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
200 .thenReturn(automationComposition);
201 var acDefinition = new AcDefinition();
202 acDefinition.setCompositionId(automationComposition.getCompositionId());
203 for (var element : automationComposition.getElements().values()) {
204 var acElementDeploy = new AcElementDeploy();
205 acElementDeploy.setProperties(Map.of());
206 acElementDeploy.setId(element.getId());
207 participantDeploy.getAcElementList().add(acElementDeploy);
208 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
210 when(cacheProvider.getAcElementsDefinitions())
211 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
213 ach.handleAutomationCompositionDeploy(deployMsg);
214 verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
216 clearInvocations(listener);
217 deployMsg.setStartPhase(2);
218 deployMsg.setFirstStartPhase(false);
219 ach.handleAutomationCompositionDeploy(deployMsg);
220 verify(listener, times(0)).deploy(any(), any(), any());
224 void handleMigrationNullTest() {
225 var ach = new AutomationCompositionHandler(
226 mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class));
227 var migrationMsg = new AutomationCompositionMigration();
228 var rollbackMsg = new AutomationCompositionMigration();
229 rollbackMsg.setRollback(true);
231 migrationMsg.setStage(0);
232 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
233 migrationMsg.setAutomationCompositionId(UUID.randomUUID());
234 migrationMsg.setCompositionTargetId(UUID.randomUUID());
235 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
237 rollbackMsg.setStage(0);
238 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
239 rollbackMsg.setAutomationCompositionId(UUID.randomUUID());
240 rollbackMsg.setCompositionTargetId(UUID.randomUUID());
241 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
245 void handleAutomationCompositionMigrationTest() {
246 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
247 automationComposition.setCompositionId(UUID.randomUUID());
248 automationComposition.setInstanceId(UUID.randomUUID());
249 automationComposition.setCompositionTargetId(UUID.randomUUID());
251 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
252 var participantDeploy =
253 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
255 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
256 automationComposition.getInstanceId(), definitions,
257 automationComposition.getCompositionTargetId(), definitions);
259 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
260 automationComposition.getInstanceId(), definitions,
261 automationComposition.getCompositionTargetId(), definitions);
263 testMigration(cacheProvider, automationComposition, 0,
264 automationComposition.getElements().size(), false);
265 testMigration(cacheProviderRollback, automationComposition, 0,
266 automationComposition.getElements().size(), true);
270 void handleMigrationAddRemoveTest() {
271 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
272 automationComposition.setCompositionId(UUID.randomUUID());
273 automationComposition.setInstanceId(UUID.randomUUID());
275 var acMigrate = new AutomationComposition(automationComposition);
276 acMigrate.setCompositionTargetId(UUID.randomUUID());
278 // replacing first element with new one
279 var element = acMigrate.getElements().values().iterator().next();
280 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0"));
281 element.setId(UUID.randomUUID());
283 var migrateDefinitions =
284 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
286 var participantDeploy =
287 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
289 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
290 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
291 automationComposition.getInstanceId(), definitions,
292 acMigrate.getCompositionTargetId(), migrateDefinitions);
293 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
294 automationComposition.getInstanceId(), definitions,
295 acMigrate.getCompositionTargetId(), migrateDefinitions);
297 testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size() + 1, false);
298 testMigration(cacheProviderRollback, acMigrate, 0, acMigrate.getElements().size() + 1, true);
302 void handleAcMigrationStageTest() {
303 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
304 automationComposition.setCompositionId(UUID.randomUUID());
305 automationComposition.setInstanceId(UUID.randomUUID());
307 var acMigrate = new AutomationComposition(automationComposition);
308 acMigrate.setCompositionTargetId(UUID.randomUUID());
310 // replacing first element with new one
311 var element = acMigrate.getElements().values().iterator().next();
312 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
313 element.setId(UUID.randomUUID());
315 // replacing definition version
316 acMigrate.getElements().values().forEach(el -> el.setDefinition(
317 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
319 var migrateDefinitions =
320 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
322 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
323 .setProperties(Map.of("stage", List.of(0, 1))));
325 var participantDeploy =
326 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
328 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
329 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
330 automationComposition.getInstanceId(), definitions,
331 acMigrate.getCompositionTargetId(), migrateDefinitions);
332 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
333 automationComposition.getInstanceId(), definitions,
334 acMigrate.getCompositionTargetId(), migrateDefinitions);
338 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
339 .setProperties(Map.of("stage", List.of(1, 2))));
341 // expected the element deleted
342 testMigration(cacheProvider, acMigrate, 0, 1, false);
343 testMigration(cacheProviderRollback, acMigrate, 0, 1, true);
345 // expected 4 elements from stage 1
346 testMigration(cacheProvider, acMigrate, 1, 4, false);
347 testMigration(cacheProviderRollback, acMigrate, 1, 4, true);
350 cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
351 automationComposition.getInstanceId(), definitions,
352 acMigrate.getCompositionTargetId(), migrateDefinitions);
353 cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
354 automationComposition.getInstanceId(), definitions,
355 acMigrate.getCompositionTargetId(), migrateDefinitions);
357 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
358 .setProperties(Map.of("stage", List.of(0, 2))));
360 // expected the element deleted + 4 elements from stage 0
361 testMigration(cacheProvider, acMigrate, 0, 5, false);
362 testMigration(cacheProviderRollback, acMigrate, 0, 5, true);
364 // expected 0 elements
365 testMigration(cacheProvider, acMigrate, 1, 0, false);
366 testMigration(cacheProviderRollback, acMigrate, 1, 0, true);
369 private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
370 UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
371 UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
372 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
373 cacheProvider.addElementDefinition(compositionId, definitions, UUID.randomUUID());
374 cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy, UUID.randomUUID());
375 cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions, UUID.randomUUID());
376 return cacheProvider;
379 private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
380 int stage, int expectedMigrated, boolean rollback) {
381 var migrationMsg = new AutomationCompositionMigration();
382 migrationMsg.setStage(stage);
383 migrationMsg.setCompositionId(acMigrate.getCompositionId());
384 migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
385 migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
386 var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
387 migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
388 var listener = mock(ThreadHandler.class);
391 var ach = new AutomationCompositionHandler(cacheProvider,
392 mock(ParticipantMessagePublisher.class), listener);
395 migrationMsg.setRollback(rollback);
396 ach.handleAutomationCompositionMigration(migrationMsg);
399 verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());
401 verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt());