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.HashMap;
34 import java.util.List;
36 import java.util.UUID;
37 import org.junit.jupiter.api.Test;
38 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
39 import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
40 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
41 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
42 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
43 import org.onap.policy.clamp.models.acm.concepts.DeployState;
44 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
45 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
46 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
47 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
48 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
49 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
50 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
51 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
54 class AutomationCompositionHandlerTest {
57 void handleAutomationCompositionStateChangeNullTest() {
58 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
59 var cacheProvider = mock(CacheProvider.class);
61 new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, mock(ThreadHandler.class));
63 var automationCompositionStateChange = new AutomationCompositionStateChange();
64 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
66 automationCompositionStateChange.setAutomationCompositionId(UUID.randomUUID());
67 automationCompositionStateChange.setDeployOrderedState(DeployOrder.DELETE);
68 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
69 verify(participantMessagePublisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
71 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
72 automationCompositionStateChange.setAutomationCompositionId(automationComposition.getInstanceId());
73 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
74 .thenReturn(automationComposition);
75 automationCompositionStateChange.setDeployOrderedState(DeployOrder.UPDATE);
76 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
80 void handleAutomationCompositionStateChangeUndeployTest() {
81 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
82 var cacheProvider = mock(CacheProvider.class);
83 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
84 .thenReturn(automationComposition);
85 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
87 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
88 var listener = mock(ThreadHandler.class);
89 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
90 Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>();
91 for (var element : automationComposition.getElements().values()) {
92 map.put(element.getDefinition(), new AutomationCompositionElementDefinition());
94 when(cacheProvider.getAcElementsDefinitions())
95 .thenReturn(Map.of(automationComposition.getCompositionId(), map));
96 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
97 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
99 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
100 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
101 for (var element : automationComposition.getElements().values()) {
102 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
105 clearInvocations(listener);
106 automationCompositionStateChange.setStartPhase(2);
107 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
108 verify(listener, times(0)).undeploy(any(), any(), any());
112 void handleAutomationCompositionStateChangeDeleteTest() {
113 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
114 var cacheProvider = mock(CacheProvider.class);
115 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
116 .thenReturn(automationComposition);
117 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
119 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
120 var listener = mock(ThreadHandler.class);
121 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
122 Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>();
123 for (var element : automationComposition.getElements().values()) {
124 map.put(element.getDefinition(), new AutomationCompositionElementDefinition());
126 when(cacheProvider.getAcElementsDefinitions())
127 .thenReturn(Map.of(automationComposition.getCompositionId(), map));
128 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
129 automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
130 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
131 verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
132 for (var element : automationComposition.getElements().values()) {
133 assertEquals(DeployState.DELETING, element.getDeployState());
136 clearInvocations(listener);
137 automationCompositionStateChange.setStartPhase(2);
138 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
139 verify(listener, times(0)).delete(any(), any(), any());
143 void handleAcPropertyUpdateTest() {
144 var cacheProvider = mock(CacheProvider.class);
145 var listener = mock(ThreadHandler.class);
146 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
147 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
149 var updateMsg = new PropertiesUpdate();
150 assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
152 updateMsg.setParticipantId(CommonTestData.getParticipantId());
153 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
154 var participantDeploy = new ParticipantDeploy();
155 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
156 updateMsg.getParticipantUpdatesList().add(participantDeploy);
158 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
159 updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
160 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
161 .thenReturn(automationComposition);
162 var acElementDeploy = new AcElementDeploy();
163 acElementDeploy.setProperties(Map.of());
164 acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
165 participantDeploy.getAcElementList().add(acElementDeploy);
167 Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>();
168 for (var element : automationComposition.getElements().values()) {
169 map.put(element.getDefinition(), new AutomationCompositionElementDefinition());
171 when(cacheProvider.getAcElementsDefinitions())
172 .thenReturn(Map.of(automationComposition.getCompositionId(), map));
173 ach.handleAcPropertyUpdate(updateMsg);
174 verify(listener).update(any(), any(), any(), any());
178 void handleAutomationCompositionDeployTest() {
179 var cacheProvider = mock(CacheProvider.class);
180 var listener = mock(ThreadHandler.class);
181 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
182 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
184 var deployMsg = new AutomationCompositionDeploy();
185 assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
187 deployMsg.setParticipantId(CommonTestData.getParticipantId());
188 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
189 var participantDeploy = new ParticipantDeploy();
190 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
191 deployMsg.getParticipantUpdatesList().add(participantDeploy);
193 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
194 deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
195 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
196 .thenReturn(automationComposition);
197 Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>();
198 for (var element : automationComposition.getElements().values()) {
199 var acElementDeploy = new AcElementDeploy();
200 acElementDeploy.setProperties(Map.of());
201 acElementDeploy.setId(element.getId());
202 participantDeploy.getAcElementList().add(acElementDeploy);
203 map.put(element.getDefinition(), new AutomationCompositionElementDefinition());
205 when(cacheProvider.getAcElementsDefinitions())
206 .thenReturn(Map.of(automationComposition.getCompositionId(), map));
208 ach.handleAutomationCompositionDeploy(deployMsg);
209 verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
211 clearInvocations(listener);
212 deployMsg.setStartPhase(2);
213 deployMsg.setFirstStartPhase(false);
214 ach.handleAutomationCompositionDeploy(deployMsg);
215 verify(listener, times(0)).deploy(any(), any(), any());
219 void handleMigrationNullTest() {
220 var ach = new AutomationCompositionHandler(
221 mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class));
222 var migrationMsg = new AutomationCompositionMigration();
223 migrationMsg.setStage(0);
224 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
225 migrationMsg.setAutomationCompositionId(UUID.randomUUID());
226 migrationMsg.setCompositionTargetId(UUID.randomUUID());
227 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
228 migrationMsg.setRollback(true);
229 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
233 void handleAutomationCompositionMigrationTest() {
234 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
235 automationComposition.setCompositionId(UUID.randomUUID());
236 automationComposition.setInstanceId(UUID.randomUUID());
237 automationComposition.setCompositionTargetId(UUID.randomUUID());
239 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
240 var participantDeploy =
241 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
243 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
244 automationComposition.getInstanceId(), definitions,
245 automationComposition.getCompositionTargetId(), definitions);
247 testMigration(cacheProvider, automationComposition, 0, automationComposition.getElements().size());
251 void handleMigrationAddRemoveTest() {
252 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
253 automationComposition.setCompositionId(UUID.randomUUID());
254 automationComposition.setInstanceId(UUID.randomUUID());
256 var acMigrate = new AutomationComposition(automationComposition);
257 acMigrate.setCompositionTargetId(UUID.randomUUID());
259 // replacing first element with new one
260 var element = acMigrate.getElements().values().iterator().next();
261 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0"));
262 element.setId(UUID.randomUUID());
264 var migrateDefinitions =
265 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
267 var participantDeploy =
268 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
270 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
271 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
272 automationComposition.getInstanceId(), definitions,
273 acMigrate.getCompositionTargetId(), migrateDefinitions);
275 testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size() + 1);
279 void handleAcMigrationStageTest() {
280 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
281 automationComposition.setCompositionId(UUID.randomUUID());
282 automationComposition.setInstanceId(UUID.randomUUID());
284 var acMigrate = new AutomationComposition(automationComposition);
285 acMigrate.setCompositionTargetId(UUID.randomUUID());
287 // replacing first element with new one
288 var element = acMigrate.getElements().values().iterator().next();
289 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
290 element.setId(UUID.randomUUID());
292 // replacing definition version
293 acMigrate.getElements().values().forEach(el -> el.setDefinition(
294 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
296 var migrateDefinitions =
297 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
299 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
300 .setProperties(Map.of("stage", List.of(0, 1))));
302 var participantDeploy =
303 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
305 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
306 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
307 automationComposition.getInstanceId(), definitions,
308 acMigrate.getCompositionTargetId(), migrateDefinitions);
311 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
312 .setProperties(Map.of("stage", List.of(1, 2))));
314 // expected the element deleted
315 testMigration(cacheProvider, acMigrate, 0, 1);
317 // expected 4 elements from stage 1
318 testMigration(cacheProvider, acMigrate, 1, 4);
321 cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
322 automationComposition.getInstanceId(), definitions,
323 acMigrate.getCompositionTargetId(), migrateDefinitions);
325 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
326 .setProperties(Map.of("stage", List.of(0, 2))));
328 // expected the element deleted + 4 elements from stage 0
329 testMigration(cacheProvider, acMigrate, 0, 5);
331 // expected 0 elements
332 testMigration(cacheProvider, acMigrate, 1, 0);
335 private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
336 UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
337 UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
338 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
339 cacheProvider.addElementDefinition(compositionId, definitions);
340 cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy);
341 cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions);
342 return cacheProvider;
345 private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
346 int stage, int expectedMigrated) {
347 var migrationMsg = new AutomationCompositionMigration();
348 migrationMsg.setStage(stage);
349 migrationMsg.setCompositionId(acMigrate.getCompositionId());
350 migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
351 migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
352 migrationMsg.setRollback(false);
353 var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
354 migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
355 var listener = mock(ThreadHandler.class);
358 var ach = new AutomationCompositionHandler(cacheProvider, mock(ParticipantMessagePublisher.class), listener);
359 ach.handleAutomationCompositionMigration(migrationMsg);
360 verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());