Remove Target and TargetType
[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.Map;
39 import java.util.concurrent.CompletableFuture;
40 import java.util.function.BiConsumer;
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.ModelVer;
47 import org.onap.aai.domain.yang.ServiceInstance;
48 import org.onap.aai.domain.yang.Tenant;
49 import org.onap.policy.aai.AaiCqResponse;
50 import org.onap.policy.common.utils.coder.Coder;
51 import org.onap.policy.common.utils.coder.CoderException;
52 import org.onap.policy.controlloop.ControlLoopOperation;
53 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
54 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
55 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
56 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
57 import org.onap.policy.so.SoModelInfo;
58 import org.onap.policy.so.SoRequest;
59 import org.onap.policy.so.SoRequestInfo;
60 import org.onap.policy.so.SoRequestStatus;
61 import org.onap.policy.so.SoResponse;
62
63 public class SoOperationTest extends BasicSoOperation {
64
65     private static final String VF_COUNT_KEY = SoConstants.VF_COUNT_PREFIX
66                     + "[my-model-customization-id][my-model-invariant-id][my-model-version-id]";
67
68     private static final List<String> PROP_NAMES = Collections.emptyList();
69
70     private static final String VERSION_ID = "1.2.3";
71
72     private SoOperation oper;
73
74     /**
75      * Sets up.
76      */
77     @Override
78     @Before
79     public void setUp() throws Exception {
80         super.setUp();
81
82         initConfig();
83
84         oper = new SoOperation(params, config, PROP_NAMES) {};
85     }
86
87     @Test
88     public void testConstructor() {
89         assertEquals(DEFAULT_ACTOR, oper.getActorName());
90         assertEquals(DEFAULT_OPERATION, oper.getName());
91         assertSame(config, oper.getConfig());
92         assertTrue(oper.isUsePolling());
93
94         // check when Target is null
95         params = params.toBuilder().targetType(null).build();
96         assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config, PROP_NAMES) {})
97                         .withMessageContaining("Target information");
98     }
99
100     @Test
101     public void testValidateTarget() {
102         // check when various fields are null
103         verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_CUSTOMIZATION_ID, targetEntities);
104         verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_INVARIANT_ID, targetEntities);
105         verifyNotNull(ControlLoopOperationParams.PARAMS_ENTITY_MODEL_VERSION_ID, targetEntities);
106
107         // verify it's still valid
108         assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException();
109     }
110
111     private void verifyNotNull(String expectedText, Map<String, String> targetEntities) {
112         String originalValue = targetEntities.get(expectedText);
113
114         // try with null
115         targetEntities.put(expectedText, null);
116         assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config))
117                         .withMessageContaining(expectedText);
118
119         targetEntities.put(expectedText, originalValue);
120     }
121
122     @Test
123     public void testStartPreprocessorAsync() {
124         assertNotNull(oper.startPreprocessorAsync());
125     }
126
127     @Test
128     public void testObtainVfCount_testGetVfCount_testSetVfCount() throws Exception {
129         // insert CQ data so it's there for the check
130         context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse());
131
132         // shouldn't actually need to do anything
133         assertNull(oper.obtainVfCount());
134
135         // verify that the count was stored
136         Integer vfcount = context.getProperty(VF_COUNT_KEY);
137         assertEquals(VF_COUNT, vfcount);
138         assertEquals(VF_COUNT.intValue(), oper.getVfCount());
139
140         // change the count and then verify that it isn't overwritten by another call
141         oper.setVfCount(VF_COUNT + 1);
142
143         assertNull(oper.obtainVfCount());
144         vfcount = context.getProperty(VF_COUNT_KEY);
145         assertEquals(VF_COUNT + 1, vfcount.intValue());
146         assertEquals(VF_COUNT + 1, oper.getVfCount());
147     }
148
149     /**
150      * Tests the VF Count methods when properties are being used.
151      * @throws Exception if an error occurs
152      */
153     @Test
154     public void testGetVfCount_testSetVfCount_ViaProperties() throws Exception {
155         oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
156
157         // verify that the count was stored
158         assertEquals(VF_COUNT.intValue(), oper.getVfCount());
159
160         oper.setVfCount(VF_COUNT + 1);
161
162         int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
163         assertEquals(VF_COUNT + 1, count);
164         assertEquals(VF_COUNT + 1, oper.getVfCount());
165     }
166
167     /**
168      * Tests obtainVfCount() when it actually has to query.
169      */
170     @Test
171     public void testObtainVfCountQuery() throws Exception {
172         CompletableFuture<OperationOutcome> future2 = oper.obtainVfCount();
173         assertNotNull(future2);
174         assertTrue(executor.runAll(100));
175
176         // not done yet
177         assertFalse(future2.isDone());
178
179         provideCqResponse(makeCqResponse());
180
181         assertTrue(executor.runAll(100));
182         assertTrue(future2.isDone());
183         assertEquals(OperationResult.SUCCESS, future2.get().getResult());
184
185         // verify that the count was stored
186         Integer vfcount = context.getProperty(VF_COUNT_KEY);
187         assertEquals(VF_COUNT, vfcount);
188
189         // repeat - shouldn't need to do anything now
190         assertNull(oper.obtainVfCount());
191     }
192
193     @Test
194     public void testGetRequestState() {
195         SoResponse resp = new SoResponse();
196         assertNull(oper.getRequestState(resp));
197
198         SoRequest req = new SoRequest();
199         resp.setRequest(req);
200         assertNull(oper.getRequestState(resp));
201
202         SoRequestStatus status = new SoRequestStatus();
203         req.setRequestStatus(status);
204         assertNull(oper.getRequestState(resp));
205
206         status.setRequestState("my-state");
207         assertEquals("my-state", oper.getRequestState(resp));
208     }
209
210     @Test
211     public void testIsSuccess() {
212         // always true
213
214         assertTrue(oper.isSuccess(rawResponse, response));
215
216         when(rawResponse.getStatus()).thenReturn(500);
217         assertTrue(oper.isSuccess(rawResponse, response));
218     }
219
220     @Test
221     public void testSetOutcome() {
222         // success case
223         when(rawResponse.getStatus()).thenReturn(200);
224         assertSame(outcome, oper.setOutcome(outcome, OperationResult.SUCCESS, rawResponse, response));
225
226         assertEquals(OperationResult.SUCCESS, outcome.getResult());
227         assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
228         assertSame(response, outcome.getResponse());
229
230         // failure case
231         when(rawResponse.getStatus()).thenReturn(500);
232         assertSame(outcome, oper.setOutcome(outcome, OperationResult.FAILURE, rawResponse, response));
233
234         assertEquals(OperationResult.FAILURE, outcome.getResult());
235         assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
236         assertSame(response, outcome.getResponse());
237     }
238
239     @Test
240     public void testPrepareSoModelInfo() throws CoderException {
241         // valid data
242         SoModelInfo info = oper.prepareSoModelInfo();
243         verifyRequest("model.json", info);
244
245         // try with null target
246         params = params.toBuilder().targetType(null).build();
247         assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config, PROP_NAMES) {})
248                         .withMessageContaining("missing Target");
249     }
250
251     @Test
252     public void testConstructRequestInfo() throws CoderException {
253         SoRequestInfo info = oper.constructRequestInfo();
254         verifyRequest("reqinfo.json", info);
255     }
256
257     @Test
258     public void testBuildRequestParameters() throws CoderException {
259         // valid data
260         verifyRequest("reqparams.json", oper.buildRequestParameters().get());
261
262         // invalid json
263         params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
264         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
265                         .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
266
267         // missing data
268         params.getPayload().remove(SoOperation.REQ_PARAM_NM);
269         assertTrue(oper.buildRequestParameters().isEmpty());
270
271         // null payload
272         params = params.toBuilder().payload(null).build();
273         oper = new SoOperation(params, config, PROP_NAMES) {};
274         assertTrue(oper.buildRequestParameters().isEmpty());
275     }
276
277     @Test
278     public void testBuildConfigurationParameters() {
279         // valid data
280         assertEquals(List.of(Collections.emptyMap()), oper.buildConfigurationParameters().get());
281
282         // invalid json
283         params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
284         assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
285                         .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
286
287         // missing data
288         params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
289         assertTrue(oper.buildConfigurationParameters().isEmpty());
290
291         // null payload
292         params = params.toBuilder().payload(null).build();
293         oper = new SoOperation(params, config, PROP_NAMES) {};
294         assertTrue(oper.buildConfigurationParameters().isEmpty());
295     }
296
297     @Test
298     public void testGetItem() {
299         AaiCqResponse cq = mock(AaiCqResponse.class);
300         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
301
302         // in neither property nor custom query
303         assertThatIllegalArgumentException().isThrownBy(() -> oper.getItem("propA", cq2 -> null, "not found"))
304                         .withMessage("not found");
305
306         // only in custom query
307         assertEquals("valueB", oper.getItem("propB", cq2 -> "valueB", "failureB"));
308
309         // both - should choose the property
310         oper.setProperty("propC", "valueC");
311         assertEquals("valueC", oper.getItem("propC", cq2 -> "valueC2", "failureC"));
312
313         // both - should choose the property, even if it's null
314         oper.setProperty("propD", null);
315         assertNull(oper.getItem("propD", cq2 -> "valueD2", "failureD"));
316     }
317
318     @Test
319     public void testGetVnfItem() {
320         // @formatter:off
321         verifyItems(OperationProperties.AAI_VNF, GenericVnf::new,
322             (cq, instance) -> when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(instance),
323             () -> oper.getVnfItem(oper.prepareSoModelInfo()),
324             "missing generic VNF");
325         // @formatter:on
326     }
327
328     @Test
329     public void testGetServiceInstance() {
330         // @formatter:off
331         verifyItems(OperationProperties.AAI_SERVICE, ServiceInstance::new,
332             (cq, instance) -> when(cq.getServiceInstance()).thenReturn(instance),
333             () -> oper.getServiceInstance(),
334             "missing VNF Service Item");
335         // @formatter:on
336     }
337
338     @Test
339     public void testGetDefaultTenant() {
340         // @formatter:off
341         verifyItems(OperationProperties.AAI_DEFAULT_TENANT, Tenant::new,
342             (cq, tenant) -> when(cq.getDefaultTenant()).thenReturn(tenant),
343             () -> oper.getDefaultTenant(),
344             "missing Default Tenant Item");
345         // @formatter:on
346     }
347
348     @Test
349     public void testGetVnfModel() {
350         GenericVnf vnf = new GenericVnf();
351         vnf.setModelVersionId(VERSION_ID);
352
353         // @formatter:off
354         verifyItems(OperationProperties.AAI_VNF_MODEL, ModelVer::new,
355             (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
356             () -> oper.getVnfModel(vnf),
357             "missing generic VNF Model");
358         // @formatter:on
359     }
360
361     @Test
362     public void testGetServiceModel() {
363         ServiceInstance service = new ServiceInstance();
364         service.setModelVersionId(VERSION_ID);
365
366         // @formatter:off
367         verifyItems(OperationProperties.AAI_SERVICE_MODEL, ModelVer::new,
368             (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
369             () -> oper.getServiceModel(service),
370             "missing Service Model");
371         // @formatter:on
372     }
373
374     @Test
375     public void testGetDefaultCloudRegion() {
376         // @formatter:off
377         verifyItems(OperationProperties.AAI_DEFAULT_CLOUD_REGION, CloudRegion::new,
378             (cq, region) -> when(cq.getDefaultCloudRegion()).thenReturn(region),
379             () -> oper.getDefaultCloudRegion(),
380             "missing Default Cloud Region");
381         // @formatter:on
382     }
383
384     private <T> void verifyItems(String propName, Supplier<T> maker, BiConsumer<AaiCqResponse, T> setter,
385                     Supplier<T> getter, String errmsg) {
386
387         AaiCqResponse cq = mock(AaiCqResponse.class);
388         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
389
390         // in neither property nor custom query
391         assertThatIllegalArgumentException().isThrownBy(getter::get).withMessage(errmsg);
392
393         // only in custom query
394         final T item1 = maker.get();
395         setter.accept(cq, item1);
396         assertSame(item1, getter.get());
397
398         // both - should choose the property
399         final T item2 = maker.get();
400         oper.setProperty(propName, item2);
401         assertSame(item2, getter.get());
402
403         // both - should choose the property, even if it's null
404         oper.setProperty(propName, null);
405         assertNull(getter.get());
406     }
407
408     @Test
409     public void testGetCoder() throws CoderException {
410         Coder opcoder = oper.getCoder();
411
412         // ensure we can decode an SO timestamp
413         String json = "{'request':{'finishTime':'Fri, 15 May 2020 12:14:21 GMT'}}";
414         SoResponse resp = opcoder.decode(json.replace('\'', '"'), SoResponse.class);
415
416         LocalDateTime tfinish = resp.getRequest().getFinishTime();
417         assertNotNull(tfinish);
418         assertEquals(2020, tfinish.getYear());
419         assertEquals(Month.MAY, tfinish.getMonth());
420     }
421 }