2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2023-2024 Nordix Foundation.
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.mockito.Mockito.clearInvocations;
24 import static org.mockito.Mockito.doThrow;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.timeout;
27 import static org.mockito.Mockito.verify;
29 import jakarta.ws.rs.core.Response.Status;
30 import java.io.IOException;
32 import java.util.UUID;
33 import org.junit.jupiter.api.Test;
34 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
35 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto;
36 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
37 import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
38 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
39 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
40 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
41 import org.onap.policy.clamp.models.acm.concepts.DeployState;
42 import org.onap.policy.clamp.models.acm.concepts.LockState;
43 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
44 import org.onap.policy.models.base.PfModelException;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
47 class ThreadHandlerTest {
49 private static final int TIMEOUT = 400;
52 void test() throws PfModelException, IOException {
53 var listener = mock(AutomationCompositionElementListener.class);
54 var intermediaryApi = mock(ParticipantIntermediaryApi.class);
55 try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
57 var compositionId = UUID.randomUUID();
58 var messageId = UUID.randomUUID();
59 var composition = new CompositionDto(compositionId, Map.of(), Map.of());
60 threadHandler.prime(messageId, composition);
61 verify(listener, timeout(TIMEOUT)).prime(composition);
63 clearInvocations(listener);
64 Map<String, Object> properties = Map.of("key", "value");
65 var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
66 properties, properties);
67 var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(),
68 null, properties, properties);
69 threadHandler.deploy(messageId, compositionElement, instanceElement);
70 verify(listener, timeout(TIMEOUT)).deploy(compositionElement, instanceElement);
72 clearInvocations(listener);
73 var element = new AcElementDeploy();
74 var elementId = UUID.randomUUID();
75 element.setId(elementId);
76 var instanceElementUpdated = new InstanceElementDto(instanceElement.instanceId(),
77 instanceElement.elementId(), null, properties, properties);
78 threadHandler.update(messageId, compositionElement, instanceElement, instanceElementUpdated);
79 verify(listener, timeout(TIMEOUT)).update(compositionElement, instanceElement, instanceElementUpdated);
81 clearInvocations(listener);
82 var compositionTargetId = UUID.randomUUID();
83 var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(),
84 properties, properties);
85 threadHandler.migrate(messageId, compositionElement, compositionElementTarget,
86 instanceElement, instanceElementUpdated);
87 verify(listener, timeout(TIMEOUT)).migrate(compositionElement, compositionElementTarget,
88 instanceElement, instanceElementUpdated);
90 clearInvocations(listener);
91 threadHandler.lock(messageId, compositionElement, instanceElement);
92 verify(listener, timeout(TIMEOUT)).lock(compositionElement, instanceElement);
94 clearInvocations(listener);
95 threadHandler.unlock(messageId, compositionElement, instanceElement);
96 verify(listener, timeout(TIMEOUT)).unlock(compositionElement, instanceElement);
98 clearInvocations(listener);
99 threadHandler.undeploy(messageId, compositionElement, instanceElement);
100 verify(listener, timeout(TIMEOUT)).undeploy(compositionElement, instanceElement);
102 clearInvocations(listener);
103 threadHandler.delete(messageId, compositionElement, instanceElement);
104 verify(listener, timeout(TIMEOUT)).delete(compositionElement, instanceElement);
106 clearInvocations(listener);
107 threadHandler.deprime(messageId, composition);
108 verify(listener, timeout(TIMEOUT)).deprime(composition);
113 void testException() throws PfModelException, IOException {
114 var listener = mock(AutomationCompositionElementListener.class);
115 var intermediaryApi = mock(ParticipantIntermediaryApi.class);
116 try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
118 var compositionId = UUID.randomUUID();
119 var composition = new CompositionDto(compositionId, Map.of(), Map.of());
120 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
122 var messageId = UUID.randomUUID();
123 threadHandler.prime(messageId, composition);
124 verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.COMMISSIONED,
125 StateChangeResult.FAILED, "Composition Defintion prime failed");
127 clearInvocations(intermediaryApi);
128 Map<String, Object> properties = Map.of("key", "value");
129 var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
130 properties, properties);
131 var instanceId = UUID.randomUUID();
132 var elementId = UUID.randomUUID();
133 var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties);
134 var element = new AcElementDeploy();
135 element.setId(elementId);
136 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
137 .deploy(compositionElement, instanceElement);
138 threadHandler.deploy(messageId, compositionElement, instanceElement);
139 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
140 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
141 "Automation composition element deploy failed");
143 clearInvocations(listener);
144 var instanceElementUpdated = new InstanceElementDto(instanceElement.instanceId(),
145 instanceElement.elementId(), null, properties, properties);
146 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
147 .update(compositionElement, instanceElement, instanceElementUpdated);
148 threadHandler.update(messageId, compositionElement, instanceElement, instanceElementUpdated);
149 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
150 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
151 "Automation composition element update failed");
153 clearInvocations(listener);
154 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
155 .lock(compositionElement, instanceElement);
156 threadHandler.lock(messageId, compositionElement, instanceElement);
157 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
158 null, LockState.UNLOCKED, StateChangeResult.FAILED, "Automation composition element lock failed");
160 clearInvocations(listener);
161 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
162 .unlock(compositionElement, instanceElement);
163 threadHandler.unlock(messageId, compositionElement, instanceElement);
164 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
165 null, LockState.LOCKED, StateChangeResult.FAILED, "Automation composition element unlock failed");
167 clearInvocations(listener);
168 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
169 .undeploy(compositionElement, instanceElement);
170 threadHandler.undeploy(messageId, compositionElement, instanceElement);
171 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
172 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
173 "Automation composition element undeploy failed");
175 clearInvocations(listener);
176 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
177 .delete(compositionElement, instanceElement);
178 threadHandler.delete(messageId, compositionElement, instanceElement);
179 verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
180 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
181 "Automation composition element delete failed");
183 clearInvocations(listener);
184 doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).deprime(composition);
185 threadHandler.deprime(messageId, composition);
186 verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.PRIMED,
187 StateChangeResult.FAILED, "Composition Defintion deprime failed");