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.drools.apps.controller.usecases.step;
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatCode;
25 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
38 import java.util.HashMap;
39 import java.util.List;
41 import java.util.TreeMap;
42 import java.util.UUID;
43 import java.util.concurrent.BlockingQueue;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.ForkJoinPool;
46 import java.util.concurrent.LinkedBlockingQueue;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.onap.aai.domain.yang.CloudRegion;
52 import org.onap.aai.domain.yang.GenericVnf;
53 import org.onap.aai.domain.yang.ModelVer;
54 import org.onap.aai.domain.yang.ServiceInstance;
55 import org.onap.aai.domain.yang.Tenant;
56 import org.onap.policy.aai.AaiCqResponse;
57 import org.onap.policy.common.utils.coder.StandardCoderObject;
58 import org.onap.policy.controlloop.VirtualControlLoopEvent;
59 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
60 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
61 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
62 import org.onap.policy.controlloop.actorserviceprovider.Operation;
63 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
64 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
65 import org.onap.policy.controlloop.actorserviceprovider.Operator;
66 import org.onap.policy.controlloop.actorserviceprovider.TargetType;
67 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
68 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
69 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
70 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2;
71 import org.onap.policy.controlloop.eventmanager.StepContext;
72 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
74 public class Step2Test {
75 private static final UUID REQ_ID = UUID.randomUUID();
76 private static final String POLICY_ACTOR = "my-actor";
77 private static final String POLICY_OPERATION = "my-operation";
78 private static final String MY_TARGET = "my-target";
79 private static final String PAYLOAD_KEY = "payload-key";
80 private static final String PAYLOAD_VALUE = "payload-value";
81 private static final String NO_SLASH = "noslash";
82 private static final String ONE_SLASH = "/one";
85 private Operator policyOperator;
87 private Operation policyOperation;
89 private Actor policyActor;
91 private ActorService actors;
93 private StepContext stepContext;
95 private AaiCqResponse aaicq;
97 private CompletableFuture<OperationOutcome> future;
98 private Map<String, String> payload;
99 private VirtualControlLoopEvent event;
100 private ControlLoopEventContext context;
101 private BlockingQueue<OperationOutcome> starts;
102 private BlockingQueue<OperationOutcome> completions;
103 private ControlLoopOperationParams params;
110 public void setUp() {
111 MockitoAnnotations.initMocks(this);
113 future = new CompletableFuture<>();
115 // configure policy operation
116 when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
117 when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
118 when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
119 when(policyOperation.start()).thenReturn(future);
121 when(policyOperation.getPropertyNames()).thenReturn(List.of());
123 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
125 payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
127 event = new VirtualControlLoopEvent();
128 event.setRequestId(REQ_ID);
129 event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
130 event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
132 context = new ControlLoopEventContext(event);
134 starts = new LinkedBlockingQueue<>();
135 completions = new LinkedBlockingQueue<>();
137 Map<String, String> entityIds = new HashMap<>();
139 params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors)
140 .completeCallback(completions::add).context(context).executor(ForkJoinPool.commonPool())
141 .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add)
142 .targetType(TargetType.VM).targetEntityIds(entityIds).targetEntity(MY_TARGET)
145 step = new Step2(stepContext, params, event);
150 public void testConstructor() {
151 assertSame(stepContext, step.stepContext);
152 assertSame(event, step.event);
153 assertSame(actors, step.getParams().getActorService());
157 public void testConstructorStep2() {
158 step = new Step2(step, "actorB", "operationB");
159 assertSame(stepContext, step.stepContext);
160 assertSame(event, step.event);
162 assertEquals("actorB", step.getActorName());
163 assertEquals("operationB", step.getOperationName());
164 assertSame(actors, step.getParams().getActorService());
168 public void testAcceptsEvent() {
169 // it's a policy step, thus it accepts events
170 assertTrue(step.acceptsEvent());
172 step = new Step2(step, "actorB", "operationB");
174 // it's not a policy step, thus it does not accept events
175 assertFalse(step.acceptsEvent());
179 public void testSuccess() {
180 assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
184 public void testGetPropertyNames() {
185 // empty property list
186 assertThat(step.getPropertyNames()).isEmpty();
188 // try with non-empty list
189 when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
190 assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
194 public void testSetProperties() {
195 CloudRegion cloudRegion = new CloudRegion();
196 when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
198 Tenant tenant = new Tenant();
199 when(aaicq.getDefaultTenant()).thenReturn(tenant);
201 when(policyOperation.getPropertyNames()).thenReturn(
202 List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
204 step.setProperties();
206 // should have been exactly two properties set
207 verify(policyOperation, times(2)).setProperty(any(), any());
208 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion);
209 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant);
213 * Tests setProperties() when the property is unknown.
216 public void testSetPropertiesUnknown() {
217 when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
219 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
220 .withMessage("unknown property unknown-property needed by my-actor.my-operation");
224 public void testLoadCloudRegion_testGetCloudRegion() {
225 CloudRegion data = new CloudRegion();
226 when(aaicq.getDefaultCloudRegion()).thenReturn(data);
227 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION));
229 step.setProperties();
230 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
234 public void testLoadTenant_testGetTenant() {
235 Tenant data = new Tenant();
236 when(aaicq.getDefaultTenant()).thenReturn(data);
237 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT));
239 step.setProperties();
240 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
244 public void testLoadPnf_testGetPnf() {
245 StandardCoderObject data = new StandardCoderObject();
246 when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
247 when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data);
248 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF));
250 step.setProperties();
251 verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
255 public void testLoadResourceVnf_testGetResourceVnf() {
256 params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, "my-resource");
257 GenericVnf data = new GenericVnf();
258 when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data);
259 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF));
261 step.setProperties();
262 verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
264 // missing resource ID
265 params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
266 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
267 .withMessageContaining("missing Target resource ID");
269 // missing target entity IDs
270 params = params.toBuilder().targetEntityIds(null).build();
271 step = new Step2(stepContext, params, event);
273 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
274 .withMessageContaining(Step2.TARGET_INFO_MSG);
278 public void testLoadService_testGetService() {
279 ServiceInstance data = new ServiceInstance();
280 when(aaicq.getServiceInstance()).thenReturn(data);
281 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE));
283 step.setProperties();
284 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
288 public void testLoadServiceModel_testGetServiceModel() {
289 ServiceInstance service = new ServiceInstance();
290 service.setModelVersionId("my-service-version");
291 when(aaicq.getServiceInstance()).thenReturn(service);
293 ModelVer data = new ModelVer();
294 when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data);
295 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL));
297 step.setProperties();
298 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
302 public void testLoadVnf_testGetVnf() {
303 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
304 GenericVnf data = new GenericVnf();
305 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data);
306 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF));
308 step.setProperties();
309 verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
311 // missing model invariant ID
312 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
313 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
314 .withMessageContaining("missing modelInvariantId");
317 params = params.toBuilder().targetEntityIds(null).build();
318 step = new Step2(stepContext, params, event);
320 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
321 .withMessageContaining(Step2.TARGET_INFO_MSG);
325 public void testLoadVnfModel_testGetVnfModel() {
326 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
327 GenericVnf vnf = new GenericVnf();
328 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf);
330 vnf.setModelVersionId("my-vnf-model-version-id");
331 ModelVer data = new ModelVer();
332 when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data);
333 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL));
335 step.setProperties();
336 verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
340 public void testLoadVserverLink_testGetVserverLink() {
341 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
343 StandardCoderObject tenant = mock(StandardCoderObject.class);
344 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
346 when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
348 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
350 step.setProperties();
351 verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
353 // missing resource link
354 when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null);
355 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
356 .withMessageContaining("missing tenant data resource-link");
358 // missing tenant data
359 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
360 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
361 .withMessageContaining("missing tenant data for");
363 // empty vserver name
364 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
365 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
366 .withMessageContaining("missing vserver.vserver-name");
368 // missing vserver name
369 event.setAai(Map.of());
370 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
371 .withMessageContaining("missing vserver.vserver-name");
375 public void testLoadVfCount_testGetVfCount() {
376 params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, "vf-count-customization");
377 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "vf-count-invariant");
378 params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, "vf-count-version");
379 when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11);
380 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT));
382 step.setProperties();
383 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
385 // missing model version id
386 params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, null);
387 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
388 .withMessageContaining("missing target modelVersionId");
390 // missing model invariant id
391 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
392 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
393 .withMessageContaining("missing target modelInvariantId");
395 // missing model customization id
396 params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, null);
397 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
398 .withMessageContaining("missing target modelCustomizationId");
401 params = params.toBuilder().targetEntityIds(null).build();
402 step = new Step2(stepContext, params, event);
404 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
405 .withMessageContaining(Step2.TARGET_INFO_MSG);
407 // get it from the step context
408 when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true);
409 when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22);
410 step.setProperties();
411 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22);
415 public void testLoadEnrichment_testGetEnrichment() {
416 event.setAai(Map.of("bandwidth", "bandwidth-value"));
417 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
419 step.setProperties();
420 verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
422 // missing enrichment data
423 event.setAai(Map.of());
424 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
428 public void testLoadAdditionalEventParams_testGetAdditionalEventParams() {
429 Map<String, String> data = Map.of("addA", "add-valueA", "addB", "add-valueB");
430 event.setAdditionalEventParams(data);
431 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS));
433 step.setProperties();
434 verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
438 public void testLoadEventPayload_testGetEventPayload() {
439 event.setPayload("some-event-payload");
440 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
442 step.setProperties();
443 verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
447 public void testLoadOptCdsGrpcAaiProperties() {
448 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
450 step.setProperties();
451 verify(policyOperation, never()).setProperty(any(), anyString());
455 public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() {
456 GenericVnf data = new GenericVnf();
457 when(aaicq.getDefaultGenericVnf()).thenReturn(data);
458 when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF));
460 step.setProperties();
461 verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
465 public void testGetCustomQueryData() {
466 assertSame(aaicq, step.getCustomQueryData());
468 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
470 assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
471 .withMessage("missing custom query data for my-actor.my-operation");
475 public void testVerifyNotNull() {
476 assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
478 assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
479 .withMessage("missing verifyB for my-actor.my-operation");
483 public void testStripPrefix() {
484 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0));
485 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1));
486 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2));
488 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
489 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
491 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
492 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
494 assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
496 assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));