dc1b8ddf6773dd687057ee25d59f5a1c9aad700f
[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 org.junit.Before;
21 import org.junit.Test;
22 import org.mockito.ArgumentCaptor;
23 import org.mockito.InjectMocks;
24 import org.mockito.Mockito;
25 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager;
26 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase;
27 import org.threeten.bp.OffsetDateTime;
28
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.NoSuchElementException;
32 import java.util.Optional;
33 import java.util.concurrent.*;
34
35 import static com.nokia.cbam.lcm.v32.model.OperationType.*;
36 import static junit.framework.TestCase.*;
37 import static org.mockito.Mockito.*;
38 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
39 import static org.springframework.test.util.ReflectionTestUtils.setField;
40
41 public class TestLifecycleChangeNotificationManager extends TestBase {
42
43     @InjectMocks
44     private LifecycleChangeNotificationManager lifecycleChangeNotificationManager;
45     private VnfLifecycleChangeNotification recievedLcn = new VnfLifecycleChangeNotification();
46     private List<OperationExecution> operationExecutions = new ArrayList<>();
47     private OperationExecution instantiationOperation = new OperationExecution();
48     private OperationExecution scaleOperation = new OperationExecution();
49     private OperationExecution healOperation = new OperationExecution();
50     private OperationExecution terminationOperation = new OperationExecution();
51
52     private ArgumentCaptor<OperationExecution> currentOperationExecution = ArgumentCaptor.forClass(OperationExecution.class);
53     private ArgumentCaptor<Optional> affectedConnectionPoints = ArgumentCaptor.forClass(Optional.class);
54
55     private List<VnfInfo> vnfs = new ArrayList<>();
56     private VnfInfo vnf = new VnfInfo();
57
58     @Before
59     public void initMocks() throws Exception {
60         setField(LifecycleChangeNotificationManager.class, "logger", logger);
61         instantiationOperation.setId("instantiationOperationExecutionId");
62         instantiationOperation.setStartTime(OffsetDateTime.now());
63         instantiationOperation.setOperationType(OperationType.INSTANTIATE);
64         scaleOperation.setId("scaleOperationExecutionId");
65         scaleOperation.setStartTime(OffsetDateTime.now().plusDays(1));
66         scaleOperation.setOperationType(OperationType.SCALE);
67         terminationOperation.setId("terminationExecutionId");
68         terminationOperation.setStartTime(OffsetDateTime.now().plusDays(1));
69         terminationOperation.setOperationType(OperationType.TERMINATE);
70         healOperation.setId("healOperaitonExecutionId");
71         healOperation.setOperationType(OperationType.HEAL);
72         recievedLcn.setLifecycleOperationOccurrenceId("instantiationOperationExecutionId");
73         healOperation.setStartTime(OffsetDateTime.now().plusDays(1));
74         recievedLcn.setVnfInstanceId(VNF_ID);
75         when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(operationExecutions));
76         prepOperation(instantiationOperation);
77         prepOperation(scaleOperation);
78         prepOperation(healOperation);
79         prepOperation(terminationOperation);
80         doNothing().when(notificationSender).processNotification(eq(recievedLcn), currentOperationExecution.capture(), affectedConnectionPoints.capture(), eq(VIM_ID));
81         InstantiateVnfRequest instantiateVnfRequest = new InstantiateVnfRequest();
82         VimInfo vimInfo = new VimInfo();
83         vimInfo.setId(VIM_ID);
84         instantiateVnfRequest.getVims().add(vimInfo);
85         when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(new Gson().toJsonTree(instantiateVnfRequest)));
86         when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnfs));
87         vnfs.add(vnf);
88         vnf.setId(VNF_ID);
89         VnfProperty prop = new VnfProperty();
90         prop.setName(LifecycleManager.EXTERNAL_VNFM_ID);
91         prop.setValue(VNFM_ID);
92         vnf.setExtensions(new ArrayList<>());
93         vnf.getExtensions().add(prop);
94         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnf));
95     }
96
97     private void prepOperation(OperationExecution operationExecution) {
98         addEmptyModifiedConnectionPoints(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         //add second termination
353         recievedLcn.setOperation(OperationType.TERMINATE);
354         recievedLcn.setStatus(OperationStatus.FINISHED);
355         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
356         ExecutorService executorService = Executors.newCachedThreadPool();
357         Future<Boolean> waitExitedWithSuccess = executorService.submit(new Callable<Boolean>() {
358             @Override
359             public Boolean call() throws Exception {
360                 try {
361                     lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
362                     return true;
363                 } catch (Exception e) {
364                     return false;
365                 }
366             }
367         });
368         //when
369         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
370         //verify
371         assertTrue(waitExitedWithSuccess.get());
372     }
373
374     /**
375      * the processing of the start notification does not trigger the deletion of the VNF
376      */
377     @Test
378     public void testStartLcnForTerminate() throws Exception {
379         recievedLcn.setOperation(OperationType.TERMINATE);
380         recievedLcn.setStatus(OperationStatus.STARTED);
381         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
382         ExecutorService executorService = Executors.newCachedThreadPool();
383         Future<Boolean> waitExitedWithSuccess = executorService.submit(() -> {
384             try {
385                 lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId());
386                 return true;
387             } catch (Exception e) {
388                 return false;
389             }
390         });
391         //processing the start notification
392         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
393         //verify
394         try {
395             waitExitedWithSuccess.get(10, TimeUnit.MILLISECONDS);
396             fail();
397         } catch (Exception e) {
398         }
399         recievedLcn.setStatus(OperationStatus.FINISHED);
400         //when
401         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
402         //verify
403         assertTrue(waitExitedWithSuccess.get());
404     }
405
406     /**
407      * Forceful termination results in an empty affected connection points
408      */
409     @Test
410     public void testMissingPreResultForForcefullTermination() {
411         //given
412         recievedLcn.setOperation(OperationType.INSTANTIATE);
413         recievedLcn.setStatus(OperationStatus.FINISHED);
414         recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId());
415         JsonObject additionalData = new JsonObject();
416         additionalData.add("operationResult", new JsonObject());
417         ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "FORCEFUL");
418         terminationOperation.setAdditionalData(additionalData);
419         terminationOperation.setStatus(OperationStatus.FINISHED);
420         terminationOperation.setOperationType(OperationType.TERMINATE);
421         //when
422         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
423         assertFalse(affectedConnectionPoints.getValue().isPresent());
424         verify(logger).warn("Unable to send information related to affected connection points during forceful termination");
425     }
426
427     /**
428      * Failures in affected connection point processing are tolerated for failed operation
429      * (because the POST script was not able to run)
430      */
431     @Test
432     public void testFailedOperations() throws Exception {
433         //given
434         recievedLcn.setOperation(OperationType.INSTANTIATE);
435         recievedLcn.setStatus(OperationStatus.FAILED);
436         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
437         instantiationOperation.setAdditionalData(null);
438         instantiationOperation.setStatus(OperationStatus.FAILED);
439         //when
440         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
441         //verify
442         assertFalse(affectedConnectionPoints.getValue().isPresent());
443         verify(logger).warn("The operation failed and the affected connection points were not reported");
444     }
445
446     /**
447      * Failures in affected connection point processing are tolerated for failed operation
448      * (because the POST script was not able to run)
449      */
450     @Test
451     public void testMissingOperationResult() throws Exception {
452         //given
453         recievedLcn.setOperation(OperationType.INSTANTIATE);
454         recievedLcn.setStatus(OperationStatus.FAILED);
455         recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId());
456         instantiationOperation.setStatus(OperationStatus.FAILED);
457         JsonObject additionalData = (JsonObject) instantiationOperation.getAdditionalData();
458         additionalData.remove("operationResult");
459         //when
460         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
461         //verify
462         assertFalse(affectedConnectionPoints.getValue().isPresent());
463         verify(logger).warn("The operation failed and the affected connection points were not reported");
464     }
465
466     /**
467      * test end notification scenario for failed scale-out
468      * - LCN is sent to VF-C, but the
469      */
470     @Test
471     public void testMissingPreResultForFailedOperation() {
472         //given
473         recievedLcn.setOperation(OperationType.SCALE);
474         recievedLcn.setStatus(OperationStatus.FAILED);
475         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
476         ScaleVnfRequest request = new ScaleVnfRequest();
477         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
478         request.setType(ScaleDirection.OUT);
479         scaleOperation.setOperationParams(request);
480         scaleOperation.setAdditionalData(null);
481         scaleOperation.setStatus(OperationStatus.FAILED);
482         scaleOperation.setOperationType(OperationType.SCALE);
483         //when
484         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
485         assertFalse(affectedConnectionPoints.getValue().isPresent());
486         verify(logger).warn("The operation failed and the affected connection points were not reported");
487     }
488
489     /**
490      * if the cbam_post is missing error handling should be applied
491      */
492     @Test
493     public void testMissingPostResultForFailedOperation() {
494         //given
495         recievedLcn.setOperation(OperationType.SCALE);
496         recievedLcn.setStatus(OperationStatus.FAILED);
497         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
498         ScaleVnfRequest request = new ScaleVnfRequest();
499         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
500         request.setType(ScaleDirection.OUT);
501         scaleOperation.setOperationParams(request);
502         scaleOperation.setStatus(OperationStatus.FAILED);
503         ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject().remove("cbam_post");
504         scaleOperation.setOperationType(OperationType.SCALE);
505         //when
506         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
507         assertFalse(affectedConnectionPoints.getValue().isPresent());
508         verify(logger).warn("The operation failed and the affected connection points were not reported");
509     }
510
511     /**
512      * if invalid type is specified for cbam_post error handling should be applied
513      */
514     @Test
515     public void testInvalidPost() {
516         //given
517         recievedLcn.setOperation(OperationType.SCALE);
518         recievedLcn.setStatus(OperationStatus.FAILED);
519         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
520         ScaleVnfRequest request = new ScaleVnfRequest();
521         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
522         request.setType(ScaleDirection.OUT);
523         scaleOperation.setOperationParams(request);
524         scaleOperation.setStatus(OperationStatus.FAILED);
525         JsonObject operationResult = ((JsonObject) scaleOperation.getAdditionalData()).get("operationResult").getAsJsonObject();
526         operationResult.remove("cbam_post");
527         operationResult.addProperty("cbam_post", "");
528         scaleOperation.setOperationType(OperationType.SCALE);
529         //when
530         lifecycleChangeNotificationManager.handleLcn(recievedLcn);
531         assertFalse(affectedConnectionPoints.getValue().isPresent());
532         verify(logger).warn("The operation failed and the affected connection points were not reported");
533     }
534
535
536     /**
537      * test end notification success scenario for scale-out
538      * - LCN is sent to VF-C
539      */
540     @Test
541     public void testMissingPreResult() {
542         //given
543         recievedLcn.setOperation(OperationType.SCALE);
544         recievedLcn.setStatus(OperationStatus.FINISHED);
545         recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId());
546         ScaleVnfRequest request = new ScaleVnfRequest();
547         request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }"));
548         request.setType(ScaleDirection.OUT);
549         scaleOperation.setOperationParams(request);
550         JsonObject additionalData = new JsonObject();
551         additionalData.add("operationResult", new JsonObject());
552         scaleOperation.setAdditionalData(additionalData);
553         scaleOperation.setStatus(OperationStatus.FINISHED);
554         scaleOperation.setOperationType(OperationType.SCALE);
555         JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}");
556         JsonObject operationParams = new JsonObject();
557         //when
558         try {
559             lifecycleChangeNotificationManager.handleLcn(recievedLcn);
560             fail();
561         } catch (Exception e) {
562             assertEquals("All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure", e.getMessage());
563         }
564     }
565
566     private JsonObject buildTerminationParams() {
567         JsonObject root = new JsonObject();
568         root.add("terminationType", new JsonPrimitive("GRACEFULL"));
569         return root;
570     }
571
572     private OperationExecution buildOperation(OffsetDateTime baseTime, OperationType operationType) {
573         OperationExecution operation = new OperationExecution();
574         operation.setStartTime(baseTime);
575         operation.setOperationType(operationType);
576         return operation;
577     }
578
579     class OperationResult {
580         ReportedAffectedConnectionPoints operationResult;
581     }
582
583 }