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.List;
40 import java.util.TreeMap;
41 import java.util.UUID;
42 import java.util.concurrent.BlockingQueue;
43 import java.util.concurrent.CompletableFuture;
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.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.onap.aai.domain.yang.CloudRegion;
51 import org.onap.aai.domain.yang.GenericVnf;
52 import org.onap.aai.domain.yang.ModelVer;
53 import org.onap.aai.domain.yang.ServiceInstance;
54 import org.onap.aai.domain.yang.Tenant;
55 import org.onap.policy.aai.AaiCqResponse;
56 import org.onap.policy.common.utils.coder.StandardCoderObject;
57 import org.onap.policy.controlloop.VirtualControlLoopEvent;
58 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
59 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
60 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
61 import org.onap.policy.controlloop.actorserviceprovider.Operation;
62 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
63 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
64 import org.onap.policy.controlloop.actorserviceprovider.Operator;
65 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
66 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
67 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
68 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2;
69 import org.onap.policy.controlloop.eventmanager.StepContext;
70 import org.onap.policy.controlloop.policy.Policy;
71 import org.onap.policy.controlloop.policy.Target;
72 import org.onap.policy.controlloop.policy.TargetType;
73 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
75 public class Step2Test {
76 private static final UUID REQ_ID = UUID.randomUUID();
77 private static final String POLICY_ID = "my-policy";
78 private static final String POLICY_ACTOR = "my-actor";
79 private static final String POLICY_OPERATION = "my-operation";
80 private static final String MY_TARGET = "my-target";
81 private static final String PAYLOAD_KEY = "payload-key";
82 private static final String PAYLOAD_VALUE = "payload-value";
83 private static final Integer POLICY_RETRY = 3;
84 private static final Integer POLICY_TIMEOUT = 20;
85 private static final String NO_SLASH = "noslash";
86 private static final String ONE_SLASH = "/one";
89 private Operator policyOperator;
91 private Operation policyOperation;
93 private Actor policyActor;
95 private ActorService actors;
97 private StepContext stepContext;
99 private AaiCqResponse aaicq;
101 private CompletableFuture<OperationOutcome> future;
102 private Target target;
103 private Map<String, String> payload;
104 private Policy policy;
105 private VirtualControlLoopEvent event;
106 private ControlLoopEventContext context;
107 private BlockingQueue<OperationOutcome> starts;
108 private BlockingQueue<OperationOutcome> completions;
109 private ControlLoopOperationParams params;
116 public void setUp() {
117 MockitoAnnotations.initMocks(this);
119 future = new CompletableFuture<>();
121 // configure policy operation
122 when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
123 when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
124 when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
125 when(policyOperation.start()).thenReturn(future);
127 when(policyOperation.getPropertyNames()).thenReturn(List.of());
129 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
131 target = new Target();
132 target.setType(TargetType.VM);
134 payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
136 policy = new Policy();
137 policy.setId(POLICY_ID);
138 policy.setActor(POLICY_ACTOR);
139 policy.setRecipe(POLICY_OPERATION);
140 policy.setTarget(target);
141 policy.setPayload(payload);
142 policy.setRetry(POLICY_RETRY);
143 policy.setTimeout(POLICY_TIMEOUT);
145 event = new VirtualControlLoopEvent();
146 event.setRequestId(REQ_ID);
147 event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
148 event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
150 context = new ControlLoopEventContext(event);
152 starts = new LinkedBlockingQueue<>();
153 completions = new LinkedBlockingQueue<>();
155 params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors)
156 .completeCallback(completions::add).context(context).executor(ForkJoinPool.commonPool())
157 .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add)
158 .target(target).targetEntity(MY_TARGET).build();
160 step = new Step2(stepContext, params, event);
165 public void testConstructor() {
166 assertSame(stepContext, step.stepContext);
167 assertSame(event, step.event);
168 assertSame(actors, step.getParams().getActorService());
172 public void testConstructorStep2() {
173 step = new Step2(step, "actorB", "operationB");
174 assertSame(stepContext, step.stepContext);
175 assertSame(event, step.event);
177 assertEquals("actorB", step.getActorName());
178 assertEquals("operationB", step.getOperationName());
179 assertSame(actors, step.getParams().getActorService());
183 public void testAcceptsEvent() {
184 // it's a policy step, thus it accepts events
185 assertTrue(step.acceptsEvent());
187 step = new Step2(step, "actorB", "operationB");
189 // it's not a policy step, thus it does not accept events
190 assertFalse(step.acceptsEvent());
194 public void testSuccess() {
195 assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
199 public void testGetPropertyNames() {
200 // empty property list
201 assertThat(step.getPropertyNames()).isEmpty();
203 // try with non-empty list
204 when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
205 assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
209 public void testSetProperties() {
210 CloudRegion cloudRegion = new CloudRegion();
211 when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
213 Tenant tenant = new Tenant();
214 when(aaicq.getDefaultTenant()).thenReturn(tenant);
216 when(policyOperation.getPropertyNames()).thenReturn(
217 List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
219 step.setProperties();
221 // should have been exactly two properties set
222 verify(policyOperation, times(2)).setProperty(any(), any());
223 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion);
224 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant);
228 * Tests setProperties() when the property is unknown.
231 public void testSetPropertiesUnknown() {
232 when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
234 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
235 .withMessage("unknown property unknown-property needed by my-actor.my-operation");
239 public void testLoadCloudRegion_testGetCloudRegion() {
240 CloudRegion data = new CloudRegion();
241 when(aaicq.getDefaultCloudRegion()).thenReturn(data);
242 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION));
244 step.setProperties();
245 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
249 public void testLoadTenant_testGetTenant() {
250 Tenant data = new Tenant();
251 when(aaicq.getDefaultTenant()).thenReturn(data);
252 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT));
254 step.setProperties();
255 verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
259 public void testLoadPnf_testGetPnf() {
260 StandardCoderObject data = new StandardCoderObject();
261 when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
262 when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data);
263 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF));
265 step.setProperties();
266 verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
270 public void testLoadResourceVnf_testGetResourceVnf() {
271 target.setResourceID("my-resource");
272 GenericVnf data = new GenericVnf();
273 when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data);
274 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF));
276 step.setProperties();
277 verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
279 // missing resource ID
280 target.setResourceID(null);
281 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
282 .withMessageContaining("missing Target resource ID");
285 params = params.toBuilder().target(null).build();
286 step = new Step2(stepContext, params, event);
288 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
289 .withMessageContaining(Step2.TARGET_INFO_MSG);
293 public void testLoadService_testGetService() {
294 ServiceInstance data = new ServiceInstance();
295 when(aaicq.getServiceInstance()).thenReturn(data);
296 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE));
298 step.setProperties();
299 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
303 public void testLoadServiceModel_testGetServiceModel() {
304 ServiceInstance service = new ServiceInstance();
305 service.setModelVersionId("my-service-version");
306 when(aaicq.getServiceInstance()).thenReturn(service);
308 ModelVer data = new ModelVer();
309 when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data);
310 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL));
312 step.setProperties();
313 verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
317 public void testLoadVnf_testGetVnf() {
318 target.setModelInvariantId("my-model-invariant");
319 GenericVnf data = new GenericVnf();
320 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data);
321 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF));
323 step.setProperties();
324 verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
326 // missing model invariant ID
327 target.setModelInvariantId(null);
328 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
329 .withMessageContaining("missing modelInvariantId");
332 params = params.toBuilder().target(null).build();
333 step = new Step2(stepContext, params, event);
335 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
336 .withMessageContaining(Step2.TARGET_INFO_MSG);
340 public void testLoadVnfModel_testGetVnfModel() {
341 target.setModelInvariantId("my-model-invariant");
342 GenericVnf vnf = new GenericVnf();
343 when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf);
345 vnf.setModelVersionId("my-vnf-model-version-id");
346 ModelVer data = new ModelVer();
347 when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data);
348 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL));
350 step.setProperties();
351 verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
355 public void testLoadVserverLink_testGetVserverLink() {
356 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
358 StandardCoderObject tenant = mock(StandardCoderObject.class);
359 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
361 when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
363 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
365 step.setProperties();
366 verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
368 // missing resource link
369 when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null);
370 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
371 .withMessageContaining("missing tenant data resource-link");
373 // missing tenant data
374 when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
375 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
376 .withMessageContaining("missing tenant data for");
378 // empty vserver name
379 event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
380 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
381 .withMessageContaining("missing vserver.vserver-name");
383 // missing vserver name
384 event.setAai(Map.of());
385 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
386 .withMessageContaining("missing vserver.vserver-name");
390 public void testLoadVfCount_testGetVfCount() {
391 target.setModelCustomizationId("vf-count-customization");
392 target.setModelInvariantId("vf-count-invariant");
393 target.setModelVersionId("vf-count-version");
394 when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11);
395 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT));
397 step.setProperties();
398 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
400 // missing model version id
401 target.setModelVersionId(null);
402 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
403 .withMessageContaining("missing target modelVersionId");
405 // missing model invariant id
406 target.setModelInvariantId(null);
407 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
408 .withMessageContaining("missing target modelInvariantId");
410 // missing model customization id
411 target.setModelCustomizationId(null);
412 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
413 .withMessageContaining("missing target modelCustomizationId");
416 params = params.toBuilder().target(null).build();
417 step = new Step2(stepContext, params, event);
419 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
420 .withMessageContaining(Step2.TARGET_INFO_MSG);
422 // get it from the step context
423 when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true);
424 when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22);
425 step.setProperties();
426 verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22);
430 public void testLoadEnrichment_testGetEnrichment() {
431 event.setAai(Map.of("bandwidth", "bandwidth-value"));
432 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
434 step.setProperties();
435 verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
437 // missing enrichment data
438 event.setAai(Map.of());
439 assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
443 public void testLoadAdditionalEventParams_testGetAdditionalEventParams() {
444 Map<String, String> data = Map.of("addA", "add-valueA", "addB", "add-valueB");
445 event.setAdditionalEventParams(data);
446 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS));
448 step.setProperties();
449 verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
453 public void testLoadEventPayload_testGetEventPayload() {
454 event.setPayload("some-event-payload");
455 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
457 step.setProperties();
458 verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
462 public void testLoadOptCdsGrpcAaiProperties() {
463 when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
465 step.setProperties();
466 verify(policyOperation, never()).setProperty(any(), anyString());
470 public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() {
471 GenericVnf data = new GenericVnf();
472 when(aaicq.getDefaultGenericVnf()).thenReturn(data);
473 when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF));
475 step.setProperties();
476 verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
480 public void testGetCustomQueryData() {
481 assertSame(aaicq, step.getCustomQueryData());
483 when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
485 assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
486 .withMessage("missing custom query data for my-actor.my-operation");
490 public void testVerifyNotNull() {
491 assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
493 assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
494 .withMessage("missing verifyB for my-actor.my-operation");
498 public void testStripPrefix() {
499 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0));
500 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1));
501 assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2));
503 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
504 assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
506 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
507 assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
509 assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
511 assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));