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.models.acm.persistence.provider;
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatThrownBy;
25 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertNotNull;
28 import static org.junit.jupiter.api.Assertions.assertThrows;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.ArgumentMatchers.anyCollection;
31 import static org.mockito.ArgumentMatchers.anyIterable;
32 import static org.mockito.ArgumentMatchers.anyString;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Optional;
40 import java.util.UUID;
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43 import org.mockito.Mockito;
44 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
45 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
46 import org.onap.policy.clamp.models.acm.concepts.DeployState;
47 import org.onap.policy.clamp.models.acm.concepts.LockState;
48 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
49 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
50 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement;
51 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;
52 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository;
53 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRepository;
54 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRollbackRepository;
55 import org.onap.policy.common.utils.coder.Coder;
56 import org.onap.policy.common.utils.coder.StandardCoder;
57 import org.onap.policy.common.utils.resources.ResourceUtils;
58 import org.onap.policy.models.base.PfConceptKey;
59 import org.onap.policy.models.base.PfModelRuntimeException;
60 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
61 import org.springframework.data.domain.Page;
62 import org.springframework.data.domain.PageImpl;
63 import org.springframework.data.domain.PageRequest;
64 import org.springframework.data.domain.Pageable;
66 class AutomationCompositionProviderTest {
68 private static final String AC_IS_NULL = "automationComposition is marked non-null but is null";
69 private static final String ACELEMENT_ID_IS_NULL = "elementId is marked non-null but is null";
71 private static final Coder CODER = new StandardCoder();
72 private static final String AUTOMATION_COMPOSITION_JSON =
73 "src/test/resources/providers/TestAutomationCompositions.json";
75 private AutomationCompositions inputAutomationCompositions;
76 private List<JpaAutomationComposition> inputAutomationCompositionsJpa;
77 private final String originalJson = ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON);
80 void beforeSetupDao() throws Exception {
81 inputAutomationCompositions = CODER.decode(originalJson, AutomationCompositions.class);
82 inputAutomationCompositionsJpa =
83 ProviderUtils.getJpaAndValidateList(inputAutomationCompositions.getAutomationCompositionList(),
84 JpaAutomationComposition::new, "automation compositions");
88 void testAutomationCompositionCreate() {
89 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
90 when(automationCompositionRepository.save(any(JpaAutomationComposition.class)))
91 .thenReturn(inputAutomationCompositionsJpa.get(0));
92 var inputAc = inputAutomationCompositions.getAutomationCompositionList().get(0);
94 var automationCompositionProvider = new AutomationCompositionProvider(
95 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
96 mock(AutomationCompositionRollbackRepository.class));
97 var createdAutomationComposition = automationCompositionProvider.createAutomationComposition(inputAc);
98 inputAc.setInstanceId(createdAutomationComposition.getInstanceId());
99 inputAc.setLastMsg(createdAutomationComposition.getLastMsg());
100 assertEquals(inputAc, createdAutomationComposition);
104 void testAutomationCompositionUpdate() {
105 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
106 var automationCompositionProvider = new AutomationCompositionProvider(
107 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
108 mock(AutomationCompositionRollbackRepository.class));
109 assertThatThrownBy(() -> automationCompositionProvider.updateAutomationComposition(null))
110 .hasMessageMatching(AC_IS_NULL);
112 when(automationCompositionRepository.save(inputAutomationCompositionsJpa.get(0)))
113 .thenReturn(inputAutomationCompositionsJpa.get(0));
115 var createdAutomationComposition = automationCompositionProvider
116 .updateAutomationComposition(inputAutomationCompositions.getAutomationCompositionList().get(0));
118 assertEquals(inputAutomationCompositions.getAutomationCompositionList().get(0), createdAutomationComposition);
122 void testGetAutomationCompositionsWithNull() {
123 var automationCompositionProvider = new AutomationCompositionProvider(
124 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
125 mock(AutomationCompositionRollbackRepository.class));
126 assertThatThrownBy(() -> automationCompositionProvider
127 .getAutomationCompositions(UUID.randomUUID(), null, null, null))
128 .hasMessage("pageable is marked non-null but is null");
130 assertThatThrownBy(() -> automationCompositionProvider
131 .getAutomationCompositions(null, null, null, Pageable.unpaged()))
132 .hasMessage("compositionId is marked non-null but is null");
136 void testGetAutomationCompositions() {
137 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
138 var automationCompositionProvider = new AutomationCompositionProvider(
139 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
140 mock(AutomationCompositionRollbackRepository.class));
141 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
142 when(automationCompositionRepository
143 .findAll(Mockito.any(), any(Pageable.class)))
144 .thenReturn(new PageImpl<>(inputAutomationCompositionsJpa));
145 var acList = automationCompositionProvider.getAutomationCompositions(UUID.randomUUID(),
146 automationComposition.getName(), automationComposition.getVersion(), Pageable.unpaged());
147 assertThat(acList).hasSize(2);
149 acList = automationCompositionProvider.getAutomationCompositions(automationComposition.getCompositionId(), null,
150 null, Pageable.unpaged());
151 assertThat(acList).hasSize(2);
153 when(automationCompositionRepository
154 .findAll(Mockito.any(), Mockito.any(Pageable.class)))
155 .thenReturn(new PageImpl<>(inputAutomationCompositionsJpa));
156 acList = automationCompositionProvider.getAutomationCompositions(automationComposition.getCompositionId(), null,
157 null, PageRequest.of(0, 10));
158 assertThat(acList).hasSize(2);
162 void testGetAutomationComposition() {
163 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
164 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
165 var automationCompositionProvider = new AutomationCompositionProvider(
166 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
167 mock(AutomationCompositionRollbackRepository.class));
169 () -> automationCompositionProvider.getAutomationComposition(automationComposition.getInstanceId()))
170 .hasMessageMatching("AutomationComposition not found");
172 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
173 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
174 var ac = automationCompositionProvider.getAutomationComposition(automationComposition.getInstanceId());
175 assertEquals(automationComposition, ac);
179 void testFindAutomationComposition() {
180 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
181 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
182 var automationCompositionProvider = new AutomationCompositionProvider(
183 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
184 mock(AutomationCompositionRollbackRepository.class));
185 var acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
186 assertThat(acOpt).isEmpty();
188 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
189 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
190 acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
191 assertEquals(automationComposition, acOpt.get());
195 void testGetAcInstancesByCompositionId() {
196 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
197 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
198 when(automationCompositionRepository.findByCompositionId(automationComposition.getCompositionId().toString()))
199 .thenReturn(inputAutomationCompositionsJpa);
200 var automationCompositionProvider = new AutomationCompositionProvider(
201 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
202 mock(AutomationCompositionRollbackRepository.class));
204 automationCompositionProvider.getAcInstancesByCompositionId(automationComposition.getCompositionId());
205 assertEquals(inputAutomationCompositions.getAutomationCompositionList(), acList);
209 void testGetAcInstancesInTransition() {
210 inputAutomationCompositions.getAutomationCompositionList().get(0).setDeployState(DeployState.DEPLOYING);
211 inputAutomationCompositions.getAutomationCompositionList().get(1).setLockState(LockState.LOCKING);
212 inputAutomationCompositionsJpa.get(0).setDeployState(DeployState.DEPLOYING);
213 inputAutomationCompositionsJpa.get(1).setLockState(LockState.LOCKING);
215 List<JpaAutomationComposition> res1 = new ArrayList<>();
216 res1.add(inputAutomationCompositionsJpa.get(0));
218 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
219 when(automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
220 DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING,
221 DeployState.MIGRATION_REVERTING)))
223 when(automationCompositionRepository.findByLockStateIn(List.of(LockState.LOCKING, LockState.UNLOCKING)))
224 .thenReturn(List.of(inputAutomationCompositionsJpa.get(1)));
225 var automationCompositionProvider = new AutomationCompositionProvider(
226 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
227 mock(AutomationCompositionRollbackRepository.class));
228 var acList = automationCompositionProvider.getAcInstancesInTransition();
229 assertThat(acList).hasSize(2)
230 .contains(inputAutomationCompositions.getAutomationCompositionList().get(0).getInstanceId())
231 .contains(inputAutomationCompositions.getAutomationCompositionList().get(1).getInstanceId());
235 void testDeleteAutomationComposition() {
236 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
237 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
238 var automationCompositionProvider = new AutomationCompositionProvider(
239 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
240 acRollbackRepository);
241 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(UUID.randomUUID()))
242 .hasMessageMatching(".*.failed, automation composition does not exist");
244 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(null))
245 .hasMessageMatching("instanceId is marked non-null but is null");
247 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
248 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
249 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
252 automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
253 assertEquals(automationComposition, deletedAc);
255 when(acRollbackRepository.existsById(automationComposition.getInstanceId().toString())).thenReturn(true);
258 automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
259 assertEquals(automationComposition, deletedAc);
260 verify(acRollbackRepository).deleteById(automationComposition.getInstanceId().toString());
264 void testDeleteElementById() {
265 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
266 var acElementRepository = mock(AutomationCompositionElementRepository.class);
267 var automationCompositionProvider = new AutomationCompositionProvider(
268 automationCompositionRepository, acElementRepository,
269 mock(AutomationCompositionRollbackRepository.class));
270 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationCompositionElement(null))
271 .hasMessageMatching(ACELEMENT_ID_IS_NULL);
272 var elementId = UUID.randomUUID();
273 automationCompositionProvider.deleteAutomationCompositionElement(elementId);
274 verify(acElementRepository).deleteById(elementId.toString());
278 void testValidateElementIds() {
279 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
281 var acElementRepository = mock(AutomationCompositionElementRepository.class);
282 var automationCompositionProvider = new AutomationCompositionProvider(
283 mock(AutomationCompositionRepository.class), acElementRepository,
284 mock(AutomationCompositionRollbackRepository.class));
285 var result = automationCompositionProvider.validateElementIds(ac);
286 assertThat(result.isValid()).isTrue();
288 var jpaElement = new JpaAutomationCompositionElement(ac.getElements().values().iterator().next());
289 when(acElementRepository.findAllById(anyIterable()))
290 .thenReturn(List.of(jpaElement));
292 ac.setInstanceId(null);
293 result = automationCompositionProvider.validateElementIds(ac);
294 assertThat(result.isValid()).isFalse();
296 ac.setInstanceId(UUID.randomUUID());
297 jpaElement.setInstanceId(UUID.randomUUID().toString());
298 result = automationCompositionProvider.validateElementIds(ac);
299 assertThat(result.isValid()).isFalse();
301 ac.setInstanceId(UUID.randomUUID());
302 jpaElement.setInstanceId(ac.getInstanceId().toString());
303 result = automationCompositionProvider.validateElementIds(ac);
304 assertThat(result.isValid()).isTrue();
308 void testCopyAcElements() {
309 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
310 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
311 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
312 var automationCompositionProvider = new AutomationCompositionProvider(
313 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
314 acRollbackRepository);
315 automationCompositionProvider.copyAcElementsBeforeUpdate(ac);
317 verify(acRollbackRepository).save(any(JpaAutomationCompositionRollback.class));
318 var instanceId = ac.getInstanceId();
319 assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
320 .getAutomationCompositionRollback(instanceId));
324 void testGetRollbackSuccess() {
325 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
326 var rollback = new JpaAutomationCompositionRollback();
327 rollback.setInstanceId(ac.getInstanceId().toString());
328 rollback.setCompositionId(ac.getCompositionId().toString());
330 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
331 when(acRollbackRepository.findById(anyString())).thenReturn(Optional.of(rollback));
333 var automationCompositionProvider = new AutomationCompositionProvider(
334 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
335 acRollbackRepository);
336 var rbFromDb = automationCompositionProvider.getAutomationCompositionRollback(ac.getInstanceId());
337 assertNotNull(rbFromDb);
341 void testGetRollbackEmpty() {
342 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
343 var automationCompositionProvider = new AutomationCompositionProvider(
344 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
345 acRollbackRepository);
346 when(acRollbackRepository.findById(anyString())).thenReturn(Optional.empty());
347 var compositionId = UUID.randomUUID();
348 assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
349 .getAutomationCompositionRollback(compositionId));
353 void testVersionCompatibility() {
355 var newDefinition = new PfConceptKey("policy.clamp.element", "1.2.3");
356 var oldDefinition = new PfConceptKey("policy.clamp.element", "1.2.3");
358 var instanceId = UUID.randomUUID();
359 assertDoesNotThrow(() ->
360 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
363 newDefinition.setVersion("1.2.4");
364 assertDoesNotThrow(() ->
365 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
368 newDefinition.setVersion("1.3.1");
369 assertDoesNotThrow(() ->
370 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
373 newDefinition.setVersion("2.1.1");
374 assertDoesNotThrow(() ->
375 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
378 newDefinition.setName("policy.clamp.newElement");
379 newDefinition.setVersion("2.2.4");
380 assertThatThrownBy(() -> AutomationCompositionProvider
381 .checkCompatibility(newDefinition, oldDefinition, instanceId))
382 .hasMessageContaining("is not compatible");
386 void testValidateNameVersion() {
387 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
388 var automationCompositionProvider = new AutomationCompositionProvider(
389 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
390 mock(AutomationCompositionRollbackRepository.class));
392 var acIdentifier = new ToscaConceptIdentifier();
393 assertDoesNotThrow(() -> {
394 automationCompositionProvider.validateNameVersion(acIdentifier);
397 when(automationCompositionRepository.findOne(Mockito.any()))
398 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
399 assertThatThrownBy(() -> {
400 automationCompositionProvider.validateNameVersion(acIdentifier);
401 }).hasMessageContaining("already defined");
405 void testValidateInstanceEndpoint() {
406 var automationComposition = new AutomationComposition();
407 automationComposition.setCompositionId(UUID.randomUUID());
409 var compositionId = automationComposition.getCompositionId();
410 assertDoesNotThrow(() -> AutomationCompositionProvider
411 .validateInstanceEndpoint(compositionId, automationComposition));
413 var wrongCompositionId = UUID.randomUUID();
414 assertThatThrownBy(() -> AutomationCompositionProvider
415 .validateInstanceEndpoint(wrongCompositionId, automationComposition))
416 .hasMessageContaining("do not match with");
420 void testGetAcInstancesByFilter() {
421 Page<JpaAutomationComposition> mockPage = new PageImpl<>(inputAutomationCompositionsJpa);
422 var acRepository = mock(AutomationCompositionRepository.class);
423 when(acRepository.findByStateChangeResultIn(anyCollection(), any(Pageable.class)))
424 .thenReturn(mockPage);
425 when(acRepository.findByDeployStateIn(anyCollection(), any(Pageable.class)))
426 .thenReturn(mockPage);
428 var stateChangeResults = new ArrayList<StateChangeResult>();
429 var deployStates = new ArrayList<DeployState>();
430 var pageable = Pageable.unpaged();
431 when(acRepository.findByStateChangeResultInAndDeployStateIn(
432 stateChangeResults, deployStates, pageable)).thenReturn(mockPage);
433 when(acRepository.findAll(any(Pageable.class))).thenReturn(mockPage);
434 var acProvider = new AutomationCompositionProvider(acRepository,
435 mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
437 var acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
438 assertNotNull(acInstances);
439 assertEquals(2, acInstances.size());
441 stateChangeResults.add(StateChangeResult.NO_ERROR);
442 acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
443 assertNotNull(acInstances);
445 deployStates.add(DeployState.DEPLOYED);
446 acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
447 assertNotNull(acInstances);
449 stateChangeResults.clear();
450 acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
451 assertNotNull(acInstances);
455 void testGetAcInstancesByFilterWithNull() {
456 var provider = new AutomationCompositionProvider(mock(AutomationCompositionRepository.class),
457 mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
458 var stateChangeResults = new ArrayList<StateChangeResult>();
459 var deployStates = new ArrayList<DeployState>();
460 var pageable = Pageable.unpaged();
461 assertThrows(NullPointerException.class, () ->
462 provider.getAcInstancesByStateResultDeployState(null, deployStates, pageable));
463 assertThrows(NullPointerException.class, () ->
464 provider.getAcInstancesByStateResultDeployState(stateChangeResults, null, pageable));
465 assertThrows(NullPointerException.class, () ->
466 provider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, null));