bfb30abd42c2aec7f00419c1d191404f4a547315
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / test / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / notification / TestLifecycleChangeNotificationManager.java
1 /*
2  * Copyright 2016-2017, Nokia Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification;
17
18 import com.google.gson.*;
19 import com.nokia.cbam.lcm.v32.model.*;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.NoSuchElementException;
23 import java.util.Optional;
24 import java.util.concurrent.*;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.mockito.ArgumentCaptor;
28 import org.mockito.InjectMocks;
29 import org.mockito.Mockito;
30 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager;
31 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase;
32 import org.threeten.bp.OffsetDateTime;
33
34 import static java.util.Optional.empty;
35
36 import static com.nokia.cbam.lcm.v32.model.OperationType.*;
37 import static junit.framework.TestCase.*;
38 import static org.mockito.Mockito.*;
39 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
40 import static org.springframework.test.util.ReflectionTestUtils.setField;
41
42 public class TestLifecycleChangeNotificationManager extends TestBase {
43
44     @InjectMocks
45     private LifecycleChangeNotificationManager lifecycleChangeNotificationManager;
46     private VnfLifecycleChangeNotification recievedLcn = new VnfLifecycleChangeNotification();
47     private List<OperationExecution> operationExecutions = new ArrayList<>();
48     private OperationExecution instantiationOperation = new OperationExecution();
49     private OperationExecution scaleOperation = new OperationExecution();
50     private OperationExecution healOperation = new OperationExecution();
51     private OperationExecution terminationOperation = new OperationExecution();
52
53     private ArgumentCaptor<OperationExecution> currentOperationExecution = ArgumentCaptor.forClass(OperationExecution.class);
54     private ArgumentCaptor<Optional> affectedConnectionPoints = ArgumentCaptor.forClass(Optional.class);
55
56     private List<VnfInfo> vnfs = new ArrayList<>();
57     private VnfInfo vnf = new VnfInfo();
58
59     @Before
60     public void initMocks() throws Exception {
61         setField(LifecycleChangeNotificationManager.class, "logger", logger);
62         instantiationOperation.setId("instantiationOperationExecutionId");
63         instantiationOperation.setStartTime(OffsetDateTime.now());
64         instantiationOperation.setOperationType(OperationType.INSTANTIATE);
65         scaleOperation.setId("scaleOperationExecutionId");
66         scaleOperation.setStartTime(OffsetDateTime.now().plusDays(1));
67         scaleOperation.setOperationType(OperationType.SCALE);
68         terminationOperation.setId("terminationExecutionId");
69         terminationOperation.setStartTime(OffsetDateTime.now().plusDays(1));
70         terminationOperation.setOperationType(OperationType.TERMINATE);
71         healOperation.setId("healOperaitonExecutionId");
72         healOperation.setOperationType(OperationType.HEAL);
73         recievedLcn.setLifecycleOperationOccurrenceId("instantiationOperationExecutionId");
74         recievedLcn.setSubscriptionId(SUBCRIPTION_ID);
75         healOperation.setStartTime(OffsetDateTime.now().plusDays(1));
76         recievedLcn.setVnfInstanceId(VNF_ID);
77         when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecutions));
78         prepOperation(instantiationOperation);
79         prepOperation(scaleOperation);
80         prepOperation(healOperation);
81         prepOperation(terminationOperation);
82         doNothing().when(notificationSender).processNotification(eq(recievedLcn), currentOperationExecution.capture(), affectedConnectionPoints.capture(), eq(VIM_ID), eq(VNFM_ID));
83         InstantiateVnfRequest instantiateVnfRequest = new InstantiateVnfRequest();
84         VimInfo vimInfo = new VimInfo();
85         vimInfo.setId(VIM_ID);
86         instantiateVnfRequest.getVims().add(vimInfo);
87         when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(new Gson().toJsonTree(instantiateVnfRequest)));
88         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnfs));
89         vnfs.add(vnf);
90         vnf.setId(VNF_ID);
91         VnfProperty prop = new VnfProperty();
92         prop.setName(LifecycleManager.EXTERNAL_VNFM_ID);
93         prop.setValue(VNFM_ID);
94         vnf.setExtensions(new ArrayList<>());
95         vnf.getExtensions().add(prop);
96         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnf));
97     }
98
99     private void prepOperation(OperationExecution operationExecution) {
100         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
101         operationExecution.setOperationParams(root);
102         switch (operationExecution.getOperationType()) {
103             case TERMINATE:
104                 root.getAsJsonObject().addProperty("terminationType", "GRACEFULL");
105         }
106         when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(operationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecution));
107         operationExecutions.add(operationExecution);
108     }
109
110     private void addEmptyModifiedConnectionPoints(OperationExecution operationExecution) {
111         OperationResult operationResult = new OperationResult();
112         operationResult.operationResult = new ReportedAffectedConnectionPoints();
113         JsonElement additionalData = new Gson().toJsonTree(operationResult);
114         operationExecution.setAdditionalData(additionalData);
115     }
116
117     /**
118      * The first instantiation before the current operation is selected
119      */
120     @Test
121     public void testLastInstantiationSelection() {
122         List<OperationExecution> operations = new ArrayList<>();
123
124         OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE);
125         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
126         OperationExecution operationClosestInstantiate = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE);
127         OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(3), INSTANTIATE);
128
129         operations.add(operation);
130         operations.add(operationScale);
131         operations.add(operationClosestInstantiate);
132         operations.add(operationFurthers);
133         assertEquals(operationClosestInstantiate, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
134     }
135
136     /**
137      * The instantiation operation itself is valid as the last instantiation operation
138      */
139     @Test
140     public void testInstantiationSufficesTheLastInstantiation() {
141         OffsetDateTime baseTime = OffsetDateTime.now();
142         List<OperationExecution> operations = new ArrayList<>();
143
144         OperationExecution operation = buildOperation(OffsetDateTime.now(), INSTANTIATE);
145         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
146         OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE);
147
148         operations.add(operation);
149         operations.add(operationScale);
150         operations.add(operationFurthers);
151         assertEquals(operation, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation));
152     }
153
154     /**
155      * If no instantiation operation is found for before the selected operation
156      */
157     @Test
158     public void testNoInstantiation() {
159         OffsetDateTime baseTime = OffsetDateTime.now();
160         List<OperationExecution> operations = new ArrayList<>();
161
162         OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE);
163         OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE);
164
165         operations.add(operation);
166         operations.add(operationScale);
167         try {
168             LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation);
169             fail();
170         } catch (NoSuchElementException e) {
171
172         }
173     }
174
175     /**
176      * the operations are ordered from newest (first) to oldest (last)
177      */
178     @Test
179     public void testOperationOrdering() {
180         List<OperationExecution> operationExecutions = new ArrayList<>();
181         OperationExecution before = buildOperation(OffsetDateTime.now(), OperationType.INSTANTIATE);
182         operationExecutions.add(before);
183         OperationExecution after = buildOperation(OffsetDateTime.now().plusDays(1), OperationType.SCALE);
184         operationExecutions.add(after);
185         List<OperationExecution> sorted1 = LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions);
186         assertEquals(after, sorted1.get(0));
187         assertEquals(before, sorted1.get(1));
188     }
189
190     /**
191      * if VNF listing fails the processing of the notifications is aborted
192      */
193     @Test
194     public void testUnableToListVnfs() throws Exception {
195         RuntimeException expectedException = new RuntimeException();
196         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
197         //when
198         try {
199             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
200             fail();
201         } catch (Exception e) {
202             assertEquals(expectedException, e.getCause());
203             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
204         }
205     }
206
207     /**
208      * if VNF query fails the processing of the notifications is aborted
209      */
210     @Test
211     public void testUnableToQueryVnf() throws Exception {
212         RuntimeException expectedException = new RuntimeException();
213         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
214         //when
215         try {
216             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
217             fail();
218         } catch (Exception e) {
219             assertEquals(expectedException, e.getCause());
220             verify(logger).error("Unable to list VNFs / query VNF", expectedException);
221         }
222     }
223
224     /**
225      * if the VNF is not managed by this VNFM the LCN is dropped
226      */
227     @Test
228     public void testNonManagedVnf() throws Exception {
229         vnf.getExtensions().clear();
230         //when
231         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
232         //verify
233         Mockito.verifyZeroInteractions(operationExecutionApi);
234         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed VNF");
235     }
236
237     /**
238      * LCN is not logged in case of non info log level
239      */
240     @Test
241     public void testNoLogging() throws Exception {
242         vnf.getExtensions().clear();
243         when(logger.isInfoEnabled()).thenReturn(false);
244         //when
245         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
246         //verify
247         verify(logger, never()).info(eq("Received LCN: {}"), anyString());
248     }
249
250     /**
251      * if the VNF is not managed by this VNFM the LCN is dropped
252      */
253     @Test
254     public void testManagedByOtherVnf() throws Exception {
255         vnf.getExtensions().get(0).setValue("unknownVnfmId");
256         //when
257         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
258         //verify
259         Mockito.verifyZeroInteractions(operationExecutionApi);
260         verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed by the VNFM with id unknownVnfmId");
261     }
262
263     /**
264      * if the VNF disappeared before processing the LCN
265      */
266     @Test
267     public void testDisappearedVnf() throws Exception {
268         vnfs.clear();
269         //when
270         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
271         //verify
272         Mockito.verifyZeroInteractions(operationExecutionApi);
273         verify(logger).warn("The VNF with " + VNF_ID + " identifier disappeared before being able to process the LCN");
274     }
275
276     /**
277      * if the operation parameters of the last instantiation is non querieable error is propagated
278      */
279     @Test
280     public void testUnableToQueryOperationParams() throws Exception {
281         recievedLcn.setOperation(OperationType.TERMINATE);
282         recievedLcn.setStatus(OperationStatus.FINISHED);
283         RuntimeException expectedException = new RuntimeException();
284         when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
285         //when
286         try {
287             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
288             fail();
289         } catch (Exception e) {
290             //verify
291             Mockito.verifyZeroInteractions(nsLcmApi);
292             assertEquals(expectedException, e.getCause());
293             verify(logger).error("Unable to detect last instantiation operation", e.getCause());
294         }
295     }
296
297     /**
298      * if unable to query all operation executions from CBAM the error is propagated
299      */
300     @Test
301     public void testUnableToQueryCurrentOperations() throws Exception {
302         recievedLcn.setOperation(OperationType.TERMINATE);
303         recievedLcn.setStatus(OperationStatus.FINISHED);
304         RuntimeException expectedException = new RuntimeException();
305         when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
306         //when
307         try {
308             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
309             fail();
310         } catch (Exception e) {
311             //verify
312             assertEquals(expectedException, e.getCause());
313             verify(logger).error("Unable to retrieve the operation executions for the VNF myVnfId", e.getCause());
314         }
315     }
316
317     /**
318      * if unable to query the given operation execution from CBAM the error is propagated
319      */
320     @Test
321     public void testUnableToQueryCurrentOperation() throws Exception {
322         recievedLcn.setOperation(OperationType.TERMINATE);
323         recievedLcn.setStatus(OperationStatus.FINISHED);
324         RuntimeException expectedException = new RuntimeException();
325         when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(recievedLcn.getLifecycleOperationOccurrenceId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException);
326         //when
327         try {
328             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
329             fail();
330         } catch (Exception e) {
331             //verify
332             assertEquals(expectedException, e.getCause());
333             verify(logger).error("Unable to retrieve the operation execution with instantiationOperationExecutionId identifier", e.getCause());
334         }
335     }
336
337     /**
338      * test that waitForTerminationToBeProcessed outwaits the successfull processing of the termination notification
339      */
340     @Test
341     public void testWaitForTermination() throws Exception {
342         //given
343         //add an non processed notification
344         VnfLifecycleChangeNotification nonProcessedEvent = new VnfLifecycleChangeNotification();
345         nonProcessedEvent.setSubscriptionId(SUBCRIPTION_ID);
346         nonProcessedEvent.setStatus(OperationStatus.FINISHED);
347         nonProcessedEvent.setOperation(OperationType.TERMINATE);
348         OperationExecution secondTerminationOperationExecution = new OperationExecution();
349         secondTerminationOperationExecution.setOperationType(OperationType.TERMINATE);
350         secondTerminationOperationExecution.setId("secondId");
351         secondTerminationOperationExecution.setOperationParams(buildTerminationParams());
352         nonProcessedEvent.setLifecycleOperationOccurrenceId(secondTerminationOperationExecution.getId());
353         lifecycleChangeNotificationManager.handleLcn(nonProcessedEvent);
354         addEmptyModifiedConnectionPoints(terminationOperation);
355         //add second termination
356         recievedLcn.setOperation(OperationType.TERMINATE);
357         recievedLcn.setStatus(OperationStatus.FINISHED);
358         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
359         ExecutorService executorService = Executors.newCachedThreadPool();
360         Future<Boolean> waitExitedWithSuccess = executorService.submit(new Callable<Boolean>() {
361             @Override
362             public Boolean call() throws Exception {
363                 try {
364                     lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
365                     return true;
366                 } catch (Exception e) {
367                     return false;
368                 }
369             }
370         });
371         //when
372         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
373         //verify
374         assertTrue(waitExitedWithSuccess.get());
375     }
376
377     /**
378      * the processing of the start notification does not trigger the deletion of the VNF
379      */
380     @Test
381     public void testStartLcnForTerminate() throws Exception {
382         recievedLcn.setOperation(OperationType.TERMINATE);
383         recievedLcn.setStatus(OperationStatus.STARTED);
384         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
385         ExecutorService executorService = Executors.newCachedThreadPool();
386         Future<Boolean> waitExitedWithSuccess = executorService.submit(() -> {
387             try {
388                 lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
389                 return true;
390             } catch (Exception e) {
391                 return false;
392             }
393         });
394         //processing the start notification
395         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
396         //verify
397         try {
398             waitExitedWithSuccess.get(10, TimeUnit.MILLISECONDS);
399             fail();
400         } catch (Exception e) {
401         }
402         recievedLcn.setStatus(OperationStatus.FINISHED);
403         //when
404         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
405         //verify
406         assertTrue(waitExitedWithSuccess.get());
407         assertEquals(empty(), affectedConnectionPoints.getValue());
408     }
409
410     /**
411      * Forceful termination results in an empty affected connection points
412      */
413     @Test
414     public void testMissingPreResultForForcefullTermination() {
415         //given
416         recievedLcn.setOperation(OperationType.INSTANTIATE);
417         recievedLcn.setStatus(OperationStatus.FINISHED);
418         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
419         JsonObject additionalData = new JsonObject();
420         additionalData.add("operationResult", new JsonObject());
421         ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "FORCEFUL");
422         terminationOperation.setAdditionalData(additionalData);
423         terminationOperation.setStatus(OperationStatus.FINISHED);
424         terminationOperation.setOperationType(OperationType.TERMINATE);
425         //when
426         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
427         assertFalse(affectedConnectionPoints.getValue().isPresent());
428         verify(logger).warn("Unable to send information related to affected connection points during forceful termination");
429     }
430
431     /**
432      * Forceful termination results in an empty affected connection points
433      */
434     @Test
435     public void testGracefullTermination() {
436         //given
437         recievedLcn.setOperation(OperationType.INSTANTIATE);
438         recievedLcn.setStatus(OperationStatus.FINISHED);
439         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
440         ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "GRACEFUL");
441         addEmptyModifiedConnectionPoints(terminationOperation);
442         terminationOperation.setStatus(OperationStatus.FINISHED);
443         terminationOperation.setOperationType(OperationType.TERMINATE);
444         //when
445         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
446         assertTrue(affectedConnectionPoints.getValue().isPresent());
447     }
448
449     /**
450      * Failures in affected connection point processing are tolerated for failed operation
451      * (because the POST script was not able to run)
452      */
453     @Test
454     public void testFailedOperations() throws Exception {
455         //given
456         recievedLcn.setOperation(OperationType.INSTANTIATE);
457         recievedLcn.setStatus(OperationStatus.FAILED);
458         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
459         instantiationOperation.setAdditionalData(null);
460         instantiationOperation.setStatus(OperationStatus.FAILED);
461         //when
462         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
463         //verify
464         assertFalse(affectedConnectionPoints.getValue().isPresent());
465         verify(logger).warn("The operation failed and the affected connection points were not reported");
466     }
467
468
469     /**
470      * affected connection points are passed to the actual notification processor
471      */
472     @Test
473     public void testAffectedConnectionPointProcessing() throws Exception {
474         //given
475         recievedLcn.setOperation(OperationType.INSTANTIATE);
476         recievedLcn.setStatus(OperationStatus.FINISHED);
477         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
478         instantiationOperation.setStatus(OperationStatus.FAILED);
479         addEmptyModifiedConnectionPoints(instantiationOperation);
480         OperationResult operationResult = new OperationResult();
481         ReportedAffectedConnectionPoints affectedCp = new ReportedAffectedConnectionPoints();
482         ReportedAffectedCp cp = new ReportedAffectedCp();
483         cp.setCpId("cpId");
484         affectedCp.getPost().add(cp);
485         operationResult.operationResult = affectedCp;
486         instantiationOperation.setAdditionalData(new Gson().toJsonTree(operationResult));
487
488         //when
489         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
490         //verify
491         assertTrue(affectedConnectionPoints.getValue().isPresent());
492         ReportedAffectedConnectionPoints actualCps = new Gson().fromJson(new Gson().toJsonTree(affectedConnectionPoints.getValue().get()), ReportedAffectedConnectionPoints.class);
493         assertEquals(1, actualCps.getPost().size());
494     }
495
496     /**
497      * Failures in affected connection point processing are tolerated for failed operation
498      * (because the POST script was not able to run)
499      */
500     @Test
501     public void testMissingOperationResult() throws Exception {
502         //given
503         recievedLcn.setOperation(OperationType.INSTANTIATE);
504         recievedLcn.setStatus(OperationStatus.FAILED);
505         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
506         instantiationOperation.setStatus(OperationStatus.FAILED);
507         addEmptyModifiedConnectionPoints(instantiationOperation);
508         JsonObject additionalData = (JsonObject) instantiationOperation.getAdditionalData();
509         additionalData.remove("operationResult");
510         //when
511         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
512         //verify
513         assertFalse(affectedConnectionPoints.getValue().isPresent());
514         verify(logger).warn("The operation failed and the affected connection points were not reported");
515     }
516
517     /**
518      * test end notification scenario for failed scale-out
519      * - LCN is sent to VF-C, but the
520      */
521     @Test
522     public void testMissingPreResultForFailedOperation() {
523         //given
524         recievedLcn.setOperation(OperationType.SCALE);
525         recievedLcn.setStatus(OperationStatus.FAILED);
526         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
527         ScaleVnfRequest request = new ScaleVnfRequest();
528         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
529         request.setType(ScaleDirection.OUT);
530         scaleOperation.setOperationParams(request);
531         scaleOperation.setAdditionalData(null);
532         scaleOperation.setStatus(OperationStatus.FAILED);
533         scaleOperation.setOperationType(OperationType.SCALE);
534         //when
535         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
536         assertFalse(affectedConnectionPoints.getValue().isPresent());
537         verify(logger).warn("The operation failed and the affected connection points were not reported");
538     }
539
540     /**
541      * if the cbam_post is missing error handling should be applied
542      */
543     @Test
544     public void testMissingPostResultForFailedOperation() {
545         //given
546         recievedLcn.setOperation(OperationType.SCALE);
547         recievedLcn.setStatus(OperationStatus.FAILED);
548         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
549         ScaleVnfRequest request = new ScaleVnfRequest();
550         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
551         request.setType(ScaleDirection.OUT);
552         scaleOperation.setOperationParams(request);
553         scaleOperation.setStatus(OperationStatus.FAILED);
554         addEmptyModifiedConnectionPoints(scaleOperation);
555         ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject().remove("cbam_post");
556         scaleOperation.setOperationType(OperationType.SCALE);
557
558         //when
559         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
560         assertFalse(affectedConnectionPoints.getValue().isPresent());
561         verify(logger).warn("The operation failed and the affected connection points were not reported");
562     }
563
564     /**
565      * if invalid type is specified for cbam_post error handling should be applied
566      */
567     @Test
568     public void testInvalidPost() {
569         //given
570         recievedLcn.setOperation(OperationType.SCALE);
571         recievedLcn.setStatus(OperationStatus.FAILED);
572         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
573         ScaleVnfRequest request = new ScaleVnfRequest();
574         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
575         request.setType(ScaleDirection.OUT);
576         scaleOperation.setOperationParams(request);
577         scaleOperation.setStatus(OperationStatus.FAILED);
578         addEmptyModifiedConnectionPoints(scaleOperation);
579         JsonObject operationResult = ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject();
580         operationResult.remove("cbam_post");
581         operationResult.addProperty("cbam_post", "");
582         scaleOperation.setOperationType(OperationType.SCALE);
583         //when
584         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
585         assertFalse(affectedConnectionPoints.getValue().isPresent());
586         verify(logger).warn("The operation failed and the affected connection points were not reported");
587     }
588
589
590     /**
591      * test end notification success scenario for scale-out
592      * - LCN is sent to VF-C
593      */
594     @Test
595     public void testMissingPreResult() {
596         //given
597         recievedLcn.setOperation(OperationType.SCALE);
598         recievedLcn.setStatus(OperationStatus.FINISHED);
599         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
600         ScaleVnfRequest request = new ScaleVnfRequest();
601         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
602         request.setType(ScaleDirection.OUT);
603         scaleOperation.setOperationParams(request);
604         JsonObject additionalData = new JsonObject();
605         additionalData.add("operationResult", new JsonObject());
606         scaleOperation.setAdditionalData(additionalData);
607         scaleOperation.setStatus(OperationStatus.FINISHED);
608         scaleOperation.setOperationType(OperationType.SCALE);
609         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
610         JsonObject operationParams = new JsonObject();
611         //when
612         try {
613             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
614             fail();
615         } catch (Exception e) {
616             assertEquals("All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure", e.getMessage());
617         }
618     }
619
620     private JsonObject buildTerminationParams() {
621         JsonObject root = new JsonObject();
622         root.add("terminationType", new JsonPrimitive("GRACEFULL"));
623         return root;
624     }
625
626     private OperationExecution buildOperation(OffsetDateTime baseTime, OperationType operationType) {
627         OperationExecution operation = new OperationExecution();
628         operation.setStartTime(baseTime);
629         operation.setOperationType(operationType);
630         return operation;
631     }
632
633     class OperationResult {
634         ReportedAffectedConnectionPoints operationResult;
635     }
636
637 }