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