Merge automation from ECOMP's repository
[vid.git] / vid-automation / src / test / java / org / onap / vid / api / AsyncInstantiationApiTest.java
1 package org.onap.vid.api;
2
3 import com.google.common.collect.ImmutableList;
4 import net.bytebuddy.utility.RandomString;
5 import net.javacrumbs.jsonunit.JsonAssert;
6 import org.apache.commons.lang3.StringUtils;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9 import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset;
10 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId;
11 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
12 import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet;
13 import org.onap.simulator.presetGenerator.presets.mso.*;
14 import org.onap.vid.model.asyncInstantiation.JobAuditStatus;
15 import org.onap.vid.model.asyncInstantiation.ServiceInfo;
16 import org.onap.sdc.ci.tests.datatypes.UserCredentials;
17 import org.springframework.http.HttpStatus;
18 import org.springframework.web.client.HttpClientErrorException;
19 import org.springframework.web.client.HttpServerErrorException;
20 import org.testng.Assert;
21 import org.testng.annotations.DataProvider;
22 import org.testng.annotations.Test;
23 import vid.automation.test.infra.FeatureTogglingTest;
24 import vid.automation.test.infra.Features;
25 import vid.automation.test.infra.Wait;
26 import vid.automation.test.model.JobStatus;
27 import vid.automation.test.services.SimulatorApi;
28
29 import java.util.*;
30 import java.util.concurrent.atomic.AtomicReference;
31 import java.util.stream.IntStream;
32 import java.util.stream.Stream;
33
34 import static java.util.stream.Collectors.*;
35 import static org.hamcrest.CoreMatchers.*;
36 import static org.hamcrest.MatcherAssert.assertThat;
37 import static org.hamcrest.Matchers.hasSize;
38 import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys;
39 import static org.testng.AssertJUnit.assertEquals;
40 import static org.testng.AssertJUnit.assertTrue;
41 import static vid.automation.test.infra.Features.FLAG_1906_INSTANTIATION_API_USER_VALIDATION;
42 import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection;
43
44 @FeatureTogglingTest({Features.FLAG_ASYNC_JOBS, Features.FLAG_ASYNC_INSTANTIATION})
45 public class AsyncInstantiationApiTest extends AsyncInstantiationBase {
46     private static final Logger logger = LogManager.getLogger(AsyncInstantiationApiTest.class);
47
48     private static final String MSO_BASE_ERROR =
49             "Received error from SDN-C: java.lang.IllegalArgumentException: All keys must be specified for class org."+
50             "opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vf.module.assignments.vf."+
51             "module.assignments.vms.VmKey. Missing key is getVmType. Supplied key is VmKey [].";
52     private static final String MSO_ERROR = MSO_BASE_ERROR + StringUtils.repeat(" and a lot of sentences for long message", 60);
53
54     private static final String INSTANCE_GROUP_ID_LABEL = "instanceGroupId";
55
56     private static final String INSTANCE_GROUP_LABEL = "instanceGroup";
57
58     @Test
59     public void createBulkOfCreateInstances(){
60         Map<Keys, String> names = generateNames();
61         final int bulkSize = 3;
62         ImmutableList<BasePreset> presets = addPresetsForCreateBulkOfCreateInstances(bulkSize, names);
63         createBulkOfInstancesAndAssert(presets, false, bulkSize, JobStatus.COMPLETED, names);
64     }
65
66     @Test(dataProvider = "auditSources")
67    public void getAuditStatus_nonExistingJobId_returnsEmptyList(JobAuditStatus.SourceStatus source){
68        List<JobAuditStatus> audits = getAuditStatuses(UUID.randomUUID().toString(), source.name());
69        Assert.assertEquals(audits.size(),0);
70    }
71
72     @Test(expectedExceptions = HttpClientErrorException.class)
73     public void getAuditStatus_nonExistingSource_returnsError() {
74         try {
75             getAuditStatuses(UUID.randomUUID().toString(), new RandomString(8).nextString());
76         } catch (HttpClientErrorException e) {
77             Assert.assertEquals(e.getResponseBodyAsString(),"The parameter source must have a value among : MSO, VID");
78             assertThat(e.getStatusCode(), is(HttpStatus.BAD_REQUEST));
79             throw e;
80         }
81     }
82
83     @Test()
84     public void simulateBulkRequest_getAuditStatus_auditStatusesReturnedAccordingSource() {
85         final int bulkSize = 2;
86         final List<String> jobIds = createBulkAndWaitForBeCompleted(bulkSize);
87
88         for(String jobId: jobIds) {
89             List<JobAuditStatus> actualVidAudits = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.VID.name());
90             List<JobAuditStatus> expectedVidAudits = Stream.of(JobStatus.PENDING, JobStatus.IN_PROGRESS, JobStatus.COMPLETED)
91                     .map(status-> vidAuditStatus(jobId, status.name(), status.equals(JobStatus.COMPLETED))).collect(toList());
92             assertThat(actualVidAudits, hasItemsFromCollection(expectedVidAudits));
93
94             List<JobAuditStatus> actualMsoAudits = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name());
95             List<JobAuditStatus> expectedMsoAudits = Stream.of("REQUESTED", "COMPLETE")
96                     .map(status-> new JobAuditStatus(UUID.fromString(jobId),
97                             status,
98                             JobAuditStatus.SourceStatus.MSO,
99                             UUID.fromString("c0011670-0e1a-4b74-945d-8bf5aede1d9c"),
100                             status.equals("COMPLETE") ? "Service Instance was created successfully." : null,
101                             false)).collect(toList());
102             assertThat(actualMsoAudits, is(expectedMsoAudits));
103         }
104     }
105
106
107     @Test(expectedExceptions = HttpClientErrorException.class)
108     public void addBulkAndDeleteInProgress_deletionIsRejected(){
109         try {
110             final Map<String, JobStatus> jobs = addBulkAllPendingButOneInProgress();
111             deleteOneJobHavingTheStatus(jobs, JobStatus.IN_PROGRESS);
112         } catch (HttpClientErrorException e) {
113             JsonAssert.assertJsonPartEquals(
114                     "Service status does not allow deletion from the queue (Request id: null)",
115                     e.getResponseBodyAsString(),
116                     "message"
117             );
118             assertThat(e.getStatusCode(), is(HttpStatus.METHOD_NOT_ALLOWED));
119
120             throw e;
121         }
122     }
123
124     @Test
125     public void addBulkAndDeletePending_deletedIsHiddenFromServiceInfoResults(){
126         Map<String, JobStatus> statusesBefore = addBulkAllPendingButOneInProgress();
127
128         final String deletedJob = deleteOneJobHavingTheStatus(statusesBefore, JobStatus.PENDING);
129
130         final Map<String, JobStatus> statusesNow = serviceListCall().getBody().stream()
131                 .filter(si -> statusesBefore.keySet().contains(si.jobId))
132                 .collect(toMap(si -> si.jobId, si -> si.jobStatus));
133
134         statusesBefore.remove(deletedJob);
135         assertThat("deleted job shall not be present in StatusInfo response", statusesNow, is(statusesBefore));
136     }
137
138     @Test(invocationCount = 3)
139     public void createBulkOfCreateInstancesWithSinglePreset_firstOneInProgressOtherArePending(){
140         final int bulkSize = 3;
141         Map<String, JobStatus> statusMap = addBulkAllPendingButOneInProgress(bulkSize);
142         Set<String> jobIds = statusMap.keySet();
143
144         final Map<JobStatus, List<ServiceInfo>> statuses = serviceListCall().getBody().stream()
145                 .filter(si -> jobIds.contains(si.jobId))
146                 .collect(groupingBy(ServiceInfo::getJobStatus));
147
148         // Variable "statuses" contains two lists by status:
149         // IN_PROGRESS:  The ultimate first job - named with _001 - is always the only one in progress
150         // PENDING:      The other two jobs - named with _002 and _003 - are the still pending
151         assertThat(jobIds, hasSize(bulkSize));
152         assertThat(statuses.get(JobStatus.IN_PROGRESS), hasSize(1));
153
154         assertThat(statuses.get(JobStatus.PENDING), hasSize(bulkSize - 1));
155     }
156
157
158     @Test(dataProvider = "trueAndFalse" )
159     public void whenServiceInBulkFailed_otherServicesAreStopped(Boolean isPresetForCreate){
160         Map<Keys, String> names = generateNames();
161         final int bulkSize = 3;
162
163         //if there is a preset for create,  service shall failed during in_progress (upon get status)
164         //it there is no preset for create, service shall failed during pending (upon create request)
165         List<BasePreset> msoBulkPresets = isPresetForCreate ?
166                 generateMsoCreateBulkPresets(bulkSize, names) :
167                 new LinkedList<>();
168         ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
169                 .add(new PresetGetSessionSlotCheckIntervalGet())
170                 .add(new PresetAAIGetSubscribersGet())
171                 .add(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN3_TO_ATT_SABABA)
172                 .addAll(msoBulkPresets)
173                 .add(new PresetMSOOrchestrationRequestGet("FAILED"))
174                 .build();
175         List<String> jobIds = createBulkOfMacroInstances(presets, false, bulkSize, names);
176         Assert.assertEquals(jobIds.size(),bulkSize);
177         boolean result = Wait.waitFor(x->{
178                 List<ServiceInfo> serviceInfoList = serviceListCall().getBody();
179                 Map<JobStatus, Long> statusCount = serviceInfoList.stream().filter(si->jobIds.contains(si.jobId)).collect(groupingBy(ServiceInfo::getJobStatus, counting()));
180                 return Objects.equals(statusCount.get(JobStatus.FAILED), 1L) && Objects.equals(statusCount.get(JobStatus.STOPPED), 2L);
181             }, null, 15, 1);
182         assertTrue(String.format("failed to get jobs [%s] to state of: 1 failed and 2 stopped ",
183                 String.join(",", jobIds)),result);
184     }
185
186     @Test
187     public void createBulkOfAssignInstances(){
188         Map<Keys, String> names = generateNames();
189         final int bulkSize = 2;
190         ImmutableList<BasePreset> msoBulkPresets = IntStream.rangeClosed(0, bulkSize-1)
191                 .mapToObj(i-> new PresetMSOAssignServiceInstanceGen2WithNames(names, i))
192                 .collect(ImmutableList.toImmutableList());
193         ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
194                 .add(new PresetGetSessionSlotCheckIntervalGet())
195                 .add(new PresetAAIGetSubscribersGet())
196                 .add(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN3_TO_ATT_SABABA)
197                 .addAll(msoBulkPresets)
198                 .add(new PresetMSOOrchestrationRequestGet())
199                 .build();
200         createBulkOfInstancesAndAssert(presets, true, bulkSize, JobStatus.COMPLETED, names);
201     }  
202
203     @Test
204     public void tryToCreateBulkOfAssignInstancesErrorResponseFromMso(){
205         ImmutableList<BasePreset> presets = ImmutableList.of(
206                 new PresetGetSessionSlotCheckIntervalGet(),
207                 new PresetAAIGetSubscribersGet(),
208                 new PresetMSOServiceInstanceGen2ErrorResponse(406));
209
210         List<String> jobIds = createBulkOfInstancesAndAssert(presets, true,1, JobStatus.FAILED, generateNames());
211         String jobId  = jobIds.get(0);
212         List<JobAuditStatus> actualMsoAudits = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name());
213         JobAuditStatus expectedMsoAudit = new JobAuditStatus(UUID.fromString(jobId), "FAILED", JobAuditStatus.SourceStatus.MSO,
214                         null,
215                         "Http Code:406, \"messageId\":\"SVC0002\",\"text\":\"JSON Object Mapping Request\"" ,
216                         false);
217         assertThat(actualMsoAudits.get(0), is(expectedMsoAudit));
218     }
219
220     @Test
221     public void whenGetLongErrorMessageFromMso_ThenAuditFirst2000Chars() {
222         Map<Keys, String> names = generateNames();
223         ImmutableList<BasePreset> presets = ImmutableList.of(
224                 new PresetGetSessionSlotCheckIntervalGet(),
225                 new PresetAAIGetSubscribersGet(),
226                 new PresetMSOCreateServiceInstanceGen2WithNames(names, 0),
227                 new PresetMSOOrchestrationRequestGet("FAILED", PresetMSOOrchestrationRequestGet.DEFAULT_REQUEST_ID, MSO_ERROR));
228
229         List<String> jobIds = createBulkOfInstancesAndAssert(presets, false, 1, JobStatus.FAILED, names);
230         String jobId  = jobIds.get(0);
231         List<JobAuditStatus> actualMsoAudits = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name());
232         Optional<JobAuditStatus> jobAuditStatus = actualMsoAudits.stream().filter(x -> x.getJobStatus().equals("FAILED")).findFirst();
233         assertTrue(jobAuditStatus.isPresent());
234         assertThat(jobAuditStatus.get().getAdditionalInfo(), startsWith(MSO_BASE_ERROR));
235         assertThat(jobAuditStatus.get().getAdditionalInfo().length(), is(2000));
236     }
237
238     @Test
239     public void whenHideCompletedService_thenServiceNotReturnInServiceList(){
240         List<String> services = createBulkAndWaitForBeCompleted(2);
241         hideService(services.get(0));
242         List<String> serviceInfoList = serviceListCall().getBody().stream().map(ServiceInfo::getJobId).collect(toList());
243         assertThat(serviceInfoList, hasItem(services.get(1)));
244         assertThat(serviceInfoList, not(hasItem(services.get(0))));
245     }
246
247     @Test
248     public void errorResponseInGetStatusFromMso_getAuditStatusFromMso_errorMsgExistInAdditionalInfo(){
249         Map<Keys, String> names = generateNames();
250         ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
251                 .add(new PresetGetSessionSlotCheckIntervalGet())
252                 .add(new PresetAAIGetSubscribersGet())
253                 .add(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN3_TO_ATT_SABABA)
254                 .add(new PresetMSOAssignServiceInstanceGen2WithNames(names, 0))
255                 .add(new PresetMSOOrchestrationRequestGetErrorResponse(406))
256                 .build();
257
258         final List<String> jobIds = createBulkOfInstancesAndAssert(presets, true,1, JobStatus.IN_PROGRESS, names);
259         String jobId = jobIds.get(0);
260         Wait.waitFor(y-> getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name()).stream()
261                         .anyMatch(si -> si.getJobStatus().equals("FAILED")),
262                 null, 10, 1 );
263         List<JobAuditStatus> actualMsoAudits = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name());
264         List<JobAuditStatus> expectedMsoAudits = Stream.of("REQUESTED", "FAILED")
265                 .map(status -> new JobAuditStatus(UUID.fromString(jobId),
266                         status,
267                         JobAuditStatus.SourceStatus.MSO,
268                         UUID.fromString("c0011670-0e1a-4b74-945d-8bf5aede1d9c"),
269                         status.equals("FAILED") ? "Http Code:406, \"messageId\":\"SVC0002\",\"text\":\"JSON Object Mapping Request\"" : null,
270                         false)).collect(toList());
271         assertThat(actualMsoAudits, is(expectedMsoAudits));
272
273     }
274
275     @Test
276     public void inProgressJobMoreThan24HoursIsFailedInVidAudit(){
277         addBulkPendingWithCustomList(Collections.singletonList(new PresetMSOOrchestrationRequestGet("IN_PROGRESS",24)));
278
279         AtomicReference<ServiceInfo> inProgressJob = new AtomicReference<>();
280         boolean isJobFound = Wait.waitFor(x->{
281             List<ServiceInfo> serviceInfoList = serviceListCall().getBody();
282             inProgressJob.set(serviceInfoList.stream().
283                     filter(serviceInfo -> serviceInfo.serviceInstanceId.equals(PresetMSOOrchestrationRequestGet.DEFAULT_SERVICE_INSTANCE_ID) && serviceInfo.jobStatus.equals(JobStatus.FAILED))
284                     .findFirst()
285                     .orElse(null));
286             return inProgressJob.get() != null;
287         }, null, 15, 1);
288
289         org.junit.Assert.assertTrue("Job with DEFAULT_SERVICE_INSTANCE_ID and status FAILED should present", isJobFound);
290
291         verifyAuditStatuses(inProgressJob.get().jobId, Arrays.asList(JobStatus.PENDING.name(), JobStatus.IN_PROGRESS.name(),JobStatus.FAILED.name()), JobAuditStatus.SourceStatus.VID);
292         verifyAuditStatuses(inProgressJob.get().jobId, Arrays.asList("REQUESTED", "IN_PROGRESS"), JobAuditStatus.SourceStatus.MSO);
293     }
294
295     @Test
296     public void inProgressJobLessThan24HoursIsStillInProgressInVidAudit(){
297         addBulkPendingWithCustomList(Collections.singletonList(new PresetMSOOrchestrationRequestGet("IN_PROGRESS",23)));
298
299         AtomicReference<ServiceInfo> inProgressJob = new AtomicReference<>();
300         boolean isJobFound = Wait.waitFor(x->{
301             List<ServiceInfo> serviceInfoList = serviceListCall().getBody();
302             inProgressJob.set(serviceInfoList.stream().filter(serviceInfo -> serviceInfo.serviceInstanceId.equals(PresetMSOOrchestrationRequestGet.DEFAULT_SERVICE_INSTANCE_ID))
303                     .findFirst()
304                     .orElse(null));
305             return inProgressJob.get() != null;
306         }, null, 15, 1);
307
308         org.junit.Assert.assertTrue("Job with DEFAULT_SERVICE_INSTANCE_ID should present", isJobFound);
309         org.junit.Assert.assertEquals("Tested job status is not as expected", JobStatus.IN_PROGRESS, inProgressJob.get().getJobStatus());
310
311         verifyAuditStatuses(inProgressJob.get().jobId, Arrays.asList(JobStatus.PENDING.name(), JobStatus.IN_PROGRESS.name()), JobAuditStatus.SourceStatus.VID);
312         verifyAuditStatuses(inProgressJob.get().jobId, Arrays.asList("REQUESTED", "IN_PROGRESS"), JobAuditStatus.SourceStatus.MSO);
313     }
314
315     @Test
316     public void verifyAuditStatusOfInstanceGroupId(){
317         SimulatorApi.registerExpectationFromPreset(new PresetMSOOrchestrationRequestsManyInstanceStatusesGet(INSTANCE_GROUP_ID_LABEL, INSTANCE_GROUP_LABEL), SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
318         final List<JobAuditStatus> expectedAuditStatusList = getAuditStatusesForInstance("VNFGROUP", "df305d54-75b4-431b-adb2-eb6b9e5460df");
319         verifyInstanceAuditStatuses(Arrays.asList(
320                 new JobAuditStatus("groupTestName", "IN_PROGRESS", UUID.fromString("28502bd2-3aff-4a03-9f2b-5a0d1cb1ca24") , INSTANCE_GROUP_LABEL+" instance creation", null, INSTANCE_GROUP_LABEL),
321                 new JobAuditStatus("groupTestName", "COMPLETE",UUID.fromString("28502bd2-3aff-4a03-9f2b-5a0d1cb1ca24") , INSTANCE_GROUP_LABEL+" instance creation", null, INSTANCE_GROUP_LABEL),
322                 new JobAuditStatus("groupTestName", "IN_PROGRESS", UUID.fromString("f711f0ff-24b6-4d7f-9314-4b4eae15f48c") , INSTANCE_GROUP_LABEL+" instance deletion", null, INSTANCE_GROUP_LABEL),
323                 new JobAuditStatus("groupTestName", "COMPLETE",UUID.fromString("f711f0ff-24b6-4d7f-9314-4b4eae15f48c")  , INSTANCE_GROUP_LABEL+" instance deletion", null, INSTANCE_GROUP_LABEL)),
324                 expectedAuditStatusList);
325     }
326
327     @Test(expectedExceptions = HttpClientErrorException.class)
328     public void verifyAuditStatusOfInstanceGroupId_notExistingVidType(){
329         try {
330             getAuditStatusesForInstance("KUKU", "df305d54-75b4-431b-adb2-eb6b9e5460df");
331         } catch (HttpClientErrorException e){ //to verify the properiatary statusCode field
332             assertThat("Code is not as expected", HttpStatus.BAD_REQUEST.equals(e.getStatusCode()));
333             throw e;
334         }
335     }
336
337     @Test(expectedExceptions = HttpServerErrorException.class)
338     public void verifyAuditStatusOfInstanceGroupId_notExistingMsoInstanceId(){
339         try {
340             getAuditStatusesForInstance("VNFGROUP", "df305d54-75b4-431b-adb2-eb6b9e5460aa");
341         } catch (HttpServerErrorException e){ //to verify the properiatary statusCode field
342             assertThat("Code is not as expected", HttpStatus.INTERNAL_SERVER_ERROR.equals(e.getStatusCode()));
343             throw e;
344         }
345     }
346
347     @DataProvider
348     public static Object[][] macroAndALaCarteBulk(){
349         return new Object[][]{{CREATE_BULK_OF_MACRO_REQUEST}, {CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF}};
350     }
351
352     @Test(dataProvider = "macroAndALaCarteBulk", expectedExceptions = HttpClientErrorException.class)
353     @FeatureTogglingTest(FLAG_1906_INSTANTIATION_API_USER_VALIDATION)
354     public void verifyCreateBulkOfInstancesUserPermissionValidation(String requestDetailsFileName) {
355         login(new UserCredentials("mo57174000", "mo57174000", null, null, null));
356         try {
357             createBulkOfInstances(false, 1, Collections.EMPTY_MAP, requestDetailsFileName);
358         } catch (HttpClientErrorException e){
359             assertEquals("Code is not as expected", HttpStatus.FORBIDDEN.value(), e.getStatusCode().value());
360             throw e;
361         }
362         finally {
363             login();
364         }
365
366     }
367
368 }