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;
38 import java.util.concurrent.CompletableFuture;
39 import java.util.function.BiConsumer;
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.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.policy.PolicyResult;
56 import org.onap.policy.so.SoModelInfo;
57 import org.onap.policy.so.SoRequest;
58 import org.onap.policy.so.SoRequestInfo;
59 import org.onap.policy.so.SoRequestStatus;
60 import org.onap.policy.so.SoResponse;
62 public class SoOperationTest extends BasicSoOperation {
64 private static final String VF_COUNT_KEY = SoConstants.VF_COUNT_PREFIX
65 + "[my-model-customization-id][my-model-invariant-id][my-model-version-id]";
67 private static final List<String> PROP_NAMES = Collections.emptyList();
69 private static final String VERSION_ID = "1.2.3";
71 private SoOperation oper;
77 public void setUp() throws Exception {
82 oper = new SoOperation(params, config, PROP_NAMES) {};
86 public void testConstructor() {
87 assertEquals(DEFAULT_ACTOR, oper.getActorName());
88 assertEquals(DEFAULT_OPERATION, oper.getName());
89 assertSame(config, oper.getConfig());
90 assertTrue(oper.isUsePolling());
92 // check when Target is null
93 params = params.toBuilder().target(null).build();
94 assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config, PROP_NAMES) {})
95 .withMessageContaining("Target information");
99 public void testValidateTarget() {
100 // check when various fields are null
101 verifyNotNull("modelCustomizationId", target::getModelCustomizationId, target::setModelCustomizationId);
102 verifyNotNull("modelInvariantId", target::getModelInvariantId, target::setModelInvariantId);
103 verifyNotNull("modelVersionId", target::getModelVersionId, target::setModelVersionId);
105 // verify it's still valid
106 assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException();
109 private void verifyNotNull(String expectedText, Supplier<String> getter, Consumer<String> setter) {
110 String originalValue = getter.get();
114 assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config))
115 .withMessageContaining(expectedText);
117 setter.accept(originalValue);
121 public void testStartPreprocessorAsync() {
122 assertNotNull(oper.startPreprocessorAsync());
126 public void testObtainVfCount_testGetVfCount_testSetVfCount() throws Exception {
127 // insert CQ data so it's there for the check
128 context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse());
130 // shouldn't actually need to do anything
131 assertNull(oper.obtainVfCount());
133 // verify that the count was stored
134 Integer vfcount = context.getProperty(VF_COUNT_KEY);
135 assertEquals(VF_COUNT, vfcount);
136 assertEquals(VF_COUNT.intValue(), oper.getVfCount());
138 // change the count and then verify that it isn't overwritten by another call
139 oper.setVfCount(VF_COUNT + 1);
141 assertNull(oper.obtainVfCount());
142 vfcount = context.getProperty(VF_COUNT_KEY);
143 assertEquals(VF_COUNT + 1, vfcount.intValue());
144 assertEquals(VF_COUNT + 1, oper.getVfCount());
148 * Tests the VF Count methods when properties are being used.
149 * @throws Exception if an error occurs
152 public void testGetVfCount_testSetVfCount_ViaProperties() throws Exception {
153 oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
155 // verify that the count was stored
156 assertEquals(VF_COUNT.intValue(), oper.getVfCount());
158 oper.setVfCount(VF_COUNT + 1);
160 int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
161 assertEquals(VF_COUNT + 1, count);
162 assertEquals(VF_COUNT + 1, oper.getVfCount());
166 * Tests obtainVfCount() when it actually has to query.
169 public void testObtainVfCountQuery() throws Exception {
170 CompletableFuture<OperationOutcome> future2 = oper.obtainVfCount();
171 assertNotNull(future2);
172 assertTrue(executor.runAll(100));
175 assertFalse(future2.isDone());
177 provideCqResponse(makeCqResponse());
179 assertTrue(executor.runAll(100));
180 assertTrue(future2.isDone());
181 assertEquals(PolicyResult.SUCCESS, future2.get().getResult());
183 // verify that the count was stored
184 Integer vfcount = context.getProperty(VF_COUNT_KEY);
185 assertEquals(VF_COUNT, vfcount);
187 // repeat - shouldn't need to do anything now
188 assertNull(oper.obtainVfCount());
192 public void testGetRequestState() {
193 SoResponse resp = new SoResponse();
194 assertNull(oper.getRequestState(resp));
196 SoRequest req = new SoRequest();
197 resp.setRequest(req);
198 assertNull(oper.getRequestState(resp));
200 SoRequestStatus status = new SoRequestStatus();
201 req.setRequestStatus(status);
202 assertNull(oper.getRequestState(resp));
204 status.setRequestState("my-state");
205 assertEquals("my-state", oper.getRequestState(resp));
209 public void testIsSuccess() {
212 assertTrue(oper.isSuccess(rawResponse, response));
214 when(rawResponse.getStatus()).thenReturn(500);
215 assertTrue(oper.isSuccess(rawResponse, response));
219 public void testSetOutcome() {
221 when(rawResponse.getStatus()).thenReturn(200);
222 assertSame(outcome, oper.setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response));
224 assertEquals(PolicyResult.SUCCESS, outcome.getResult());
225 assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
226 assertSame(response, outcome.getResponse());
229 when(rawResponse.getStatus()).thenReturn(500);
230 assertSame(outcome, oper.setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response));
232 assertEquals(PolicyResult.FAILURE, outcome.getResult());
233 assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage());
234 assertSame(response, outcome.getResponse());
238 public void testPrepareSoModelInfo() throws CoderException {
239 verifyMissingModelInfo(target::getModelCustomizationId, target::setModelCustomizationId);
240 verifyMissingModelInfo(target::getModelInvariantId, target::setModelInvariantId);
241 verifyMissingModelInfo(target::getModelName, target::setModelName);
242 verifyMissingModelInfo(target::getModelVersion, target::setModelVersion);
243 verifyMissingModelInfo(target::getModelVersionId, target::setModelVersionId);
246 SoModelInfo info = oper.prepareSoModelInfo();
247 verifyRequest("model.json", info);
249 // try with null target
250 params = params.toBuilder().target(null).build();
251 assertThatIllegalArgumentException().isThrownBy(() -> new SoOperation(params, config, PROP_NAMES) {})
252 .withMessageContaining("missing Target");
255 private void verifyMissingModelInfo(Supplier<String> getter, Consumer<String> setter) {
256 String original = getter.get();
259 assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo())
260 .withMessage("missing VF Module model");
262 setter.accept(original);
266 public void testConstructRequestInfo() throws CoderException {
267 SoRequestInfo info = oper.constructRequestInfo();
268 verifyRequest("reqinfo.json", info);
272 public void testBuildRequestParameters() throws CoderException {
274 verifyRequest("reqparams.json", oper.buildRequestParameters().get());
277 params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json");
278 assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters())
279 .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM);
282 params.getPayload().remove(SoOperation.REQ_PARAM_NM);
283 assertTrue(oper.buildRequestParameters().isEmpty());
286 params = params.toBuilder().payload(null).build();
287 oper = new SoOperation(params, config, PROP_NAMES) {};
288 assertTrue(oper.buildRequestParameters().isEmpty());
292 public void testBuildConfigurationParameters() {
294 assertEquals(List.of(Collections.emptyMap()), oper.buildConfigurationParameters().get());
297 params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json");
298 assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters())
299 .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM);
302 params.getPayload().remove(SoOperation.CONFIG_PARAM_NM);
303 assertTrue(oper.buildConfigurationParameters().isEmpty());
306 params = params.toBuilder().payload(null).build();
307 oper = new SoOperation(params, config, PROP_NAMES) {};
308 assertTrue(oper.buildConfigurationParameters().isEmpty());
312 public void testGetItem() {
313 AaiCqResponse cq = mock(AaiCqResponse.class);
314 params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
316 // in neither property nor custom query
317 assertThatIllegalArgumentException().isThrownBy(() -> oper.getItem("propA", cq2 -> null, "not found"))
318 .withMessage("not found");
320 // only in custom query
321 assertEquals("valueB", oper.getItem("propB", cq2 -> "valueB", "failureB"));
323 // both - should choose the property
324 oper.setProperty("propC", "valueC");
325 assertEquals("valueC", oper.getItem("propC", cq2 -> "valueC2", "failureC"));
327 // both - should choose the property, even if it's null
328 oper.setProperty("propD", null);
329 assertNull(oper.getItem("propD", cq2 -> "valueD2", "failureD"));
333 public void testGetVnfItem() {
335 verifyItems(OperationProperties.AAI_VNF, GenericVnf::new,
336 (cq, instance) -> when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(instance),
337 () -> oper.getVnfItem(oper.prepareSoModelInfo()),
338 "missing generic VNF");
343 public void testGetServiceInstance() {
345 verifyItems(OperationProperties.AAI_SERVICE, ServiceInstance::new,
346 (cq, instance) -> when(cq.getServiceInstance()).thenReturn(instance),
347 () -> oper.getServiceInstance(),
348 "missing VNF Service Item");
353 public void testGetDefaultTenant() {
355 verifyItems(OperationProperties.AAI_DEFAULT_TENANT, Tenant::new,
356 (cq, tenant) -> when(cq.getDefaultTenant()).thenReturn(tenant),
357 () -> oper.getDefaultTenant(),
358 "missing Default Tenant Item");
363 public void testGetVnfModel() {
364 GenericVnf vnf = new GenericVnf();
365 vnf.setModelVersionId(VERSION_ID);
368 verifyItems(OperationProperties.AAI_VNF_MODEL, ModelVer::new,
369 (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
370 () -> oper.getVnfModel(vnf),
371 "missing generic VNF Model");
376 public void testGetServiceModel() {
377 ServiceInstance service = new ServiceInstance();
378 service.setModelVersionId(VERSION_ID);
381 verifyItems(OperationProperties.AAI_SERVICE_MODEL, ModelVer::new,
382 (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
383 () -> oper.getServiceModel(service),
384 "missing Service Model");
389 public void testGetDefaultCloudRegion() {
391 verifyItems(OperationProperties.AAI_DEFAULT_CLOUD_REGION, CloudRegion::new,
392 (cq, region) -> when(cq.getDefaultCloudRegion()).thenReturn(region),
393 () -> oper.getDefaultCloudRegion(),
394 "missing Default Cloud Region");
398 private <T> void verifyItems(String propName, Supplier<T> maker, BiConsumer<AaiCqResponse, T> setter,
399 Supplier<T> getter, String errmsg) {
401 AaiCqResponse cq = mock(AaiCqResponse.class);
402 params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
404 // in neither property nor custom query
405 assertThatIllegalArgumentException().isThrownBy(getter::get).withMessage(errmsg);
407 // only in custom query
408 final T item1 = maker.get();
409 setter.accept(cq, item1);
410 assertSame(item1, getter.get());
412 // both - should choose the property
413 final T item2 = maker.get();
414 oper.setProperty(propName, item2);
415 assertSame(item2, getter.get());
417 // both - should choose the property, even if it's null
418 oper.setProperty(propName, null);
419 assertNull(getter.get());
423 public void testGetCoder() throws CoderException {
424 Coder opcoder = oper.getCoder();
426 // ensure we can decode an SO timestamp
427 String json = "{'request':{'finishTime':'Fri, 15 May 2020 12:14:21 GMT'}}";
428 SoResponse resp = opcoder.decode(json.replace('\'', '"'), SoResponse.class);
430 LocalDateTime tfinish = resp.getRequest().getFinishTime();
431 assertNotNull(tfinish);
432 assertEquals(2020, tfinish.getYear());
433 assertEquals(Month.MAY, tfinish.getMonth());