2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.controlloop.actor.so;
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;
34 import java.time.LocalDateTime;
35 import java.time.Month;
36 import java.util.Collections;
37 import java.util.List;
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;
63 public class SoOperationTest extends BasicSoOperation {
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]";
68 private static final List<String> PROP_NAMES = Collections.emptyList();
70 private static final String VERSION_ID = "1.2.3";
72 private SoOperation oper;
79 public void setUp() throws Exception {
84 oper = new SoOperation(params, config, PROP_NAMES) {};
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());
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");
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);
107 // verify it's still valid
108 assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException();
111 private void verifyNotNull(String expectedText, Map<String, String> targetEntities) {
112 String originalValue = targetEntities.get(expectedText);
115 targetEntities.put(expectedText, null);
116 assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config))
117 .withMessageContaining(expectedText);
119 targetEntities.put(expectedText, originalValue);
123 public void testStartPreprocessorAsync() {
124 assertNotNull(oper.startPreprocessorAsync());
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());
132 // shouldn't actually need to do anything
133 assertNull(oper.obtainVfCount());
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());
140 // change the count and then verify that it isn't overwritten by another call
141 oper.setVfCount(VF_COUNT + 1);
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());
150 * Tests the VF Count methods when properties are being used.
151 * @throws Exception if an error occurs
154 public void testGetVfCount_testSetVfCount_ViaProperties() throws Exception {
155 oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
157 // verify that the count was stored
158 assertEquals(VF_COUNT.intValue(), oper.getVfCount());
160 oper.setVfCount(VF_COUNT + 1);
162 int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
163 assertEquals(VF_COUNT + 1, count);
164 assertEquals(VF_COUNT + 1, oper.getVfCount());
168 * Tests obtainVfCount() when it actually has to query.
171 public void testObtainVfCountQuery() throws Exception {
172 CompletableFuture<OperationOutcome> future2 = oper.obtainVfCount();
173 assertNotNull(future2);
174 assertTrue(executor.runAll(100));
177 assertFalse(future2.isDone());
179 provideCqResponse(makeCqResponse());
181 assertTrue(executor.runAll(100));
182 assertTrue(future2.isDone());
183 assertEquals(OperationResult.SUCCESS, future2.get().getResult());
185 // verify that the count was stored
186 Integer vfcount = context.getProperty(VF_COUNT_KEY);
187 assertEquals(VF_COUNT, vfcount);
189 // repeat - shouldn't need to do anything now
190 assertNull(oper.obtainVfCount());
194 public void testGetRequestState() {
195 SoResponse resp = new SoResponse();
196 assertNull(oper.getRequestState(resp));
198 SoRequest req = new SoRequest();
199 resp.setRequest(req);
200 assertNull(oper.getRequestState(resp));
202 SoRequestStatus status = new SoRequestStatus();
203 req.setRequestStatus(status);
204 assertNull(oper.getRequestState(resp));
206 status.setRequestState("my-state");
207 assertEquals("my-state", oper.getRequestState(resp));
211 public void testIsSuccess() {
214 assertTrue(oper.isSuccess(rawResponse, response));
216 when(rawResponse.getStatus()).thenReturn(500);
217 assertTrue(oper.isSuccess(rawResponse, response));
221 public void testSetOutcome() {
223 when(rawResponse.getStatus()).thenReturn(200);
224 assertSame(outcome, oper.setOutcome(outcome, OperationResult.SUCCESS, rawResponse, response));
226 assertEquals(OperationResult.SUCCESS, outcome.getResult());
227 assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
228 assertSame(response, outcome.getResponse());
231 when(rawResponse.getStatus()).thenReturn(500);
232 assertSame(outcome, oper.setOutcome(outcome, OperationResult.FAILURE, rawResponse, response));
234 assertEquals(OperationResult.FAILURE, outcome.getResult());
235 assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
236 assertSame(response, outcome.getResponse());
240 public void testPrepareSoModelInfo() throws CoderException {
242 SoModelInfo info = oper.prepareSoModelInfo();
243 verifyRequest("model.json", info);
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");
252 public void testConstructRequestInfo() throws CoderException {
253 SoRequestInfo info = oper.constructRequestInfo();
254 verifyRequest("reqinfo.json", info);
258 public void testBuildRequestParameters() throws CoderException {
260 verifyRequest("reqparams.json", oper.buildRequestParameters().get());
263 params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
264 assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
265 .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
268 params.getPayload().remove(SoOperation.REQ_PARAM_NM);
269 assertTrue(oper.buildRequestParameters().isEmpty());
272 params = params.toBuilder().payload(null).build();
273 oper = new SoOperation(params, config, PROP_NAMES) {};
274 assertTrue(oper.buildRequestParameters().isEmpty());
278 public void testBuildConfigurationParameters() {
280 assertEquals(List.of(Collections.emptyMap()), oper.buildConfigurationParameters().get());
283 params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
284 assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
285 .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
288 params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
289 assertTrue(oper.buildConfigurationParameters().isEmpty());
292 params = params.toBuilder().payload(null).build();
293 oper = new SoOperation(params, config, PROP_NAMES) {};
294 assertTrue(oper.buildConfigurationParameters().isEmpty());
298 public void testGetItem() {
299 AaiCqResponse cq = mock(AaiCqResponse.class);
300 params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
302 // in neither property nor custom query
303 assertThatIllegalArgumentException().isThrownBy(() -> oper.getItem("propA", cq2 -> null, "not found"))
304 .withMessage("not found");
306 // only in custom query
307 assertEquals("valueB", oper.getItem("propB", cq2 -> "valueB", "failureB"));
309 // both - should choose the property
310 oper.setProperty("propC", "valueC");
311 assertEquals("valueC", oper.getItem("propC", cq2 -> "valueC2", "failureC"));
313 // both - should choose the property, even if it's null
314 oper.setProperty("propD", null);
315 assertNull(oper.getItem("propD", cq2 -> "valueD2", "failureD"));
319 public void testGetVnfItem() {
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");
329 public void testGetServiceInstance() {
331 verifyItems(OperationProperties.AAI_SERVICE, ServiceInstance::new,
332 (cq, instance) -> when(cq.getServiceInstance()).thenReturn(instance),
333 () -> oper.getServiceInstance(),
334 "missing VNF Service Item");
339 public void testGetDefaultTenant() {
341 verifyItems(OperationProperties.AAI_DEFAULT_TENANT, Tenant::new,
342 (cq, tenant) -> when(cq.getDefaultTenant()).thenReturn(tenant),
343 () -> oper.getDefaultTenant(),
344 "missing Default Tenant Item");
349 public void testGetVnfModel() {
350 GenericVnf vnf = new GenericVnf();
351 vnf.setModelVersionId(VERSION_ID);
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");
362 public void testGetServiceModel() {
363 ServiceInstance service = new ServiceInstance();
364 service.setModelVersionId(VERSION_ID);
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");
375 public void testGetDefaultCloudRegion() {
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");
384 private <T> void verifyItems(String propName, Supplier<T> maker, BiConsumer<AaiCqResponse, T> setter,
385 Supplier<T> getter, String errmsg) {
387 AaiCqResponse cq = mock(AaiCqResponse.class);
388 params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
390 // in neither property nor custom query
391 assertThatIllegalArgumentException().isThrownBy(getter::get).withMessage(errmsg);
393 // only in custom query
394 final T item1 = maker.get();
395 setter.accept(cq, item1);
396 assertSame(item1, getter.get());
398 // both - should choose the property
399 final T item2 = maker.get();
400 oper.setProperty(propName, item2);
401 assertSame(item2, getter.get());
403 // both - should choose the property, even if it's null
404 oper.setProperty(propName, null);
405 assertNull(getter.get());
409 public void testGetCoder() throws CoderException {
410 Coder opcoder = oper.getCoder();
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);
416 LocalDateTime tfinish = resp.getRequest().getFinishTime();
417 assertNotNull(tfinish);
418 assertEquals(2020, tfinish.getYear());
419 assertEquals(Month.MAY, tfinish.getMonth());