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 handleAcStateChangeUndeployTest() {
82 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
83 automationComposition.setCompositionId(UUID.randomUUID());
84 automationComposition.setInstanceId(UUID.randomUUID());
85 automationComposition.setCompositionTargetId(UUID.randomUUID());
86 var participantDeploy =
87 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
89 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
90 cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(),
91 automationComposition.getInstanceId(), participantDeploy, UUID.randomUUID());
93 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
94 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
96 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
97 var listener = mock(ThreadHandler.class);
98 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
99 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
100 automationComposition = cacheProvider.getAutomationComposition(automationComposition.getInstanceId());
101 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
102 for (var element : automationComposition.getElements().values()) {
103 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
108 void handleAutomationCompositionStateChangeUndeployTest() {
109 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
110 var cacheProvider = mock(CacheProvider.class);
111 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
112 .thenReturn(automationComposition);
113 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
115 var acDefinition = new AcDefinition();
116 acDefinition.setCompositionId(automationComposition.getCompositionId());
117 for (var element : automationComposition.getElements().values()) {
118 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
120 when(cacheProvider.getAcElementsDefinitions())
121 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
122 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
123 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
125 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
126 var listener = mock(ThreadHandler.class);
127 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
128 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
129 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
130 for (var element : automationComposition.getElements().values()) {
131 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
134 clearInvocations(listener);
135 automationCompositionStateChange.setStartPhase(2);
136 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
137 verify(listener, times(0)).undeploy(any(), any(), any());
141 void handleAutomationCompositionStateChangeDeleteTest() {
142 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
143 var cacheProvider = mock(CacheProvider.class);
144 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
145 .thenReturn(automationComposition);
146 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
148 var acDefinition = new AcDefinition();
149 acDefinition.setCompositionId(automationComposition.getCompositionId());
150 for (var element : automationComposition.getElements().values()) {
151 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
153 when(cacheProvider.getAcElementsDefinitions())
154 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
155 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
156 automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
157 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
158 var listener = mock(ThreadHandler.class);
159 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
160 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
161 verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
162 for (var element : automationComposition.getElements().values()) {
163 assertEquals(DeployState.DELETING, element.getDeployState());
166 clearInvocations(listener);
167 automationCompositionStateChange.setStartPhase(2);
168 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
169 verify(listener, times(0)).delete(any(), any(), any());
173 void handleAcPropertyUpdateTest() {
174 var cacheProvider = mock(CacheProvider.class);
175 var listener = mock(ThreadHandler.class);
176 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
177 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
179 var updateMsg = new PropertiesUpdate();
180 assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
182 updateMsg.setParticipantId(CommonTestData.getParticipantId());
183 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
184 var participantDeploy = new ParticipantDeploy();
185 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
186 updateMsg.getParticipantUpdatesList().add(participantDeploy);
188 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
189 updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
190 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
191 .thenReturn(automationComposition);
192 var acElementDeploy = new AcElementDeploy();
193 acElementDeploy.setProperties(Map.of());
194 acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
195 participantDeploy.getAcElementList().add(acElementDeploy);
197 var acDefinition = new AcDefinition();
198 acDefinition.setCompositionId(automationComposition.getCompositionId());
199 for (var element : automationComposition.getElements().values()) {
200 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
202 when(cacheProvider.getAcElementsDefinitions())
203 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
204 ach.handleAcPropertyUpdate(updateMsg);
205 verify(listener).update(any(), any(), any(), any());
209 void handleAutomationCompositionDeployTest() {
210 var cacheProvider = mock(CacheProvider.class);
211 var listener = mock(ThreadHandler.class);
212 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
213 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
215 var deployMsg = new AutomationCompositionDeploy();
216 assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
218 deployMsg.setParticipantId(CommonTestData.getParticipantId());
219 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
220 var participantDeploy = new ParticipantDeploy();
221 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
222 deployMsg.getParticipantUpdatesList().add(participantDeploy);
224 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
225 deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
226 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
227 .thenReturn(automationComposition);
228 var acDefinition = new AcDefinition();
229 acDefinition.setCompositionId(automationComposition.getCompositionId());
230 for (var element : automationComposition.getElements().values()) {
231 var acElementDeploy = new AcElementDeploy();
232 acElementDeploy.setProperties(Map.of());
233 acElementDeploy.setId(element.getId());
234 participantDeploy.getAcElementList().add(acElementDeploy);
235 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
237 when(cacheProvider.getAcElementsDefinitions())
238 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
240 ach.handleAutomationCompositionDeploy(deployMsg);
241 verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
243 clearInvocations(listener);
244 deployMsg.setStartPhase(2);
245 deployMsg.setFirstStartPhase(false);
246 ach.handleAutomationCompositionDeploy(deployMsg);
247 verify(listener, times(0)).deploy(any(), any(), any());
251 void handleMigrationNullTest() {
252 var ach = new AutomationCompositionHandler(
253 mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class));
254 var migrationMsg = new AutomationCompositionMigration();
255 var rollbackMsg = new AutomationCompositionMigration();
256 rollbackMsg.setRollback(true);
258 migrationMsg.setStage(0);
259 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
260 migrationMsg.setAutomationCompositionId(UUID.randomUUID());
261 migrationMsg.setCompositionTargetId(UUID.randomUUID());
262 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
264 rollbackMsg.setStage(0);
265 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
266 rollbackMsg.setAutomationCompositionId(UUID.randomUUID());
267 rollbackMsg.setCompositionTargetId(UUID.randomUUID());
268 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
272 void handleAutomationCompositionMigrationTest() {
273 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
274 automationComposition.setCompositionId(UUID.randomUUID());
275 automationComposition.setInstanceId(UUID.randomUUID());
276 automationComposition.setCompositionTargetId(UUID.randomUUID());
278 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
279 var participantDeploy =
280 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
282 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
283 automationComposition.getInstanceId(), definitions,
284 automationComposition.getCompositionTargetId(), definitions);
286 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
287 automationComposition.getInstanceId(), definitions,
288 automationComposition.getCompositionTargetId(), definitions);
290 testMigration(cacheProvider, automationComposition, 0,
291 automationComposition.getElements().size(), false);
292 testMigration(cacheProviderRollback, automationComposition, 0,
293 automationComposition.getElements().size(), true);
297 void handleMigrationAddRemoveTest() {
298 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
299 automationComposition.setCompositionId(UUID.randomUUID());
300 automationComposition.setInstanceId(UUID.randomUUID());
302 var acMigrate = new AutomationComposition(automationComposition);
303 acMigrate.setCompositionTargetId(UUID.randomUUID());
305 // replacing first element with new one
306 var element = acMigrate.getElements().values().iterator().next();
307 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0"));
308 element.setId(UUID.randomUUID());
310 var migrateDefinitions =
311 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
313 var participantDeploy =
314 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
316 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
317 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
318 automationComposition.getInstanceId(), definitions,
319 acMigrate.getCompositionTargetId(), migrateDefinitions);
320 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
321 automationComposition.getInstanceId(), definitions,
322 acMigrate.getCompositionTargetId(), migrateDefinitions);
324 testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size() + 1, false);
325 testMigration(cacheProviderRollback, acMigrate, 0, acMigrate.getElements().size() + 1, true);
329 void handleAcMigrationStageTest() {
330 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
331 automationComposition.setCompositionId(UUID.randomUUID());
332 automationComposition.setInstanceId(UUID.randomUUID());
334 var acMigrate = new AutomationComposition(automationComposition);
335 acMigrate.setCompositionTargetId(UUID.randomUUID());
337 // replacing first element with new one
338 var element = acMigrate.getElements().values().iterator().next();
339 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
340 element.setId(UUID.randomUUID());
342 // replacing definition version
343 acMigrate.getElements().values().forEach(el -> el.setDefinition(
344 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
346 var migrateDefinitions =
347 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
349 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
350 .setProperties(Map.of("stage", List.of(0, 1))));
352 var participantDeploy =
353 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
355 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
356 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
357 automationComposition.getInstanceId(), definitions,
358 acMigrate.getCompositionTargetId(), migrateDefinitions);
359 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
360 automationComposition.getInstanceId(), definitions,
361 acMigrate.getCompositionTargetId(), migrateDefinitions);
365 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
366 .setProperties(Map.of("stage", List.of(1, 2))));
368 // expected the element deleted
369 testMigration(cacheProvider, acMigrate, 0, 1, false);
370 testMigration(cacheProviderRollback, acMigrate, 0, 1, true);
372 // expected 4 elements from stage 1
373 testMigration(cacheProvider, acMigrate, 1, 4, false);
374 testMigration(cacheProviderRollback, acMigrate, 1, 4, true);
377 cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
378 automationComposition.getInstanceId(), definitions,
379 acMigrate.getCompositionTargetId(), migrateDefinitions);
380 cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
381 automationComposition.getInstanceId(), definitions,
382 acMigrate.getCompositionTargetId(), migrateDefinitions);
384 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
385 .setProperties(Map.of("stage", List.of(0, 2))));
387 // expected the element deleted + 4 elements from stage 0
388 testMigration(cacheProvider, acMigrate, 0, 5, false);
389 testMigration(cacheProviderRollback, acMigrate, 0, 5, true);
391 // expected 0 elements
392 testMigration(cacheProvider, acMigrate, 1, 0, false);
393 testMigration(cacheProviderRollback, acMigrate, 1, 0, true);
396 private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
397 UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
398 UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
399 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
400 cacheProvider.addElementDefinition(compositionId, definitions, UUID.randomUUID());
401 cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy, UUID.randomUUID());
402 cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions, UUID.randomUUID());
403 return cacheProvider;
406 private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
407 int stage, int expectedMigrated, boolean rollback) {
408 var migrationMsg = new AutomationCompositionMigration();
409 migrationMsg.setStage(stage);
410 migrationMsg.setCompositionId(acMigrate.getCompositionId());
411 migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
412 migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
413 var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
414 migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
415 var listener = mock(ThreadHandler.class);
418 var ach = new AutomationCompositionHandler(cacheProvider,
419 mock(ParticipantMessagePublisher.class), listener);
422 migrationMsg.setRollback(rollback);
423 ach.handleAutomationCompositionMigration(migrationMsg);
426 verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());
428 verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt());