d054719017eddaec354589f13ab8be435538e420
[policy/clamp.git] /
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.acm.participant.intermediary.handler;
22
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;
28
29 import jakarta.ws.rs.core.Response.Status;
30 import java.io.IOException;
31 import java.util.Map;
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;
46
47 class ThreadHandlerTest {
48
49     private static final int TIMEOUT = 400;
50
51     @Test
52     void testPrime() 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))) {
56
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);
62
63             clearInvocations(listener);
64             threadHandler.deprime(messageId, composition);
65             verify(listener, timeout(TIMEOUT)).deprime(composition);
66         }
67     }
68
69     @Test
70     void testPrimeException() throws PfModelException, IOException {
71         var listener = mock(AutomationCompositionElementListener.class);
72         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
73         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
74
75             var compositionId = UUID.randomUUID();
76             var composition = new CompositionDto(compositionId, Map.of(), Map.of());
77             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).prime(composition);
78             var messageId = UUID.randomUUID();
79             threadHandler.prime(messageId, composition);
80             verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.COMMISSIONED,
81                 StateChangeResult.FAILED, "Composition Defintion prime failed");
82
83             clearInvocations(listener);
84             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).deprime(composition);
85             threadHandler.deprime(messageId, composition);
86             verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.PRIMED,
87                 StateChangeResult.FAILED, "Composition Defintion deprime failed");
88         }
89     }
90
91     @Test
92     void testDeploy() throws PfModelException, IOException {
93         var listener = mock(AutomationCompositionElementListener.class);
94         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
95         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
96
97             Map<String, Object> properties = Map.of("key", "value");
98             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
99                 properties, properties);
100             var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(),
101                     null, properties, properties);
102             var messageId = UUID.randomUUID();
103             threadHandler.deploy(messageId, compositionElement, instanceElement);
104             verify(listener, timeout(TIMEOUT)).deploy(compositionElement, instanceElement);
105
106             clearInvocations(listener);
107             var element = new AcElementDeploy();
108             var elementId = UUID.randomUUID();
109             element.setId(elementId);
110             var instanceElementUpdated = new InstanceElementDto(instanceElement.instanceId(),
111                 instanceElement.elementId(), null, properties, properties);
112             threadHandler.update(messageId, compositionElement, instanceElement, instanceElementUpdated);
113             verify(listener, timeout(TIMEOUT)).update(compositionElement, instanceElement, instanceElementUpdated);
114
115             clearInvocations(listener);
116             var compositionTargetId = UUID.randomUUID();
117             var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(),
118                 properties, properties);
119             threadHandler.migrate(messageId, compositionElement, compositionElementTarget,
120                 instanceElement, instanceElementUpdated, 0);
121             verify(listener, timeout(TIMEOUT)).migrate(compositionElement, compositionElementTarget,
122                 instanceElement, instanceElementUpdated, 0);
123
124             clearInvocations(listener);
125             threadHandler.undeploy(messageId, compositionElement, instanceElement);
126             verify(listener, timeout(TIMEOUT)).undeploy(compositionElement, instanceElement);
127
128             clearInvocations(listener);
129             threadHandler.delete(messageId, compositionElement, instanceElement);
130             verify(listener, timeout(TIMEOUT)).delete(compositionElement, instanceElement);
131         }
132     }
133
134     @Test
135     void testDeployException() throws PfModelException, IOException {
136         var listener = mock(AutomationCompositionElementListener.class);
137         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
138         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
139
140             Map<String, Object> properties = Map.of("key", "value");
141             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
142                 properties, properties);
143             var instanceId = UUID.randomUUID();
144             var elementId = UUID.randomUUID();
145             var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties);
146             var element = new AcElementDeploy();
147             element.setId(elementId);
148             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
149                 .deploy(compositionElement, instanceElement);
150             var messageId = UUID.randomUUID();
151             threadHandler.deploy(messageId, compositionElement, instanceElement);
152             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
153                 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
154                     "Automation composition element deploy failed");
155
156             clearInvocations(listener);
157             var instanceElementUpdated = new InstanceElementDto(instanceElement.instanceId(),
158                 instanceElement.elementId(), null, properties, properties);
159             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
160                 .update(compositionElement, instanceElement, instanceElementUpdated);
161             threadHandler.update(messageId, compositionElement, instanceElement, instanceElementUpdated);
162             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
163                 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
164                 "Automation composition element update failed");
165
166             clearInvocations(listener);
167             var compositionTargetId = UUID.randomUUID();
168             var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(),
169                 properties, properties);
170             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
171                 .migrate(compositionElement, compositionElementTarget, instanceElement, instanceElementUpdated, 0);
172             threadHandler.migrate(messageId, compositionElement, compositionElementTarget,
173                 instanceElement, instanceElementUpdated, 0);
174             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
175                 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
176                 "Automation composition element migrate failed");
177
178             clearInvocations(listener);
179             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
180                 .undeploy(compositionElement, instanceElement);
181             threadHandler.undeploy(messageId, compositionElement, instanceElement);
182             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
183                 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
184                 "Automation composition element undeploy failed");
185
186             clearInvocations(listener);
187             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
188                 .delete(compositionElement, instanceElement);
189             threadHandler.delete(messageId, compositionElement, instanceElement);
190             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
191                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
192                     "Automation composition element delete failed");
193         }
194     }
195
196     @Test
197     void testLock() throws PfModelException, IOException {
198         var listener = mock(AutomationCompositionElementListener.class);
199         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
200         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
201
202             Map<String, Object> properties = Map.of("key", "value");
203             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
204                 properties, properties);
205             var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(),
206                 null, properties, properties);
207             var messageId = UUID.randomUUID();
208             threadHandler.lock(messageId, compositionElement, instanceElement);
209             verify(listener, timeout(TIMEOUT)).lock(compositionElement, instanceElement);
210
211             clearInvocations(listener);
212             threadHandler.unlock(messageId, compositionElement, instanceElement);
213             verify(listener, timeout(TIMEOUT)).unlock(compositionElement, instanceElement);
214
215             clearInvocations(listener);
216             threadHandler.undeploy(messageId, compositionElement, instanceElement);
217             verify(listener, timeout(TIMEOUT)).undeploy(compositionElement, instanceElement);
218         }
219     }
220
221     @Test
222     void testLockException() throws PfModelException, IOException {
223         var listener = mock(AutomationCompositionElementListener.class);
224         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
225         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
226
227             Map<String, Object> properties = Map.of("key", "value");
228             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
229                 properties, properties);
230             var instanceId = UUID.randomUUID();
231             var elementId = UUID.randomUUID();
232             var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties);
233             var element = new AcElementDeploy();
234             element.setId(elementId);
235             var messageId = UUID.randomUUID();
236             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
237                 .lock(compositionElement, instanceElement);
238             threadHandler.lock(messageId, compositionElement, instanceElement);
239             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
240                 null, LockState.UNLOCKED, StateChangeResult.FAILED, "Automation composition element lock failed");
241
242             clearInvocations(listener);
243             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
244                 .unlock(compositionElement, instanceElement);
245             threadHandler.unlock(messageId, compositionElement, instanceElement);
246             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
247                 null, LockState.LOCKED, StateChangeResult.FAILED, "Automation composition element unlock failed");
248         }
249     }
250
251     @Test
252     void testSubState() throws PfModelException, IOException {
253         var listener = mock(AutomationCompositionElementListener.class);
254         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
255         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
256
257             Map<String, Object> properties = Map.of("key", "value");
258             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
259                 properties, properties);
260             var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(),
261                 null, properties, properties);
262             var messageId = UUID.randomUUID();
263             threadHandler.prepare(messageId, compositionElement, instanceElement);
264             verify(listener, timeout(TIMEOUT)).prepare(compositionElement, instanceElement);
265
266             clearInvocations(listener);
267             threadHandler.review(messageId, compositionElement, instanceElement);
268             verify(listener, timeout(TIMEOUT)).review(compositionElement, instanceElement);
269
270             clearInvocations(listener);
271             var instanceElementMigrate = new InstanceElementDto(instanceElement.instanceId(),
272                 instanceElement.elementId(), null, properties, properties);
273             var compositionTargetId = UUID.randomUUID();
274             var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(),
275                 properties, properties);
276             threadHandler.migratePrecheck(messageId, compositionElement, compositionElementTarget,
277                 instanceElement, instanceElementMigrate);
278             verify(listener, timeout(TIMEOUT)).migratePrecheck(compositionElement, compositionElementTarget,
279                 instanceElement, instanceElementMigrate);
280         }
281     }
282
283     @Test
284     void testSubStateException() throws PfModelException, IOException {
285         var listener = mock(AutomationCompositionElementListener.class);
286         var intermediaryApi = mock(ParticipantIntermediaryApi.class);
287         try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) {
288
289             Map<String, Object> properties = Map.of("key", "value");
290             var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(),
291                 properties, properties);
292             var instanceId = UUID.randomUUID();
293             var elementId = UUID.randomUUID();
294             var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties);
295             var element = new AcElementDeploy();
296             element.setId(elementId);
297             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
298                 .prepare(compositionElement, instanceElement);
299             var messageId = UUID.randomUUID();
300             threadHandler.prepare(messageId, compositionElement, instanceElement);
301             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
302                 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
303                 "Automation composition element prepare Pre Deploy failed");
304
305             clearInvocations(listener);
306             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
307                 .review(compositionElement, instanceElement);
308             threadHandler.review(messageId, compositionElement, instanceElement);
309             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
310                 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
311                 "Automation composition element Review failed");
312
313             clearInvocations(listener);
314             var compositionTargetId = UUID.randomUUID();
315             var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(),
316                 properties, properties);
317             var instanceElementMigrate = new InstanceElementDto(instanceElement.instanceId(),
318                 instanceElement.elementId(), null, properties, properties);
319             doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener)
320                 .migratePrecheck(compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate);
321             threadHandler.migratePrecheck(messageId, compositionElement, compositionElementTarget,
322                 instanceElement, instanceElementMigrate);
323             verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId,
324                 DeployState.DEPLOYED, null, StateChangeResult.FAILED,
325                 "Automation composition element migrate precheck failed");
326         }
327     }
328 }