1fe36539e25707b1404af02e3f06f73e04ff8f20
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.drools.apps.controller.usecases.step;
22
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;
37
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
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.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;
72
73 public class Step2Test {
74     private static final UUID REQ_ID = UUID.randomUUID();
75     private static final String POLICY_ACTOR = "my-actor";
76     private static final String POLICY_OPERATION = "my-operation";
77     private static final String MY_TARGET = "my-target";
78     private static final String PAYLOAD_KEY = "payload-key";
79     private static final String PAYLOAD_VALUE = "payload-value";
80     private static final String NO_SLASH = "noslash";
81     private static final String ONE_SLASH = "/one";
82
83     @Mock
84     private Operator policyOperator;
85     @Mock
86     private Operation policyOperation;
87     @Mock
88     private Actor policyActor;
89     @Mock
90     private ActorService actors;
91     @Mock
92     private StepContext stepContext;
93     @Mock
94     private AaiCqResponse aaicq;
95
96     private CompletableFuture<OperationOutcome> future;
97     private Map<String, String> payload;
98     private VirtualControlLoopEvent event;
99     private BlockingQueue<OperationOutcome> starts;
100     private BlockingQueue<OperationOutcome> completions;
101     private ControlLoopOperationParams params;
102     private Step2 step;
103
104     /**
105      * Sets up.
106      */
107     @Before
108     public void setUp() {
109         MockitoAnnotations.initMocks(this);
110
111         future = new CompletableFuture<>();
112
113         // configure policy operation
114         when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
115         when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
116         when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
117         when(policyOperation.start()).thenReturn(future);
118
119         when(policyOperation.getPropertyNames()).thenReturn(List.of());
120
121         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
122
123         payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
124
125         event = new VirtualControlLoopEvent();
126         event.setRequestId(REQ_ID);
127
128         starts = new LinkedBlockingQueue<>();
129         completions = new LinkedBlockingQueue<>();
130
131         Map<String, String> entityIds = new HashMap<>();
132
133         params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors)
134                         .completeCallback(completions::add).executor(ForkJoinPool.commonPool())
135                         .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add)
136                         .targetType(TargetType.VM).targetEntityIds(entityIds)
137                         .requestId(REQ_ID).build();
138
139         step = new Step2(stepContext, params, event);
140         step.init();
141     }
142
143     @Test
144     public void testConstructor() {
145         assertSame(stepContext, step.stepContext);
146         assertSame(event, step.event);
147         assertSame(actors, step.getParams().getActorService());
148     }
149
150     @Test
151     public void testConstructorStep2() {
152         step = new Step2(step, "actorB", "operationB");
153         assertSame(stepContext, step.stepContext);
154         assertSame(event, step.event);
155
156         assertEquals("actorB", step.getActorName());
157         assertEquals("operationB", step.getOperationName());
158         assertSame(actors, step.getParams().getActorService());
159     }
160
161     @Test
162     public void testAcceptsEvent() {
163         // it's a policy step, thus it accepts events
164         assertTrue(step.acceptsEvent());
165
166         step = new Step2(step, "actorB", "operationB");
167
168         // it's not a policy step, thus it does not accept events
169         assertFalse(step.acceptsEvent());
170     }
171
172     @Test
173     public void testSuccess() {
174         assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
175     }
176
177     @Test
178     public void testGetPropertyNames() {
179         // empty property list
180         assertThat(step.getPropertyNames()).isEmpty();
181
182         // try with non-empty list
183         when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
184         assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
185     }
186
187     @Test
188     public void testSetProperties() {
189         CloudRegion cloudRegion = new CloudRegion();
190         when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
191
192         Tenant tenant = new Tenant();
193         when(aaicq.getDefaultTenant()).thenReturn(tenant);
194
195         when(policyOperation.getPropertyNames()).thenReturn(
196                         List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
197
198         step.setProperties();
199
200         // should have been exactly two properties set
201         verify(policyOperation, times(2)).setProperty(any(), any());
202         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion);
203         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant);
204     }
205
206     /**
207      * Tests setProperties() when the property is unknown.
208      */
209     @Test
210     public void testSetPropertiesUnknown() {
211         when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
212
213         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
214                         .withMessage("unknown property unknown-property needed by my-actor.my-operation");
215     }
216
217     @Test
218     public void testLoadCloudRegion_testGetCloudRegion() {
219         CloudRegion data = new CloudRegion();
220         when(aaicq.getDefaultCloudRegion()).thenReturn(data);
221         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION));
222
223         step.setProperties();
224         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
225
226         when(aaicq.getDefaultCloudRegion()).thenReturn(null);
227         assertThatIllegalArgumentException().isThrownBy(() -> step.getCloudRegion())
228                         .withMessageContaining("missing default cloud region in A&AI response");
229     }
230
231     @Test
232     public void testLoadTenant_testGetTenant() {
233         Tenant data = new Tenant();
234         when(aaicq.getDefaultTenant()).thenReturn(data);
235         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT));
236
237         step.setProperties();
238         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
239
240         when(aaicq.getDefaultTenant()).thenReturn(null);
241         assertThatIllegalArgumentException().isThrownBy(() -> step.getTenant())
242                         .withMessageContaining("missing default tenant in A&AI response");
243     }
244
245     @Test
246     public void testLoadPnf_testGetPnf() {
247         StandardCoderObject data = new StandardCoderObject();
248         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
249         when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data);
250         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF));
251
252         step.setProperties();
253         verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
254
255         when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(null);
256         assertThatIllegalArgumentException().isThrownBy(() -> step.getPnf())
257                         .withMessageContaining("missing PNF for my-target");
258     }
259
260     @Test
261     public void testLoadResourceVnf_testGetResourceVnf() {
262         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, "my-resource");
263         GenericVnf data = new GenericVnf();
264         when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data);
265         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF));
266
267         step.setProperties();
268         verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
269
270         when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(null);
271         assertThatIllegalArgumentException().isThrownBy(() -> step.getResourceVnf())
272                         .withMessageContaining("missing VNF for my-resource");
273
274         // missing resource ID
275         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
276         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
277                         .withMessageContaining("missing Target resource ID");
278
279         // missing target entity IDs
280         params = params.toBuilder().targetEntityIds(null).build();
281         step = new Step2(stepContext, params, event);
282         step.init();
283         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
284                         .withMessageContaining(Step2.TARGET_INFO_MSG);
285     }
286
287     @Test
288     public void testLoadService_testGetService() {
289         ServiceInstance data = new ServiceInstance();
290         when(aaicq.getServiceInstance()).thenReturn(data);
291         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE));
292
293         step.setProperties();
294         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
295
296         when(aaicq.getServiceInstance()).thenReturn(null);
297         assertThatIllegalArgumentException().isThrownBy(() -> step.getService())
298                         .withMessageContaining("missing service instance in A&AI response");
299     }
300
301     @Test
302     public void testLoadServiceModel_testGetServiceModel() {
303         ServiceInstance service = new ServiceInstance();
304         service.setModelVersionId("my-service-version");
305         when(aaicq.getServiceInstance()).thenReturn(service);
306
307         ModelVer data = new ModelVer();
308         when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data);
309         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL));
310
311         step.setProperties();
312         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
313
314         when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(null);
315         assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
316                         .withMessageContaining("missing model version for service in A&AI response");
317
318         service.setModelVersionId(null);
319         assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
320                         .withMessageContaining("missing service model version ID in A&AI response");
321
322         when(aaicq.getServiceInstance()).thenReturn(null);
323         assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
324                         .withMessageContaining("missing service instance in A&AI response");
325     }
326
327     @Test
328     public void testGetVserver() {
329         Vserver vserver = new Vserver();
330         when(aaicq.getVserver()).thenReturn(vserver);
331
332         assertSame(vserver, step.getVServer());
333
334         when(aaicq.getVserver()).thenReturn(null);
335         assertThatIllegalArgumentException().isThrownBy(() -> step.getVServer())
336                         .withMessageContaining("missing vserver in A&AI response");
337     }
338
339     @Test
340     public void testGetTargetEntity() {
341         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
342
343         assertEquals(MY_TARGET, step.getTargetEntity());
344
345         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(null);
346         assertThatIllegalArgumentException().isThrownBy(() -> step.getTargetEntity())
347                         .withMessageContaining("missing A&AI target entity");
348     }
349
350     @Test
351     public void testLoadVnf_testGetVnf() {
352         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
353         GenericVnf data = new GenericVnf();
354         when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data);
355         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF));
356
357         step.setProperties();
358         verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
359
360         when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(null);
361         assertThatIllegalArgumentException().isThrownBy(() -> step.getVnf())
362                         .withMessageContaining("missing generic VNF in A&AI response for my-model-invariant");
363
364         // missing model invariant ID
365         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
366         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
367                         .withMessageContaining("missing modelInvariantId");
368
369         // missing target
370         params = params.toBuilder().targetEntityIds(null).build();
371         step = new Step2(stepContext, params, event);
372         step.init();
373         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
374                         .withMessageContaining(Step2.TARGET_INFO_MSG);
375     }
376
377     @Test
378     public void testLoadVnfModel_testGetVnfModel() {
379         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
380         GenericVnf vnf = new GenericVnf();
381         when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf);
382
383         vnf.setModelVersionId("my-vnf-model-version-id");
384         ModelVer data = new ModelVer();
385         when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data);
386         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL));
387
388         step.setProperties();
389         verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
390
391         when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(null);
392         assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
393                         .withMessageContaining("missing model version for generic VNF in A&AI response");
394
395         vnf.setModelVersionId(null);
396         assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
397                         .withMessageContaining("missing model version ID for generic VNF in A&AI response");
398     }
399
400     @Test
401     public void testLoadVserverLink_testGetVserverLink() {
402         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
403
404         StandardCoderObject tenant = mock(StandardCoderObject.class);
405         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
406
407         when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
408
409         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
410
411         step.setProperties();
412         verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
413
414         // missing resource link
415         when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null);
416         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
417                         .withMessageContaining("missing tenant data resource-link");
418
419         // missing tenant data
420         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
421         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
422                         .withMessageContaining("missing tenant data for");
423
424         // empty vserver name
425         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
426         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
427                         .withMessageContaining("missing vserver.vserver-name");
428
429         // missing vserver name
430         event.setAai(Map.of());
431         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
432                         .withMessageContaining("missing vserver.vserver-name");
433     }
434
435     @Test
436     public void testLoadVfCount_testGetVfCount() {
437         params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, "vf-count-customization");
438         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "vf-count-invariant");
439         params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, "vf-count-version");
440         when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11);
441         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT));
442
443         step.setProperties();
444         verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
445
446         // missing model version id
447         params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, null);
448         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
449                         .withMessageContaining("missing target modelVersionId");
450
451         // missing model invariant id
452         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
453         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
454                         .withMessageContaining("missing target modelInvariantId");
455
456         // missing model customization id
457         params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, null);
458         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
459                         .withMessageContaining("missing target modelCustomizationId");
460
461         // missing target
462         params = params.toBuilder().targetEntityIds(null).build();
463         step = new Step2(stepContext, params, event);
464         step.init();
465         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
466                         .withMessageContaining(Step2.TARGET_INFO_MSG);
467
468         // get it from the step context
469         when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true);
470         when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22);
471         step.setProperties();
472         verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22);
473     }
474
475     @Test
476     public void testLoadEnrichment_testGetEnrichment() {
477         event.setAai(Map.of("bandwidth", "bandwidth-value"));
478         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
479
480         step.setProperties();
481         verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
482
483         // missing enrichment data
484         event.setAai(Map.of());
485         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
486     }
487
488     @Test
489     public void testLoadAdditionalEventParams_testGetAdditionalEventParams() {
490         Map<String, String> data = Map.of("addA", "add-valueA", "addB", "add-valueB");
491         event.setAdditionalEventParams(data);
492         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS));
493
494         step.setProperties();
495         verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
496     }
497
498     @Test
499     public void testLoadEventPayload_testGetEventPayload() {
500         event.setPayload("some-event-payload");
501         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
502
503         step.setProperties();
504         verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
505     }
506
507     @Test
508     public void testLoadOptCdsGrpcAaiProperties() {
509         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
510
511         step.setProperties();
512         verify(policyOperation, never()).setProperty(any(), anyString());
513     }
514
515     @Test
516     public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() {
517         GenericVnf data = new GenericVnf();
518         when(aaicq.getDefaultGenericVnf()).thenReturn(data);
519         when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF));
520
521         step.setProperties();
522         verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
523
524         when(aaicq.getDefaultGenericVnf()).thenReturn(null);
525         assertThatIllegalArgumentException().isThrownBy(() -> step.getDefaultGenericVnf())
526                         .withMessageContaining("missing generic VNF in A&AI response");
527     }
528
529     @Test
530     public void testGetCustomQueryData() {
531         assertSame(aaicq, step.getCustomQueryData());
532
533         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
534
535         assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
536                         .withMessage("missing custom query data for my-actor.my-operation");
537     }
538
539     @Test
540     public void testVerifyNotNull() {
541         assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
542
543         assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
544                         .withMessage("missing verifyB for my-actor.my-operation");
545     }
546
547     @Test
548     public void testStripPrefix() {
549         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0));
550         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1));
551         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2));
552
553         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
554         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
555
556         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
557         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
558
559         assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
560
561         assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));
562     }
563
564 }