Merge "Moving common polling code into HttpOperation"
[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.assertFalse;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertSame;
30 import static org.junit.Assert.assertTrue;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.when;
33
34 import java.time.LocalDateTime;
35 import java.time.Month;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.concurrent.CompletableFuture;
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.Coder;
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.SoRequestStatus;
57 import org.onap.policy.so.SoResponse;
58
59 public class SoOperationTest extends BasicSoOperation {
60
61     private static final String VF_COUNT_KEY = SoConstants.VF_COUNT_PREFIX
62                     + "[my-model-customization-id][my-model-invariant-id][my-model-version-id]";
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() {
79         assertEquals(DEFAULT_ACTOR, oper.getActorName());
80         assertEquals(DEFAULT_OPERATION, oper.getName());
81         assertSame(config, oper.getConfig());
82         assertTrue(oper.isUsePolling());
83
84         // check when Target is null
85         params = params.toBuilder().target(null).build();
86         assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config) {})
87                         .withMessageContaining("Target information");
88     }
89
90     @Test
91     public void testValidateTarget() {
92         // check when various fields are null
93         verifyNotNull("modelCustomizationId", target::getModelCustomizationId, target::setModelCustomizationId);
94         verifyNotNull("modelInvariantId", target::getModelInvariantId, target::setModelInvariantId);
95         verifyNotNull("modelVersionId", target::getModelVersionId, target::setModelVersionId);
96
97         // verify it's still valid
98         assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException();
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 testObtainVfCount_testGetVfCount_testSetVfCount() throws Exception {
119         // insert CQ data so it's there for the check
120         context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse());
121
122         // shouldn't actually need to do anything
123         assertNull(oper.obtainVfCount());
124
125         // verify that the count was stored
126         Integer vfcount = context.getProperty(VF_COUNT_KEY);
127         assertEquals(VF_COUNT, vfcount);
128         assertEquals(VF_COUNT.intValue(), oper.getVfCount());
129
130         // change the count and then verify that it isn't overwritten by another call
131         oper.setVfCount(VF_COUNT + 1);
132
133         assertNull(oper.obtainVfCount());
134         vfcount = context.getProperty(VF_COUNT_KEY);
135         assertEquals(VF_COUNT + 1, vfcount.intValue());
136         assertEquals(VF_COUNT + 1, oper.getVfCount());
137     }
138
139     /**
140      * Tests obtainVfCount() when it actually has to query.
141      */
142     @Test
143     public void testObtainVfCountQuery() throws Exception {
144         CompletableFuture<OperationOutcome> future2 = oper.obtainVfCount();
145         assertNotNull(future2);
146         assertTrue(executor.runAll(100));
147
148         // not done yet
149         assertFalse(future2.isDone());
150
151         provideCqResponse(makeCqResponse());
152
153         assertTrue(executor.runAll(100));
154         assertTrue(future2.isDone());
155         assertEquals(PolicyResult.SUCCESS, future2.get().getResult());
156
157         // verify that the count was stored
158         Integer vfcount = context.getProperty(VF_COUNT_KEY);
159         assertEquals(VF_COUNT, vfcount);
160
161         // repeat - shouldn't need to do anything now
162         assertNull(oper.obtainVfCount());
163     }
164
165     @Test
166     public void testGetRequestState() {
167         SoResponse resp = new SoResponse();
168         assertNull(oper.getRequestState(resp));
169
170         SoRequest req = new SoRequest();
171         resp.setRequest(req);
172         assertNull(oper.getRequestState(resp));
173
174         SoRequestStatus status = new SoRequestStatus();
175         req.setRequestStatus(status);
176         assertNull(oper.getRequestState(resp));
177
178         status.setRequestState("my-state");
179         assertEquals("my-state", oper.getRequestState(resp));
180     }
181
182     @Test
183     public void testIsSuccess() {
184         // always true
185
186         assertTrue(oper.isSuccess(rawResponse, response));
187
188         when(rawResponse.getStatus()).thenReturn(500);
189         assertTrue(oper.isSuccess(rawResponse, response));
190     }
191
192     @Test
193     public void testSetOutcome() {
194         // success case
195         when(rawResponse.getStatus()).thenReturn(200);
196         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response));
197
198         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
199         assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
200         assertSame(response, outcome.getResponse());
201
202         // failure case
203         when(rawResponse.getStatus()).thenReturn(500);
204         assertSame(outcome, oper.setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response));
205
206         assertEquals(PolicyResult.FAILURE, outcome.getResult());
207         assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
208         assertSame(response, outcome.getResponse());
209     }
210
211     @Test
212     public void testPrepareSoModelInfo() throws CoderException {
213         verifyMissingModelInfo(target::getModelCustomizationId, target::setModelCustomizationId);
214         verifyMissingModelInfo(target::getModelInvariantId, target::setModelInvariantId);
215         verifyMissingModelInfo(target::getModelName, target::setModelName);
216         verifyMissingModelInfo(target::getModelVersion, target::setModelVersion);
217         verifyMissingModelInfo(target::getModelVersionId, target::setModelVersionId);
218
219         // valid data
220         SoModelInfo info = oper.prepareSoModelInfo();
221         verifyRequest("model.json", info);
222
223         // try with null target
224         params = params.toBuilder().target(null).build();
225         assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config) {})
226                         .withMessageContaining("missing Target");
227     }
228
229     private void verifyMissingModelInfo(Supplier<String> getter, Consumer<String> setter) {
230         String original = getter.get();
231
232         setter.accept(null);
233         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo())
234                         .withMessage("missing VF Module model");
235
236         setter.accept(original);
237     }
238
239     @Test
240     public void testConstructRequestInfo() throws CoderException {
241         SoRequestInfo info = oper.constructRequestInfo();
242         verifyRequest("reqinfo.json", info);
243     }
244
245     @Test
246     public void testBuildRequestParameters() throws CoderException {
247         // valid data
248         verifyRequest("reqparams.json", oper.buildRequestParameters().get());
249
250         // invalid json
251         params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
252         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
253                         .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
254
255         // missing data
256         params.getPayload().remove(SoOperation.REQ_PARAM_NM);
257         assertTrue(oper.buildRequestParameters().isEmpty());
258
259         // null payload
260         params = params.toBuilder().payload(null).build();
261         oper = new SoOperation(params, config) {};
262         assertTrue(oper.buildRequestParameters().isEmpty());
263     }
264
265     @Test
266     public void testBuildConfigurationParameters() {
267         // valid data
268         assertEquals(List.of(Collections.emptyMap()), oper.buildConfigurationParameters().get());
269
270         // invalid json
271         params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
272         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
273                         .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
274
275         // missing data
276         params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
277         assertTrue(oper.buildConfigurationParameters().isEmpty());
278
279         // null payload
280         params = params.toBuilder().payload(null).build();
281         oper = new SoOperation(params, config) {};
282         assertTrue(oper.buildConfigurationParameters().isEmpty());
283     }
284
285     @Test
286     public void testGetVnfItem() {
287         // missing data
288         AaiCqResponse cq = mock(AaiCqResponse.class);
289         assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo()))
290                         .withMessage("missing generic VNF");
291
292         // valid data
293         GenericVnf vnf = new GenericVnf();
294         when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf);
295         assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo()));
296     }
297
298     @Test
299     public void testGetServiceInstance() {
300         // missing data
301         AaiCqResponse cq = mock(AaiCqResponse.class);
302         assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq))
303                         .withMessage("missing VNF Service Item");
304
305         // valid data
306         ServiceInstance instance = new ServiceInstance();
307         when(cq.getServiceInstance()).thenReturn(instance);
308         assertSame(instance, oper.getServiceInstance(cq));
309     }
310
311     @Test
312     public void testGetDefaultTenant() {
313         // missing data
314         AaiCqResponse cq = mock(AaiCqResponse.class);
315         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq))
316                         .withMessage("missing Tenant Item");
317
318         // valid data
319         Tenant tenant = new Tenant();
320         when(cq.getDefaultTenant()).thenReturn(tenant);
321         assertSame(tenant, oper.getDefaultTenant(cq));
322     }
323
324     @Test
325     public void testGetDefaultCloudRegion() {
326         // missing data
327         AaiCqResponse cq = mock(AaiCqResponse.class);
328         assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq))
329                         .withMessage("missing Cloud Region");
330
331         // valid data
332         CloudRegion region = new CloudRegion();
333         when(cq.getDefaultCloudRegion()).thenReturn(region);
334         assertSame(region, oper.getDefaultCloudRegion(cq));
335     }
336
337     @Test
338     public void testGetCoder() throws CoderException {
339         Coder opcoder = oper.getCoder();
340
341         // ensure we can decode an SO timestamp
342         String json = "{'request':{'finishTime':'Fri, 15 May 2020 12:14:21 GMT'}}";
343         SoResponse resp = opcoder.decode(json.replace('\'', '"'), SoResponse.class);
344
345         LocalDateTime tfinish = resp.getRequest().getFinishTime();
346         assertNotNull(tfinish);
347         assertEquals(2020, tfinish.getYear());
348         assertEquals(Month.MAY, tfinish.getMonth());
349     }
350 }