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.anyIterable;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.Optional;
39 import java.util.UUID;
40 import org.junit.jupiter.api.BeforeEach;
41 import org.junit.jupiter.api.Test;
42 import org.mockito.Mockito;
43 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
44 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
45 import org.onap.policy.clamp.models.acm.concepts.DeployState;
46 import org.onap.policy.clamp.models.acm.concepts.LockState;
47 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
48 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement;
49 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;
50 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository;
51 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRepository;
52 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRollbackRepository;
53 import org.onap.policy.common.utils.coder.Coder;
54 import org.onap.policy.common.utils.coder.StandardCoder;
55 import org.onap.policy.common.utils.resources.ResourceUtils;
56 import org.onap.policy.models.base.PfConceptKey;
57 import org.onap.policy.models.base.PfModelRuntimeException;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
59 import org.springframework.data.domain.PageImpl;
60 import org.springframework.data.domain.PageRequest;
61 import org.springframework.data.domain.Pageable;
63 class AutomationCompositionProviderTest {
65 private static final String AC_IS_NULL = "automationComposition is marked non-null but is null";
66 private static final String ACELEMENT_ID_IS_NULL = "elementId is marked non-null but is null";
68 private static final Coder CODER = new StandardCoder();
69 private static final String AUTOMATION_COMPOSITION_JSON =
70 "src/test/resources/providers/TestAutomationCompositions.json";
72 private AutomationCompositions inputAutomationCompositions;
73 private List<JpaAutomationComposition> inputAutomationCompositionsJpa;
74 private final String originalJson = ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON);
77 void beforeSetupDao() throws Exception {
78 inputAutomationCompositions = CODER.decode(originalJson, AutomationCompositions.class);
79 inputAutomationCompositionsJpa =
80 ProviderUtils.getJpaAndValidateList(inputAutomationCompositions.getAutomationCompositionList(),
81 JpaAutomationComposition::new, "automation compositions");
85 void testAutomationCompositionCreate() {
86 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
87 when(automationCompositionRepository.save(any(JpaAutomationComposition.class)))
88 .thenReturn(inputAutomationCompositionsJpa.get(0));
89 var inputAc = inputAutomationCompositions.getAutomationCompositionList().get(0);
91 var automationCompositionProvider = new AutomationCompositionProvider(
92 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
93 mock(AutomationCompositionRollbackRepository.class));
94 var createdAutomationComposition = automationCompositionProvider.createAutomationComposition(inputAc);
95 inputAc.setInstanceId(createdAutomationComposition.getInstanceId());
96 inputAc.setLastMsg(createdAutomationComposition.getLastMsg());
97 assertEquals(inputAc, createdAutomationComposition);
101 void testAutomationCompositionUpdate() {
102 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
103 var automationCompositionProvider = new AutomationCompositionProvider(
104 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
105 mock(AutomationCompositionRollbackRepository.class));
106 assertThatThrownBy(() -> automationCompositionProvider.updateAutomationComposition(null))
107 .hasMessageMatching(AC_IS_NULL);
109 when(automationCompositionRepository.save(inputAutomationCompositionsJpa.get(0)))
110 .thenReturn(inputAutomationCompositionsJpa.get(0));
112 var createdAutomationComposition = automationCompositionProvider
113 .updateAutomationComposition(inputAutomationCompositions.getAutomationCompositionList().get(0));
115 assertEquals(inputAutomationCompositions.getAutomationCompositionList().get(0), createdAutomationComposition);
119 void testGetAutomationCompositionsWithNull() {
120 var automationCompositionProvider = new AutomationCompositionProvider(
121 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
122 mock(AutomationCompositionRollbackRepository.class));
123 assertThatThrownBy(() -> automationCompositionProvider
124 .getAutomationCompositions(UUID.randomUUID(), null, null, null))
125 .hasMessage("pageable is marked non-null but is null");
127 assertThatThrownBy(() -> automationCompositionProvider
128 .getAutomationCompositions(null, null, null, Pageable.unpaged()))
129 .hasMessage("compositionId is marked non-null but is null");
133 void testGetAutomationCompositions() {
134 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
135 var automationCompositionProvider = new AutomationCompositionProvider(
136 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
137 mock(AutomationCompositionRollbackRepository.class));
138 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
139 when(automationCompositionRepository
140 .findAll(Mockito.any(), any(Pageable.class)))
141 .thenReturn(new PageImpl<>(inputAutomationCompositionsJpa));
142 var acList = automationCompositionProvider.getAutomationCompositions(UUID.randomUUID(),
143 automationComposition.getName(), automationComposition.getVersion(), Pageable.unpaged());
144 assertThat(acList).hasSize(2);
146 acList = automationCompositionProvider.getAutomationCompositions(automationComposition.getCompositionId(), null,
147 null, Pageable.unpaged());
148 assertThat(acList).hasSize(2);
150 when(automationCompositionRepository
151 .findAll(Mockito.any(), Mockito.any(Pageable.class)))
152 .thenReturn(new PageImpl<>(inputAutomationCompositionsJpa));
153 acList = automationCompositionProvider.getAutomationCompositions(automationComposition.getCompositionId(), null,
154 null, PageRequest.of(0, 10));
155 assertThat(acList).hasSize(2);
159 void testGetAutomationComposition() {
160 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
161 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
162 var automationCompositionProvider = new AutomationCompositionProvider(
163 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
164 mock(AutomationCompositionRollbackRepository.class));
166 () -> automationCompositionProvider.getAutomationComposition(automationComposition.getInstanceId()))
167 .hasMessageMatching("AutomationComposition not found");
169 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
170 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
171 var ac = automationCompositionProvider.getAutomationComposition(automationComposition.getInstanceId());
172 assertEquals(automationComposition, ac);
176 void testFindAutomationComposition() {
177 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
178 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
179 var automationCompositionProvider = new AutomationCompositionProvider(
180 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
181 mock(AutomationCompositionRollbackRepository.class));
182 var acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
183 assertThat(acOpt).isEmpty();
185 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
186 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
187 acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
188 assertEquals(automationComposition, acOpt.get());
192 void testGetAcInstancesByCompositionId() {
193 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
194 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
195 when(automationCompositionRepository.findByCompositionId(automationComposition.getCompositionId().toString()))
196 .thenReturn(inputAutomationCompositionsJpa);
197 var automationCompositionProvider = new AutomationCompositionProvider(
198 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
199 mock(AutomationCompositionRollbackRepository.class));
201 automationCompositionProvider.getAcInstancesByCompositionId(automationComposition.getCompositionId());
202 assertEquals(inputAutomationCompositions.getAutomationCompositionList(), acList);
206 void testGetAcInstancesInTransition() {
207 inputAutomationCompositions.getAutomationCompositionList().get(0).setDeployState(DeployState.DEPLOYING);
208 inputAutomationCompositions.getAutomationCompositionList().get(1).setLockState(LockState.LOCKING);
209 inputAutomationCompositionsJpa.get(0).setDeployState(DeployState.DEPLOYING);
210 inputAutomationCompositionsJpa.get(1).setLockState(LockState.LOCKING);
212 List<JpaAutomationComposition> res1 = new ArrayList<>();
213 res1.add(inputAutomationCompositionsJpa.get(0));
215 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
216 when(automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
217 DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING,
218 DeployState.MIGRATION_REVERTING)))
220 when(automationCompositionRepository.findByLockStateIn(List.of(LockState.LOCKING, LockState.UNLOCKING)))
221 .thenReturn(List.of(inputAutomationCompositionsJpa.get(1)));
222 var automationCompositionProvider = new AutomationCompositionProvider(
223 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
224 mock(AutomationCompositionRollbackRepository.class));
225 var acList = automationCompositionProvider.getAcInstancesInTransition();
226 assertThat(acList).hasSize(2)
227 .contains(inputAutomationCompositions.getAutomationCompositionList().get(0).getInstanceId())
228 .contains(inputAutomationCompositions.getAutomationCompositionList().get(1).getInstanceId());
232 void testDeleteAutomationComposition() {
233 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
234 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
235 var automationCompositionProvider = new AutomationCompositionProvider(
236 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
237 acRollbackRepository);
238 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(UUID.randomUUID()))
239 .hasMessageMatching(".*.failed, automation composition does not exist");
241 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationComposition(null))
242 .hasMessageMatching("instanceId is marked non-null but is null");
244 var automationComposition = inputAutomationCompositions.getAutomationCompositionList().get(0);
245 when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
246 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
249 automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
250 assertEquals(automationComposition, deletedAc);
252 when(acRollbackRepository.existsById(automationComposition.getInstanceId().toString())).thenReturn(true);
255 automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
256 assertEquals(automationComposition, deletedAc);
257 verify(acRollbackRepository).deleteById(automationComposition.getInstanceId().toString());
261 void testDeleteElementById() {
262 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
263 var acElementRepository = mock(AutomationCompositionElementRepository.class);
264 var automationCompositionProvider = new AutomationCompositionProvider(
265 automationCompositionRepository, acElementRepository,
266 mock(AutomationCompositionRollbackRepository.class));
267 assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationCompositionElement(null))
268 .hasMessageMatching(ACELEMENT_ID_IS_NULL);
269 var elementId = UUID.randomUUID();
270 automationCompositionProvider.deleteAutomationCompositionElement(elementId);
271 verify(acElementRepository).deleteById(elementId.toString());
275 void testValidateElementIds() {
276 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
278 var acElementRepository = mock(AutomationCompositionElementRepository.class);
279 var automationCompositionProvider = new AutomationCompositionProvider(
280 mock(AutomationCompositionRepository.class), acElementRepository,
281 mock(AutomationCompositionRollbackRepository.class));
282 var result = automationCompositionProvider.validateElementIds(ac);
283 assertThat(result.isValid()).isTrue();
285 var jpaElement = new JpaAutomationCompositionElement(ac.getElements().values().iterator().next());
286 when(acElementRepository.findAllById(anyIterable()))
287 .thenReturn(List.of(jpaElement));
289 ac.setInstanceId(null);
290 result = automationCompositionProvider.validateElementIds(ac);
291 assertThat(result.isValid()).isFalse();
293 ac.setInstanceId(UUID.randomUUID());
294 jpaElement.setInstanceId(UUID.randomUUID().toString());
295 result = automationCompositionProvider.validateElementIds(ac);
296 assertThat(result.isValid()).isFalse();
298 ac.setInstanceId(UUID.randomUUID());
299 jpaElement.setInstanceId(ac.getInstanceId().toString());
300 result = automationCompositionProvider.validateElementIds(ac);
301 assertThat(result.isValid()).isTrue();
305 void testCopyAcElements() {
306 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
307 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
308 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
309 var automationCompositionProvider = new AutomationCompositionProvider(
310 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
311 acRollbackRepository);
312 automationCompositionProvider.copyAcElementsBeforeUpdate(ac);
314 verify(acRollbackRepository).save(any(JpaAutomationCompositionRollback.class));
315 var instanceId = ac.getInstanceId();
316 assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
317 .getAutomationCompositionRollback(instanceId));
321 void testGetRollbackSuccess() {
322 var ac = inputAutomationCompositions.getAutomationCompositionList().get(0);
323 var rollback = new JpaAutomationCompositionRollback();
324 rollback.setInstanceId(ac.getInstanceId().toString());
325 rollback.setCompositionId(ac.getCompositionId().toString());
327 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
328 when(acRollbackRepository.findById(anyString())).thenReturn(Optional.of(rollback));
330 var automationCompositionProvider = new AutomationCompositionProvider(
331 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
332 acRollbackRepository);
333 var rbFromDb = automationCompositionProvider.getAutomationCompositionRollback(ac.getInstanceId());
334 assertNotNull(rbFromDb);
338 void testGetRollbackEmpty() {
339 var acRollbackRepository = mock(AutomationCompositionRollbackRepository.class);
340 var automationCompositionProvider = new AutomationCompositionProvider(
341 mock(AutomationCompositionRepository.class), mock(AutomationCompositionElementRepository.class),
342 acRollbackRepository);
343 when(acRollbackRepository.findById(anyString())).thenReturn(Optional.empty());
344 var compositionId = UUID.randomUUID();
345 assertThrows(PfModelRuntimeException.class, () -> automationCompositionProvider
346 .getAutomationCompositionRollback(compositionId));
350 void testVersionCompatibility() {
352 var newDefinition = new PfConceptKey("policy.clamp.element", "1.2.3");
353 var oldDefinition = new PfConceptKey("policy.clamp.element", "1.2.3");
355 var instanceId = UUID.randomUUID();
356 assertDoesNotThrow(() ->
357 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
360 newDefinition.setVersion("1.2.4");
361 assertDoesNotThrow(() ->
362 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
365 newDefinition.setVersion("1.3.1");
366 assertDoesNotThrow(() ->
367 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
370 newDefinition.setVersion("2.1.1");
371 assertDoesNotThrow(() ->
372 AutomationCompositionProvider.checkCompatibility(newDefinition, oldDefinition, instanceId));
375 newDefinition.setName("policy.clamp.newElement");
376 newDefinition.setVersion("2.2.4");
377 assertThatThrownBy(() -> AutomationCompositionProvider
378 .checkCompatibility(newDefinition, oldDefinition, instanceId))
379 .hasMessageContaining("is not compatible");
383 void testValidateNameVersion() {
384 var automationCompositionRepository = mock(AutomationCompositionRepository.class);
385 var automationCompositionProvider = new AutomationCompositionProvider(
386 automationCompositionRepository, mock(AutomationCompositionElementRepository.class),
387 mock(AutomationCompositionRollbackRepository.class));
389 var acIdentifier = new ToscaConceptIdentifier();
390 assertDoesNotThrow(() -> {
391 automationCompositionProvider.validateNameVersion(acIdentifier);
394 when(automationCompositionRepository.findOne(Mockito.any()))
395 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
396 assertThatThrownBy(() -> {
397 automationCompositionProvider.validateNameVersion(acIdentifier);
398 }).hasMessageContaining("already defined");
402 void testValidateInstanceEndpoint() {
403 var automationComposition = new AutomationComposition();
404 automationComposition.setCompositionId(UUID.randomUUID());
406 var compositionId = automationComposition.getCompositionId();
407 assertDoesNotThrow(() -> AutomationCompositionProvider
408 .validateInstanceEndpoint(compositionId, automationComposition));
410 var wrongCompositionId = UUID.randomUUID();
411 assertThatThrownBy(() -> AutomationCompositionProvider
412 .validateInstanceEndpoint(wrongCompositionId, automationComposition))
413 .hasMessageContaining("do not match with");