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());