d80484a2e971fef040f605555e58ecec52de4813
[policy/drools-applications.git] / controlloop / common / controller-usecases / src / test / java / org / onap / policy / drools / apps / controller / usecases / step / Step2Test.java
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.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;
72
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";
83
84     @Mock
85     private Operator policyOperator;
86     @Mock
87     private Operation policyOperation;
88     @Mock
89     private Actor policyActor;
90     @Mock
91     private ActorService actors;
92     @Mock
93     private StepContext stepContext;
94     @Mock
95     private AaiCqResponse aaicq;
96
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         // 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);
113
114         when(policyOperation.getPropertyNames()).thenReturn(List.of());
115
116         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
117
118         payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
119
120         event = new VirtualControlLoopEvent();
121         event.setRequestId(REQ_ID);
122
123         starts = new LinkedBlockingQueue<>();
124         completions = new LinkedBlockingQueue<>();
125
126         Map<String, String> entityIds = new HashMap<>();
127
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();
133
134         step = new Step2(stepContext, params, event);
135         step.init();
136     }
137
138     @Test
139     public void testConstructor() {
140         assertSame(stepContext, step.stepContext);
141         assertSame(event, step.event);
142         assertSame(actors, step.getParams().getActorService());
143     }
144
145     @Test
146     public void testConstructorStep2() {
147         step = new Step2(step, "actorB", "operationB");
148         assertSame(stepContext, step.stepContext);
149         assertSame(event, step.event);
150
151         assertEquals("actorB", step.getActorName());
152         assertEquals("operationB", step.getOperationName());
153         assertSame(actors, step.getParams().getActorService());
154     }
155
156     @Test
157     public void testAcceptsEvent() {
158         // it's a policy step, thus it accepts events
159         assertTrue(step.acceptsEvent());
160
161         step = new Step2(step, "actorB", "operationB");
162
163         // it's not a policy step, thus it does not accept events
164         assertFalse(step.acceptsEvent());
165     }
166
167     @Test
168     public void testSuccess() {
169         assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
170     }
171
172     @Test
173     public void testGetPropertyNames() {
174         // empty property list
175         assertThat(step.getPropertyNames()).isEmpty();
176
177         // try with non-empty list
178         when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
179         assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
180     }
181
182     @Test
183     public void testSetProperties() {
184         CloudRegion cloudRegion = new CloudRegion();
185         when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
186
187         Tenant tenant = new Tenant();
188         when(aaicq.getDefaultTenant()).thenReturn(tenant);
189
190         when(policyOperation.getPropertyNames()).thenReturn(
191                         List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
192
193         step.setProperties();
194
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);
199     }
200
201     /**
202      * Tests setProperties() when the property is unknown.
203      */
204     @Test
205     public void testSetPropertiesUnknown() {
206         when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
207
208         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
209                         .withMessage("unknown property unknown-property needed by my-actor.my-operation");
210     }
211
212     @Test
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));
217
218         step.setProperties();
219         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
220
221         when(aaicq.getDefaultCloudRegion()).thenReturn(null);
222         assertThatIllegalArgumentException().isThrownBy(() -> step.getCloudRegion())
223                         .withMessageContaining("missing default cloud region in A&AI response");
224     }
225
226     @Test
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));
231
232         step.setProperties();
233         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
234
235         when(aaicq.getDefaultTenant()).thenReturn(null);
236         assertThatIllegalArgumentException().isThrownBy(() -> step.getTenant())
237                         .withMessageContaining("missing default tenant in A&AI response");
238     }
239
240     @Test
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));
246
247         step.setProperties();
248         verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
249
250         when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(null);
251         assertThatIllegalArgumentException().isThrownBy(() -> step.getPnf())
252                         .withMessageContaining("missing PNF for my-target");
253     }
254
255     @Test
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));
261
262         step.setProperties();
263         verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
264
265         when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(null);
266         assertThatIllegalArgumentException().isThrownBy(() -> step.getResourceVnf())
267                         .withMessageContaining("missing VNF for my-resource");
268
269         // missing resource ID
270         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
271         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
272                         .withMessageContaining("missing Target resource ID");
273
274         // missing target entity IDs
275         params = params.toBuilder().targetEntityIds(null).build();
276         step = new Step2(stepContext, params, event);
277         step.init();
278         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
279                         .withMessageContaining(Step2.TARGET_INFO_MSG);
280     }
281
282     @Test
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));
287
288         step.setProperties();
289         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
290
291         when(aaicq.getServiceInstance()).thenReturn(null);
292         assertThatIllegalArgumentException().isThrownBy(() -> step.getService())
293                         .withMessageContaining("missing service instance in A&AI response");
294     }
295
296     @Test
297     public void testLoadServiceModel_testGetServiceModel() {
298         ServiceInstance service = new ServiceInstance();
299         service.setModelVersionId("my-service-version");
300         when(aaicq.getServiceInstance()).thenReturn(service);
301
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));
305
306         step.setProperties();
307         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
308
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");
312
313         service.setModelVersionId(null);
314         assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
315                         .withMessageContaining("missing service model version ID in A&AI response");
316
317         when(aaicq.getServiceInstance()).thenReturn(null);
318         assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
319                         .withMessageContaining("missing service instance in A&AI response");
320     }
321
322     @Test
323     public void testGetVserver() {
324         Vserver vserver = new Vserver();
325         when(aaicq.getVserver()).thenReturn(vserver);
326
327         assertSame(vserver, step.getVServer());
328
329         when(aaicq.getVserver()).thenReturn(null);
330         assertThatIllegalArgumentException().isThrownBy(() -> step.getVServer())
331                         .withMessageContaining("missing vserver in A&AI response");
332     }
333
334     @Test
335     public void testGetTargetEntity() {
336         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
337
338         assertEquals(MY_TARGET, step.getTargetEntity());
339
340         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(null);
341         assertThatIllegalArgumentException().isThrownBy(() -> step.getTargetEntity())
342                         .withMessageContaining("missing A&AI target entity");
343     }
344
345     @Test
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));
351
352         step.setProperties();
353         verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
354
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");
358
359         // missing model invariant ID
360         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
361         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
362                         .withMessageContaining("missing modelInvariantId");
363
364         // missing target
365         params = params.toBuilder().targetEntityIds(null).build();
366         step = new Step2(stepContext, params, event);
367         step.init();
368         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
369                         .withMessageContaining(Step2.TARGET_INFO_MSG);
370     }
371
372     @Test
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);
377
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));
382
383         step.setProperties();
384         verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
385
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");
389
390         vnf.setModelVersionId(null);
391         assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
392                         .withMessageContaining("missing model version ID for generic VNF in A&AI response");
393     }
394
395     @Test
396     public void testLoadVserverLink_testGetVserverLink() {
397         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
398
399         StandardCoderObject tenant = mock(StandardCoderObject.class);
400         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
401
402         when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
403
404         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
405
406         step.setProperties();
407         verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
408
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");
413
414         // missing tenant data
415         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
416         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
417                         .withMessageContaining("missing tenant data for");
418
419         // empty vserver name
420         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
421         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
422                         .withMessageContaining("missing vserver.vserver-name");
423
424         // missing vserver name
425         event.setAai(Map.of());
426         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
427                         .withMessageContaining("missing vserver.vserver-name");
428     }
429
430     @Test
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));
437
438         step.setProperties();
439         verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
440
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");
445
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");
450
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");
455
456         // missing target
457         params = params.toBuilder().targetEntityIds(null).build();
458         step = new Step2(stepContext, params, event);
459         step.init();
460         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
461                         .withMessageContaining(Step2.TARGET_INFO_MSG);
462
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);
468     }
469
470     @Test
471     public void testLoadEnrichment_testGetEnrichment() {
472         event.setAai(Map.of("bandwidth", "bandwidth-value"));
473         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
474
475         step.setProperties();
476         verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
477
478         // missing enrichment data
479         event.setAai(Map.of());
480         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
481     }
482
483     @Test
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));
488
489         step.setProperties();
490         verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
491     }
492
493     @Test
494     public void testLoadEventPayload_testGetEventPayload() {
495         event.setPayload("some-event-payload");
496         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
497
498         step.setProperties();
499         verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
500     }
501
502     @Test
503     public void testLoadOptCdsGrpcAaiProperties() {
504         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
505
506         step.setProperties();
507         verify(policyOperation, never()).setProperty(any(), anyString());
508     }
509
510     @Test
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));
515
516         step.setProperties();
517         verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
518
519         when(aaicq.getDefaultGenericVnf()).thenReturn(null);
520         assertThatIllegalArgumentException().isThrownBy(() -> step.getDefaultGenericVnf())
521                         .withMessageContaining("missing generic VNF in A&AI response");
522     }
523
524     @Test
525     public void testGetCustomQueryData() {
526         assertSame(aaicq, step.getCustomQueryData());
527
528         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
529
530         assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
531                         .withMessage("missing custom query data for my-actor.my-operation");
532     }
533
534     @Test
535     public void testVerifyNotNull() {
536         assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
537
538         assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
539                         .withMessage("missing verifyB for my-actor.my-operation");
540     }
541
542     @Test
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));
547
548         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
549         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
550
551         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
552         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
553
554         assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
555
556         assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));
557     }
558
559 }