Merge "Add SO actor"
[policy/models.git] / models-interactions / model-actors / actor.so / src / test / java / org / onap / policy / controlloop / actor / so / SoOperationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.actor.so;
22
23 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertSame;
27 import static org.junit.Assert.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.when;
31
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.concurrent.CompletableFuture;
36 import java.util.concurrent.ForkJoinPool;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.atomic.AtomicBoolean;
39 import java.util.function.Consumer;
40 import java.util.function.Supplier;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.onap.aai.domain.yang.CloudRegion;
44 import org.onap.aai.domain.yang.GenericVnf;
45 import org.onap.aai.domain.yang.ServiceInstance;
46 import org.onap.aai.domain.yang.Tenant;
47 import org.onap.policy.aai.AaiCqResponse;
48 import org.onap.policy.common.utils.coder.CoderException;
49 import org.onap.policy.controlloop.ControlLoopOperation;
50 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
51 import org.onap.policy.controlloop.policy.PolicyResult;
52 import org.onap.policy.so.SoModelInfo;
53 import org.onap.policy.so.SoRequest;
54 import org.onap.policy.so.SoRequestInfo;
55 import org.onap.policy.so.SoRequestParameters;
56 import org.onap.policy.so.SoRequestReferences;
57 import org.onap.policy.so.SoRequestStatus;
58 import org.onap.policy.so.SoResponse;
59
60 public class SoOperationTest extends BasicSoOperation {
61
62     private SoOperation oper;
63
64     /**
65      * Sets up.
66      */
67     @Before
68     public void setUp() throws Exception {
69         super.setUp();
70
71         initOperator();
72
73         oper = new SoOperation(params, soOperator) {};
74     }
75
76     @Test
77     public void testConstructor_testGetWaitMsGet() {
78         assertEquals(DEFAULT_ACTOR, oper.getActorName());
79         assertEquals(DEFAULT_OPERATION, oper.getName());
80         assertSame(soOperator, oper.getOperator());
81         assertEquals(1000 * WAIT_SEC_GETS, oper.getWaitMsGet());
82     }
83
84     @Test
85     public void testStartPreprocessorAsync() {
86         AtomicBoolean guardStarted = new AtomicBoolean();
87
88         oper = new SoOperation(params, soOperator) {
89             @Override
90             protected CompletableFuture<OperationOutcome> startGuardAsync() {
91                 guardStarted.set(true);
92                 return super.startGuardAsync();
93             }
94         };
95
96         assertNull(oper.startPreprocessorAsync());
97         assertTrue(guardStarted.get());
98     }
99
100     @Test
101     public void testPostProcess() throws Exception {
102         // completed
103         CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
104         assertTrue(future2.isDone());
105         assertSame(outcome, future2.get());
106         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
107
108         // failed
109         response.getRequest().getRequestStatus().setRequestState(SoOperation.FAILED);
110         future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
111         assertTrue(future2.isDone());
112         assertSame(outcome, future2.get());
113         assertEquals(PolicyResult.FAILURE, outcome.getResult());
114
115         // no request id in the response
116         response.getRequestReferences().setRequestId(null);
117         response.getRequest().getRequestStatus().setRequestState("unknown");
118         assertThatIllegalArgumentException()
119                         .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response))
120                         .withMessage("missing request ID in response");
121         response.getRequestReferences().setRequestId(REQ_ID.toString());
122
123         // status = 500
124         when(rawResponse.getStatus()).thenReturn(500);
125
126         // null request reference
127         SoRequestReferences ref = response.getRequestReferences();
128         response.setRequestReferences(null);
129         assertThatIllegalArgumentException()
130                         .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response))
131                         .withMessage("missing request ID in response");
132         response.setRequestReferences(ref);
133     }
134
135     /**
136      * Tests postProcess() when the "get" is repeated a couple of times.
137      */
138     @Test
139     public void testPostProcessRepeated_testResetGetCount() throws Exception {
140         /*
141          * Two failures and then a success - should result in two "get" calls.
142          *
143          * Note: getStatus() is invoked twice during each call, so have to double up the
144          * return values.
145          */
146         when(rawResponse.getStatus()).thenReturn(500, 500, 500, 500, 200, 200);
147
148         when(client.get(any(), any(), any())).thenAnswer(provideResponse(rawResponse));
149
150         // use a real executor
151         params = params.toBuilder().executor(ForkJoinPool.commonPool()).build();
152
153         oper = new SoOperation(params, soOperator) {
154             @Override
155             public long getWaitMsGet() {
156                 return 1;
157             }
158         };
159
160         CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
161
162         assertSame(outcome, future2.get(5, TimeUnit.SECONDS));
163         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
164         assertEquals(2, oper.getGetCount());
165
166         /*
167          * repeat - this time, the "get" operations will be exhausted, so it should fail
168          */
169         when(rawResponse.getStatus()).thenReturn(500);
170
171         future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
172
173         assertSame(outcome, future2.get(5, TimeUnit.SECONDS));
174         assertEquals(PolicyResult.FAILURE_TIMEOUT, outcome.getResult());
175         assertEquals(MAX_GETS + 1, oper.getGetCount());
176
177         oper.resetGetCount();
178         assertEquals(0, oper.getGetCount());
179     }
180
181     @Test
182     public void testGetRequestState() {
183         SoResponse resp = new SoResponse();
184         assertNull(oper.getRequestState(resp));
185
186         SoRequest req = new SoRequest();
187         resp.setRequest(req);
188         assertNull(oper.getRequestState(resp));
189
190         SoRequestStatus status = new SoRequestStatus();
191         req.setRequestStatus(status);
192         assertNull(oper.getRequestState(resp));
193
194         status.setRequestState("my-state");
195         assertEquals("my-state", oper.getRequestState(resp));
196     }
197
198     @Test
199     public void testIsSuccess() {
200         // always true
201
202         assertTrue(oper.isSuccess(rawResponse, response));
203
204         when(rawResponse.getStatus()).thenReturn(500);
205         assertTrue(oper.isSuccess(rawResponse, response));
206     }
207
208     @Test
209     public void testSetOutcome() {
210         // success case
211         when(rawResponse.getStatus()).thenReturn(200);
212         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response));
213
214         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
215         assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
216
217         // failure case
218         when(rawResponse.getStatus()).thenReturn(500);
219         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response));
220
221         assertEquals(PolicyResult.FAILURE, outcome.getResult());
222         assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
223     }
224
225     @Test
226     public void testPrepareSoModelInfo() throws CoderException {
227         verifyMissingModelInfo(target::getModelCustomizationId, target::setModelCustomizationId);
228         verifyMissingModelInfo(target::getModelInvariantId, target::setModelInvariantId);
229         verifyMissingModelInfo(target::getModelName, target::setModelName);
230         verifyMissingModelInfo(target::getModelVersion, target::setModelVersion);
231         verifyMissingModelInfo(target::getModelVersionId, target::setModelVersionId);
232
233         // valid data
234         SoModelInfo info = oper.prepareSoModelInfo();
235         verifyRequest("model.json", info);
236
237         // try with null target
238         params = params.toBuilder().target(null).build();
239         oper = new SoOperation(params, soOperator) {};
240
241         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo()).withMessage("missing Target");
242     }
243
244     private void verifyMissingModelInfo(Supplier<String> getter, Consumer<String> setter) {
245         String original = getter.get();
246
247         setter.accept(null);
248         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo())
249                         .withMessage("missing VF Module model");
250
251         setter.accept(original);
252     }
253
254     @Test
255     public void testConstructRequestInfo() throws CoderException {
256         SoRequestInfo info = oper.constructRequestInfo();
257         verifyRequest("reqinfo.json", info);
258     }
259
260     @Test
261     public void testBuildRequestParameters() throws CoderException {
262         // valid data
263         SoRequestParameters reqParams = oper.buildRequestParameters();
264         verifyRequest("reqparams.json", reqParams);
265
266         // invalid json
267         params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
268         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
269                         .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
270
271         // missing data
272         params.getPayload().remove(SoOperation.REQ_PARAM_NM);
273         assertNull(oper.buildRequestParameters());
274
275         // null payload
276         params = params.toBuilder().payload(null).build();
277         oper = new SoOperation(params, soOperator) {};
278         assertNull(oper.buildRequestParameters());
279     }
280
281     @Test
282     public void testBuildConfigurationParameters() {
283         // valid data
284         List<Map<String, String>> result = oper.buildConfigurationParameters();
285         assertEquals(List.of(Collections.emptyMap()), result);
286
287         // invalid json
288         params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
289         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
290                         .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
291
292         // missing data
293         params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
294         assertNull(oper.buildConfigurationParameters());
295
296         // null payload
297         params = params.toBuilder().payload(null).build();
298         oper = new SoOperation(params, soOperator) {};
299         assertNull(oper.buildConfigurationParameters());
300     }
301
302     @Test
303     public void testGetVnfItem() {
304         // missing data
305         AaiCqResponse cq = mock(AaiCqResponse.class);
306         assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo()))
307                         .withMessage("missing generic VNF");
308
309         // valid data
310         GenericVnf vnf = new GenericVnf();
311         when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf);
312         assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo()));
313     }
314
315     @Test
316     public void testGetServiceInstance() {
317         // missing data
318         AaiCqResponse cq = mock(AaiCqResponse.class);
319         assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq))
320                         .withMessage("missing VNF Service Item");
321
322         // valid data
323         ServiceInstance instance = new ServiceInstance();
324         when(cq.getServiceInstance()).thenReturn(instance);
325         assertSame(instance, oper.getServiceInstance(cq));
326     }
327
328     @Test
329     public void testGetDefaultTenant() {
330         // missing data
331         AaiCqResponse cq = mock(AaiCqResponse.class);
332         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq))
333                         .withMessage("missing Tenant Item");
334
335         // valid data
336         Tenant tenant = new Tenant();
337         when(cq.getDefaultTenant()).thenReturn(tenant);
338         assertSame(tenant, oper.getDefaultTenant(cq));
339     }
340
341     @Test
342     public void testGetDefaultCloudRegion() {
343         // missing data
344         AaiCqResponse cq = mock(AaiCqResponse.class);
345         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq))
346                         .withMessage("missing Cloud Region");
347
348         // valid data
349         CloudRegion region = new CloudRegion();
350         when(cq.getDefaultCloudRegion()).thenReturn(region);
351         assertSame(region, oper.getDefaultCloudRegion(cq));
352     }
353 }