2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 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.ForkJoinPool;
45 import java.util.concurrent.LinkedBlockingQueue;
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.mockito.Mock;
50 import org.mockito.junit.MockitoJUnitRunner;
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.aai.domain.yang.Vserver;
57 import org.onap.policy.aai.AaiCqResponse;
58 import org.onap.policy.common.utils.coder.StandardCoderObject;
59 import org.onap.policy.controlloop.VirtualControlLoopEvent;
60 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
61 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
62 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
63 import org.onap.policy.controlloop.actorserviceprovider.Operation;
64 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
65 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
66 import org.onap.policy.controlloop.actorserviceprovider.Operator;
67 import org.onap.policy.controlloop.actorserviceprovider.TargetType;
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.StepContext;
71 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
73 @RunWith(MockitoJUnitRunner.class)
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 Map<String, String> payload;
98 private VirtualControlLoopEvent event;
99 private BlockingQueue<OperationOutcome> starts;
100 private BlockingQueue<OperationOutcome> completions;
101 private ControlLoopOperationParams params;
108 public void setUp() {
109 // configure policy operation
110 when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
111 when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
112 when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
114 when(policyOperation.getPropertyNames()).thenReturn(List.of());
116 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
118 payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
120 event = new VirtualControlLoopEvent();
121 event.setRequestId(REQ_ID);
123 starts = new LinkedBlockingQueue<>();
124 completions = new LinkedBlockingQueue<>();
126 Map<String, String> entityIds = new HashMap<>();
128 params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors)
129 .completeCallback(completions::add).executor(ForkJoinPool.commonPool())
130 .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add)
131 .targetType(TargetType.VM).targetEntityIds(entityIds)
132 .requestId(REQ_ID).build();
134 step = new Step2(stepContext, params, event);
139 public void testConstructor() {
140 assertSame(stepContext, step.stepContext);
141 assertSame(event, step.event);
142 assertSame(actors, step.getParams().getActorService());
146 public void testConstructorStep2() {
147 step = new Step2(step, "actorB", "operationB");
148 assertSame(stepContext, step.stepContext);
149 assertSame(event, step.event);
151 assertEquals("actorB", step.getActorName());
152 assertEquals("operationB", step.getOperationName());
153 assertSame(actors, step.getParams().getActorService());
157 public void testAcceptsEvent() {
158 // it's a policy step, thus it accepts events
159 assertTrue(step.acceptsEvent());
161 step = new Step2(step, "actorB", "operationB");
163 // it's not a policy step, thus it does not accept events
164 assertFalse(step.acceptsEvent());
168 public void testSuccess() {
169 assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
173 public void testGetPropertyNames() {
174 // empty property list
175 assertThat(step.getPropertyNames()).isEmpty();
177 // try with non-empty list
178 when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
179 assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
183 public void testSetProperties() {
184 CloudRegion cloudRegion = new CloudRegion();
185 when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
187 Tenant tenant = new Tenant();
188 when(aaicq.getDefaultTenant()).thenReturn(tenant);
190 when(policyOperation.getPropertyNames()).thenReturn(
191 List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
193 step.setProperties();
195 // should have been exactly two properties set
196 verify(policyOperation, times(2)).setProperty(any(), any());
197 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion);
198 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant);
202 * Tests setProperties() when the property is unknown.
205 public void testSetPropertiesUnknown() {
206 when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
208 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
209 .withMessage("unknown property unknown-property needed by my-actor.my-operation");
213 public void testLoadCloudRegion_testGetCloudRegion() {
214 CloudRegion data = new CloudRegion();
215 when(aaicq.getDefaultCloudRegion()).thenReturn(data);
216 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION));
218 step.setProperties();
219 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
221 when(aaicq.getDefaultCloudRegion()).thenReturn(null);
222 assertThatIllegalArgumentException().isThrownBy(() -> step.getCloudRegion())
223 .withMessageContaining("missing default cloud region in A&AI response");
227 public void testLoadTenant_testGetTenant() {
228 Tenant data = new Tenant();
229 when(aaicq.getDefaultTenant()).thenReturn(data);
230 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT));
232 step.setProperties();
233 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
235 when(aaicq.getDefaultTenant()).thenReturn(null);
236 assertThatIllegalArgumentException().isThrownBy(() -> step.getTenant())
237 .withMessageContaining("missing default tenant in A&AI response");
241 public void testLoadPnf_testGetPnf() {
242 StandardCoderObject data = new StandardCoderObject();
243 when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
244 when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data);
245 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF));
247 step.setProperties();
248 verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
250 when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(null);
251 assertThatIllegalArgumentException().isThrownBy(() -> step.getPnf())
252 .withMessageContaining("missing PNF for my-target");
256 public void testLoadResourceVnf_testGetResourceVnf() {
257 params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, "my-resource");
258 GenericVnf data = new GenericVnf();
259 when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data);
260 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF));
262 step.setProperties();
263 verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
265 when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(null);
266 assertThatIllegalArgumentException().isThrownBy(() -> step.getResourceVnf())
267 .withMessageContaining("missing VNF for my-resource");
269 // missing resource ID
270 params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
271 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
272 .withMessageContaining("missing Target resource ID");
274 // missing target entity IDs
275 params = params.toBuilder().targetEntityIds(null).build();
276 step = new Step2(stepContext, params, event);
278 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
279 .withMessageContaining(Step2.TARGET_INFO_MSG);
283 public void testLoadService_testGetService() {
284 ServiceInstance data = new ServiceInstance();
285 when(aaicq.getServiceInstance()).thenReturn(data);
286 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE));
288 step.setProperties();
289 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
291 when(aaicq.getServiceInstance()).thenReturn(null);
292 assertThatIllegalArgumentException().isThrownBy(() -> step.getService())
293 .withMessageContaining("missing service instance in A&AI response");
297 public void testLoadServiceModel_testGetServiceModel() {
298 ServiceInstance service = new ServiceInstance();
299 service.setModelVersionId("my-service-version");
300 when(aaicq.getServiceInstance()).thenReturn(service);
302 ModelVer data = new ModelVer();
303 when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data);
304 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL));
306 step.setProperties();
307 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
309 when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(null);
310 assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
311 .withMessageContaining("missing model version for service in A&AI response");
313 service.setModelVersionId(null);
314 assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
315 .withMessageContaining("missing service model version ID in A&AI response");
317 when(aaicq.getServiceInstance()).thenReturn(null);
318 assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
319 .withMessageContaining("missing service instance in A&AI response");
323 public void testGetVserver() {
324 Vserver vserver = new Vserver();
325 when(aaicq.getVserver()).thenReturn(vserver);
327 assertSame(vserver, step.getVServer());
329 when(aaicq.getVserver()).thenReturn(null);
330 assertThatIllegalArgumentException().isThrownBy(() -> step.getVServer())
331 .withMessageContaining("missing vserver in A&AI response");
335 public void testGetTargetEntity() {
336 when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
338 assertEquals(MY_TARGET, step.getTargetEntity());
340 when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(null);
341 assertThatIllegalArgumentException().isThrownBy(() -> step.getTargetEntity())
342 .withMessageContaining("missing A&AI target entity");
346 public void testLoadVnf_testGetVnf() {
347 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
348 GenericVnf data = new GenericVnf();
349 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data);
350 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF));
352 step.setProperties();
353 verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
355 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(null);
356 assertThatIllegalArgumentException().isThrownBy(() -> step.getVnf())
357 .withMessageContaining("missing generic VNF in A&AI response for my-model-invariant");
359 // missing model invariant ID
360 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
361 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
362 .withMessageContaining("missing modelInvariantId");
365 params = params.toBuilder().targetEntityIds(null).build();
366 step = new Step2(stepContext, params, event);
368 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
369 .withMessageContaining(Step2.TARGET_INFO_MSG);
373 public void testLoadVnfModel_testGetVnfModel() {
374 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
375 GenericVnf vnf = new GenericVnf();
376 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf);
378 vnf.setModelVersionId("my-vnf-model-version-id");
379 ModelVer data = new ModelVer();
380 when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data);
381 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL));
383 step.setProperties();
384 verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
386 when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(null);
387 assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
388 .withMessageContaining("missing model version for generic VNF in A&AI response");
390 vnf.setModelVersionId(null);
391 assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
392 .withMessageContaining("missing model version ID for generic VNF in A&AI response");
396 public void testLoadVserverLink_testGetVserverLink() {
397 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
399 StandardCoderObject tenant = mock(StandardCoderObject.class);
400 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
402 when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
404 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
406 step.setProperties();
407 verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
409 // missing resource link
410 when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null);
411 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
412 .withMessageContaining("missing tenant data resource-link");
414 // missing tenant data
415 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
416 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
417 .withMessageContaining("missing tenant data for");
419 // empty vserver name
420 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
421 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
422 .withMessageContaining("missing vserver.vserver-name");
424 // missing vserver name
425 event.setAai(Map.of());
426 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
427 .withMessageContaining("missing vserver.vserver-name");
431 public void testLoadVfCount_testGetVfCount() {
432 params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, "vf-count-customization");
433 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "vf-count-invariant");
434 params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, "vf-count-version");
435 when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11);
436 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT));
438 step.setProperties();
439 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
441 // missing model version id
442 params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, null);
443 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
444 .withMessageContaining("missing target modelVersionId");
446 // missing model invariant id
447 params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
448 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
449 .withMessageContaining("missing target modelInvariantId");
451 // missing model customization id
452 params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, null);
453 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
454 .withMessageContaining("missing target modelCustomizationId");
457 params = params.toBuilder().targetEntityIds(null).build();
458 step = new Step2(stepContext, params, event);
460 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
461 .withMessageContaining(Step2.TARGET_INFO_MSG);
463 // get it from the step context
464 when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true);
465 when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22);
466 step.setProperties();
467 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22);
471 public void testLoadEnrichment_testGetEnrichment() {
472 event.setAai(Map.of("bandwidth", "bandwidth-value"));
473 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
475 step.setProperties();
476 verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
478 // missing enrichment data
479 event.setAai(Map.of());
480 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
484 public void testLoadAdditionalEventParams_testGetAdditionalEventParams() {
485 Map<String, String> data = Map.of("addA", "add-valueA", "addB", "add-valueB");
486 event.setAdditionalEventParams(data);
487 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS));
489 step.setProperties();
490 verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
494 public void testLoadEventPayload_testGetEventPayload() {
495 event.setPayload("some-event-payload");
496 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
498 step.setProperties();
499 verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
503 public void testLoadOptCdsGrpcAaiProperties() {
504 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
506 step.setProperties();
507 verify(policyOperation, never()).setProperty(any(), anyString());
511 public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() {
512 GenericVnf data = new GenericVnf();
513 when(aaicq.getDefaultGenericVnf()).thenReturn(data);
514 when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF));
516 step.setProperties();
517 verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
519 when(aaicq.getDefaultGenericVnf()).thenReturn(null);
520 assertThatIllegalArgumentException().isThrownBy(() -> step.getDefaultGenericVnf())
521 .withMessageContaining("missing generic VNF in A&AI response");
525 public void testGetCustomQueryData() {
526 assertSame(aaicq, step.getCustomQueryData());
528 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
530 assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
531 .withMessage("missing custom query data for my-actor.my-operation");
535 public void testVerifyNotNull() {
536 assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
538 assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
539 .withMessage("missing verifyB for my-actor.my-operation");
543 public void testStripPrefix() {
544 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0));
545 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1));
546 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2));
548 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
549 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
551 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
552 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
554 assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
556 assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));