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