2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023-2024 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.controlloop.actor.appclcm;
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
26 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertFalse;
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertNull;
31 import static org.junit.jupiter.api.Assertions.assertSame;
32 import static org.junit.jupiter.api.Assertions.assertTrue;
34 import java.util.HashMap;
35 import java.util.List;
38 import java.util.stream.Collectors;
39 import org.junit.jupiter.api.AfterAll;
40 import org.junit.jupiter.api.AfterEach;
41 import org.junit.jupiter.api.BeforeAll;
42 import org.junit.jupiter.api.BeforeEach;
43 import org.junit.jupiter.api.Test;
44 import org.junit.jupiter.api.extension.ExtendWith;
45 import org.mockito.junit.jupiter.MockitoExtension;
46 import org.onap.policy.appclcm.AppcLcmBody;
47 import org.onap.policy.appclcm.AppcLcmCommonHeader;
48 import org.onap.policy.appclcm.AppcLcmMessageWrapper;
49 import org.onap.policy.appclcm.AppcLcmOutput;
50 import org.onap.policy.appclcm.AppcLcmResponseStatus;
51 import org.onap.policy.common.message.bus.event.TopicSink;
52 import org.onap.policy.common.message.bus.event.TopicSource;
53 import org.onap.policy.common.utils.coder.Coder;
54 import org.onap.policy.common.utils.coder.CoderException;
55 import org.onap.policy.common.utils.coder.StandardCoder;
56 import org.onap.policy.controlloop.ControlLoopOperation;
57 import org.onap.policy.controlloop.actor.test.BasicBidirectionalTopicOperation;
58 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
59 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
60 import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperation.Status;
61 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
62 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
63 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
64 import org.onap.policy.simulators.AppcLcmTopicServer;
65 import org.onap.policy.simulators.TopicServer;
67 @ExtendWith(MockitoExtension.class)
68 class AppcLcmOperationTest extends BasicBidirectionalTopicOperation<AppcLcmMessageWrapper> {
70 private static final String EXPECTED_EXCEPTION = "expected exception";
71 private static final String PAYLOAD_KEY1 = "key-A";
72 private static final String PAYLOAD_VALUE1 = "value-A";
73 private static final String MY_MESSAGE = "my-message";
74 protected static final String MY_VNF = "my-vnf";
75 protected static final String RESOURCE_ID = "my-resource";
76 private static final int SUCCESS_CODE = 400;
78 private AppcLcmMessageWrapper response;
79 private AppcLcmOperation oper;
82 static void setUpBeforeClass() throws Exception {
83 initBeforeClass(MY_SINK, MY_SOURCE);
87 static void tearDownAfterClass() {
98 response = makeResponse();
100 oper = new AppcLcmOperation(params, config);
101 oper.setProperty(OperationProperties.AAI_TARGET_ENTITY, TARGET_ENTITY);
106 super.tearDownBasic();
110 protected TopicServer<AppcLcmMessageWrapper> makeServer(TopicSink sink, TopicSource source) {
111 return new AppcLcmTopicServer(sink, source);
115 * Tests "success" case with simulator.
118 void testSuccess() throws Exception {
119 BidirectionalTopicParams opParams =
120 BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SOURCE).build();
121 config = new BidirectionalTopicConfig(blockingExecutor, opParams, topicMgr, AppcLcmOperation.SELECTOR_KEYS);
123 params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build();
125 oper = new AppcLcmOperation(params, config);
126 oper.setProperty(OperationProperties.AAI_TARGET_ENTITY, TARGET_ENTITY);
128 outcome = oper.start().get();
129 assertNotNull(outcome);
133 void testConstructor() {
134 assertEquals(DEFAULT_ACTOR, oper.getActorName());
135 assertEquals(DEFAULT_OPERATION, oper.getName());
139 void testGetPropertyNames() {
140 assertThat(oper.getPropertyNames()).isEqualTo(List.of(OperationProperties.AAI_TARGET_ENTITY));
144 void testMakeRequest() {
145 oper.generateSubRequestId(2);
146 String subreq = oper.getSubRequestId();
147 assertNotNull(subreq);
149 AppcLcmMessageWrapper request = oper.makeRequest(2);
150 assertEquals("DefaultOperation", request.getBody().getInput().getAction());
152 AppcLcmCommonHeader header = request.getBody().getInput().getCommonHeader();
153 assertNotNull(header);
154 assertEquals(params.getRequestId(), header.getRequestId());
156 assertEquals(subreq, header.getSubRequestId());
158 assertEquals("{vnf-id=my-target}", request.getBody().getInput().getActionIdentifiers().toString());
160 request = oper.makeRequest(2);
161 assertEquals(subreq, request.getBody().getInput().getCommonHeader().getSubRequestId());
165 * Tests makeRequest() when a property is missing.
168 void testMakeRequestMissingProperty() {
169 oper = new AppcLcmOperation(params, config);
170 oper.generateSubRequestId(1);
172 assertThatIllegalStateException().isThrownBy(() -> oper.makeRequest(1))
173 .withMessageContaining("missing target entity");
177 void testConvertPayload() {
178 // only builds a payload for ConfigModify
179 params = params.toBuilder().operation(AppcLcmConstants.OPERATION_CONFIG_MODIFY).build();
180 oper = new AppcLcmOperation(params, config);
181 oper.setProperty(OperationProperties.AAI_TARGET_ENTITY, TARGET_ENTITY);
183 oper.generateSubRequestId(2);
184 AppcLcmMessageWrapper req = oper.makeRequest(2);
185 assertEquals("{\"key-A\":\"value-A\"}", req.getBody().getInput().getPayload());
188 oper = new AppcLcmOperation(params, config) {
190 protected Coder getCoder() {
191 return new StandardCoder() {
193 public String encode(Object object) throws CoderException {
194 throw new CoderException(EXPECTED_EXCEPTION);
200 oper.setProperty(OperationProperties.AAI_TARGET_ENTITY, TARGET_ENTITY);
201 oper.generateSubRequestId(2);
203 assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest(2))
204 .withMessageContaining("Cannot convert payload");
208 void testGetExpectedKeyValues() {
209 oper.generateSubRequestId(2);
210 AppcLcmMessageWrapper request = oper.makeRequest(2);
211 assertEquals(List.of(request.getBody().getInput().getCommonHeader().getSubRequestId()),
212 oper.getExpectedKeyValues(50, request));
216 void testDetmStatus() {
217 assertEquals(Status.SUCCESS, oper.detmStatus(null, response));
220 response.getBody().getOutput().getStatus().setCode(405);
221 assertEquals(Status.FAILURE, oper.detmStatus(null, response));
224 response.getBody().getOutput().getStatus().setCode(200);
225 assertThatIllegalArgumentException().isThrownBy(() -> oper.detmStatus(null, response));
228 response.getBody().getOutput().getStatus().setCode(305);
229 assertThatIllegalArgumentException().isThrownBy(() -> oper.detmStatus(null, response));
232 response.getBody().getOutput().getStatus().setCode(100);
233 assertEquals(Status.STILL_WAITING, oper.detmStatus(null, response));
236 response.getBody().getOutput().getStatus().setCode(-1);
237 assertThatIllegalArgumentException().isThrownBy(() -> oper.detmStatus(null, response));
240 response.getBody().getOutput().setStatus(null);
241 assertThatIllegalArgumentException().isThrownBy(() -> oper.detmStatus(null, response));
245 void testSetOutcome() {
246 oper.setOutcome(outcome, OperationResult.SUCCESS, response);
247 assertEquals(OperationResult.SUCCESS, outcome.getResult());
248 assertEquals(MY_MESSAGE, outcome.getMessage());
249 assertSame(response, outcome.getResponse());
252 oper.setOutcome(outcome, OperationResult.FAILURE, response);
253 assertEquals(OperationResult.FAILURE, outcome.getResult());
254 assertEquals(MY_MESSAGE, outcome.getMessage());
255 assertSame(response, outcome.getResponse());
258 response.getBody().getOutput().getStatus().setMessage(null);
259 oper.setOutcome(outcome, OperationResult.SUCCESS, response);
260 assertEquals(ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
261 assertSame(response, outcome.getResponse());
264 response.getBody().getOutput().setStatus(null);
265 oper.setOutcome(outcome, OperationResult.SUCCESS, response);
266 assertEquals(ControlLoopOperation.SUCCESS_MSG, outcome.getMessage());
267 assertSame(response, outcome.getResponse());
271 void testGetStatus() {
272 assertNotNull(oper.getStatus(response));
275 response.getBody().getOutput().setStatus(null);
276 assertNull(oper.getStatus(response));
279 response.getBody().setOutput(null);
280 assertNull(oper.getStatus(response));
283 response.setBody(null);
284 assertNull(oper.getStatus(response));
287 assertNull(oper.getStatus(null));
291 void testOperationSupportsPayload() {
292 // these should support a payload
293 Set<String> supported = Set.of(AppcLcmConstants.OPERATION_CONFIG_MODIFY);
295 for (String name : supported) {
296 params = params.toBuilder().operation(name).build();
297 oper = new AppcLcmOperation(params, config);
298 assertTrue(oper.operationSupportsPayload(), name);
301 // these should NOT support a payload
302 Set<String> unsupported = AppcLcmConstants.OPERATION_NAMES.stream().filter(name -> !supported.contains(name))
303 .collect(Collectors.toSet());
305 for (String name : unsupported) {
306 params = params.toBuilder().operation(name).build();
307 oper = new AppcLcmOperation(params, config);
308 assertFalse(oper.operationSupportsPayload(), name);
311 // pick an operation that would ordinarily support payloads
312 String sup = supported.iterator().next();
314 // verify that it still supports payload
315 params = params.toBuilder().operation(sup).build();
316 oper = new AppcLcmOperation(params, config);
317 assertTrue(oper.operationSupportsPayload());
319 // try with empty payload
320 params = params.toBuilder().payload(Map.of()).build();
321 oper = new AppcLcmOperation(params, config);
322 assertFalse(oper.operationSupportsPayload());
324 // try with null payload
325 params = params.toBuilder().payload(null).build();
326 oper = new AppcLcmOperation(params, config);
327 assertFalse(oper.operationSupportsPayload());
331 protected void makeContext() {
334 Map<String, String> targetEntities = new HashMap<>();
335 targetEntities.put(ControlLoopOperationParams.PARAMS_ENTITY_RESOURCEID, RESOURCE_ID);
337 params = params.toBuilder().targetEntityIds(targetEntities).build();
341 protected Map<String, Object> makePayload() {
342 return Map.of(PAYLOAD_KEY1, PAYLOAD_VALUE1);
345 private AppcLcmMessageWrapper makeResponse() {
346 AppcLcmMessageWrapper response = new AppcLcmMessageWrapper();
348 AppcLcmBody body = new AppcLcmBody();
349 response.setBody(body);
351 AppcLcmOutput output = new AppcLcmOutput();
352 body.setOutput(output);
354 AppcLcmResponseStatus status = new AppcLcmResponseStatus();
355 output.setStatus(status);
356 status.setMessage(MY_MESSAGE);
357 status.setCode(SUCCESS_CODE);