Change payload to Map<String,Object> so it's more versatile
[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.assertThatCode;
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.when;
33
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.concurrent.CompletableFuture;
38 import java.util.concurrent.ForkJoinPool;
39 import java.util.concurrent.TimeUnit;
40 import java.util.function.Consumer;
41 import java.util.function.Supplier;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.onap.aai.domain.yang.CloudRegion;
45 import org.onap.aai.domain.yang.GenericVnf;
46 import org.onap.aai.domain.yang.ServiceInstance;
47 import org.onap.aai.domain.yang.Tenant;
48 import org.onap.policy.aai.AaiCqResponse;
49 import org.onap.policy.common.utils.coder.CoderException;
50 import org.onap.policy.controlloop.ControlLoopOperation;
51 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
52 import org.onap.policy.controlloop.policy.PolicyResult;
53 import org.onap.policy.so.SoModelInfo;
54 import org.onap.policy.so.SoRequest;
55 import org.onap.policy.so.SoRequestInfo;
56 import org.onap.policy.so.SoRequestParameters;
57 import org.onap.policy.so.SoRequestReferences;
58 import org.onap.policy.so.SoRequestStatus;
59 import org.onap.policy.so.SoResponse;
60
61 public class SoOperationTest extends BasicSoOperation {
62
63     private SoOperation oper;
64
65     /**
66      * Sets up.
67      */
68     @Before
69     public void setUp() throws Exception {
70         super.setUp();
71
72         initConfig();
73
74         oper = new SoOperation(params, config) {};
75     }
76
77     @Test
78     public void testConstructor_testGetWaitMsGet() {
79         assertEquals(DEFAULT_ACTOR, oper.getActorName());
80         assertEquals(DEFAULT_OPERATION, oper.getName());
81         assertSame(config, oper.getConfig());
82         assertEquals(1000 * WAIT_SEC_GETS, oper.getWaitMsGet());
83     }
84
85     @Test
86     public void testValidateTarget() {
87         // check when various fields are null
88         verifyNotNull("model-customization-id", target::getModelCustomizationId, target::setModelCustomizationId);
89         verifyNotNull("model-invariant-id", target::getModelInvariantId, target::setModelInvariantId);
90         verifyNotNull("model-version-id", target::getModelVersionId, target::setModelVersionId);
91
92         // verify it's still valid
93         assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException();
94
95         // check when Target, itself, is null
96         params = params.toBuilder().target(null).build();
97         assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config))
98                         .withMessageContaining("Target information");
99     }
100
101     private void verifyNotNull(String expectedText, Supplier<String> getter, Consumer<String> setter) {
102         String originalValue = getter.get();
103
104         // try with null
105         setter.accept(null);
106         assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config))
107                         .withMessageContaining(expectedText);
108
109         setter.accept(originalValue);
110     }
111
112     @Test
113     public void testStartPreprocessorAsync() {
114         assertNotNull(oper.startPreprocessorAsync());
115     }
116
117     @Test
118     public void testStoreVfCountRunGuard() throws Exception {
119         // insert CQ data so it's there for the guard
120         context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse());
121
122         // cause guard to fail
123         OperationOutcome outcome2 = params.makeOutcome();
124         outcome2.setResult(PolicyResult.FAILURE);
125         when(guardOperation.start()).thenReturn(CompletableFuture.completedFuture(outcome2));
126
127         CompletableFuture<OperationOutcome> future2 = oper.storeVfCountRunGuard();
128         assertTrue(executor.runAll(100));
129         assertTrue(future2.isDone());
130         assertEquals(PolicyResult.FAILURE, future2.get().getResult());
131
132         // verify that the count was stored
133         Integer vfcount = context.getProperty(SoConstants.CONTEXT_KEY_VF_COUNT);
134         assertEquals(VF_COUNT, vfcount);
135     }
136
137     @Test
138     public void testPostProcess() throws Exception {
139         // completed
140         CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
141         assertTrue(future2.isDone());
142         assertSame(outcome, future2.get());
143         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
144
145         // failed
146         response.getRequest().getRequestStatus().setRequestState(SoOperation.FAILED);
147         future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
148         assertTrue(future2.isDone());
149         assertSame(outcome, future2.get());
150         assertEquals(PolicyResult.FAILURE, outcome.getResult());
151
152         // no request id in the response
153         response.getRequestReferences().setRequestId(null);
154         response.getRequest().getRequestStatus().setRequestState("unknown");
155         assertThatIllegalArgumentException()
156                         .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response))
157                         .withMessage("missing request ID in response");
158         response.getRequestReferences().setRequestId(REQ_ID.toString());
159
160         // status = 500
161         when(rawResponse.getStatus()).thenReturn(500);
162
163         // null request reference
164         SoRequestReferences ref = response.getRequestReferences();
165         response.setRequestReferences(null);
166         assertThatIllegalArgumentException()
167                         .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response))
168                         .withMessage("missing request ID in response");
169         response.setRequestReferences(ref);
170     }
171
172     /**
173      * Tests postProcess() when the "get" is repeated a couple of times.
174      */
175     @Test
176     public void testPostProcessRepeated_testResetGetCount() throws Exception {
177         /*
178          * Two failures and then a success - should result in two "get" calls.
179          *
180          * Note: getStatus() is invoked twice during each call, so have to double up the
181          * return values.
182          */
183         when(rawResponse.getStatus()).thenReturn(500, 500, 500, 500, 200, 200);
184
185         when(client.get(any(), any(), any())).thenAnswer(provideResponse(rawResponse));
186
187         // use a real executor
188         params = params.toBuilder().executor(ForkJoinPool.commonPool()).build();
189
190         oper = new SoOperation(params, config) {
191             @Override
192             public long getWaitMsGet() {
193                 return 1;
194             }
195         };
196
197         CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
198
199         assertSame(outcome, future2.get(500, TimeUnit.SECONDS));
200         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
201         assertEquals(2, oper.getGetCount());
202
203         /*
204          * repeat - this time, the "get" operations will be exhausted, so it should fail
205          */
206         when(rawResponse.getStatus()).thenReturn(500);
207
208         future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
209
210         assertSame(outcome, future2.get(5, TimeUnit.SECONDS));
211         assertEquals(PolicyResult.FAILURE_TIMEOUT, outcome.getResult());
212         assertEquals(MAX_GETS + 1, oper.getGetCount());
213
214         oper.resetGetCount();
215         assertEquals(0, oper.getGetCount());
216     }
217
218     @Test
219     public void testGetRequestState() {
220         SoResponse resp = new SoResponse();
221         assertNull(oper.getRequestState(resp));
222
223         SoRequest req = new SoRequest();
224         resp.setRequest(req);
225         assertNull(oper.getRequestState(resp));
226
227         SoRequestStatus status = new SoRequestStatus();
228         req.setRequestStatus(status);
229         assertNull(oper.getRequestState(resp));
230
231         status.setRequestState("my-state");
232         assertEquals("my-state", oper.getRequestState(resp));
233     }
234
235     @Test
236     public void testIsSuccess() {
237         // always true
238
239         assertTrue(oper.isSuccess(rawResponse, response));
240
241         when(rawResponse.getStatus()).thenReturn(500);
242         assertTrue(oper.isSuccess(rawResponse, response));
243     }
244
245     @Test
246     public void testSetOutcome() {
247         // success case
248         when(rawResponse.getStatus()).thenReturn(200);
249         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response));
250
251         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
252         assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
253
254         // failure case
255         when(rawResponse.getStatus()).thenReturn(500);
256         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response));
257
258         assertEquals(PolicyResult.FAILURE, outcome.getResult());
259         assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
260     }
261
262     @Test
263     public void testPrepareSoModelInfo() throws CoderException {
264         verifyMissingModelInfo(target::getModelCustomizationId, target::setModelCustomizationId);
265         verifyMissingModelInfo(target::getModelInvariantId, target::setModelInvariantId);
266         verifyMissingModelInfo(target::getModelName, target::setModelName);
267         verifyMissingModelInfo(target::getModelVersion, target::setModelVersion);
268         verifyMissingModelInfo(target::getModelVersionId, target::setModelVersionId);
269
270         // valid data
271         SoModelInfo info = oper.prepareSoModelInfo();
272         verifyRequest("model.json", info);
273
274         // try with null target
275         params = params.toBuilder().target(null).build();
276         oper = new SoOperation(params, config) {};
277
278         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo()).withMessage("missing Target");
279     }
280
281     private void verifyMissingModelInfo(Supplier<String> getter, Consumer<String> setter) {
282         String original = getter.get();
283
284         setter.accept(null);
285         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo())
286                         .withMessage("missing VF Module model");
287
288         setter.accept(original);
289     }
290
291     @Test
292     public void testConstructRequestInfo() throws CoderException {
293         SoRequestInfo info = oper.constructRequestInfo();
294         verifyRequest("reqinfo.json", info);
295     }
296
297     @Test
298     public void testBuildRequestParameters() throws CoderException {
299         // valid data
300         SoRequestParameters reqParams = oper.buildRequestParameters();
301         verifyRequest("reqparams.json", reqParams);
302
303         // invalid json
304         params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
305         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
306                         .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
307
308         // missing data
309         params.getPayload().remove(SoOperation.REQ_PARAM_NM);
310         assertNull(oper.buildRequestParameters());
311
312         // null payload
313         params = params.toBuilder().payload(null).build();
314         oper = new SoOperation(params, config) {};
315         assertNull(oper.buildRequestParameters());
316     }
317
318     @Test
319     public void testBuildConfigurationParameters() {
320         // valid data
321         List<Map<String, String>> result = oper.buildConfigurationParameters();
322         assertEquals(List.of(Collections.emptyMap()), result);
323
324         // invalid json
325         params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
326         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
327                         .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
328
329         // missing data
330         params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
331         assertNull(oper.buildConfigurationParameters());
332
333         // null payload
334         params = params.toBuilder().payload(null).build();
335         oper = new SoOperation(params, config) {};
336         assertNull(oper.buildConfigurationParameters());
337     }
338
339     @Test
340     public void testGetVnfItem() {
341         // missing data
342         AaiCqResponse cq = mock(AaiCqResponse.class);
343         assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo()))
344                         .withMessage("missing generic VNF");
345
346         // valid data
347         GenericVnf vnf = new GenericVnf();
348         when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf);
349         assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo()));
350     }
351
352     @Test
353     public void testGetServiceInstance() {
354         // missing data
355         AaiCqResponse cq = mock(AaiCqResponse.class);
356         assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq))
357                         .withMessage("missing VNF Service Item");
358
359         // valid data
360         ServiceInstance instance = new ServiceInstance();
361         when(cq.getServiceInstance()).thenReturn(instance);
362         assertSame(instance, oper.getServiceInstance(cq));
363     }
364
365     @Test
366     public void testGetDefaultTenant() {
367         // missing data
368         AaiCqResponse cq = mock(AaiCqResponse.class);
369         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq))
370                         .withMessage("missing Tenant Item");
371
372         // valid data
373         Tenant tenant = new Tenant();
374         when(cq.getDefaultTenant()).thenReturn(tenant);
375         assertSame(tenant, oper.getDefaultTenant(cq));
376     }
377
378     @Test
379     public void testGetDefaultCloudRegion() {
380         // missing data
381         AaiCqResponse cq = mock(AaiCqResponse.class);
382         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq))
383                         .withMessage("missing Cloud Region");
384
385         // valid data
386         CloudRegion region = new CloudRegion();
387         when(cq.getDefaultCloudRegion()).thenReturn(region);
388         assertSame(region, oper.getDefaultCloudRegion(cq));
389     }
390 }