Create Service Info file for assertion on Cypress and API test
[vid.git] / vid-automation / src / test / java / org / onap / vid / api / InstantiationTemplatesApiTest.java
1 package org.onap.vid.api;
2
3 import static java.util.Arrays.stream;
4 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
5 import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals;
6 import static net.javacrumbs.jsonunit.core.Option.IGNORING_VALUES;
7 import static org.hamcrest.MatcherAssert.assertThat;
8 import static org.hamcrest.Matchers.allOf;
9 import static org.hamcrest.Matchers.arrayWithSize;
10 import static org.hamcrest.Matchers.greaterThan;
11 import static org.onap.vid.api.TestUtils.convertRequest;
12 import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset;
13
14 import com.fasterxml.jackson.databind.JsonNode;
15 import com.fasterxml.jackson.databind.node.ObjectNode;
16 import com.google.common.collect.ImmutableMap;
17 import java.io.IOException;
18 import java.util.Map.Entry;
19 import java.util.function.Predicate;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22 import org.apache.commons.lang3.exception.ExceptionUtils;
23 import org.onap.sdc.ci.tests.datatypes.UserCredentials;
24 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
25 import org.onap.vid.model.mso.MsoResponseWrapper2;
26 import org.springframework.core.ParameterizedTypeReference;
27 import org.springframework.http.HttpEntity;
28 import org.springframework.http.HttpMethod;
29 import org.testng.annotations.AfterMethod;
30 import org.testng.annotations.BeforeMethod;
31 import org.testng.annotations.Test;
32 import vid.automation.test.Constants.Users;
33 import vid.automation.test.infra.FeatureTogglingTest;
34 import vid.automation.test.infra.Features;
35 import vid.automation.test.model.User;
36 import vid.automation.test.services.AsyncJobsService;
37 import vid.automation.test.services.SimulatorApi.RegistrationStrategy;
38
39 public class InstantiationTemplatesApiTest extends AsyncInstantiationBase {
40
41     /*
42     Testing the Template Topology API should be very thin, given the following
43     assumptions:
44
45       - Template topology API is relying on Retry's logic.
46
47       - The templates themselves are an actual representation of the initial
48         state in VID's backend. This is all the knowledge that used to create
49         a service in the first time. So if API is fed with same state, it already
50         should be able to reiterate another instance.
51
52
53     The tests below will verify that:
54
55       - A request resulting from Cypress test on "instantiation-templates.e2e.ts"
56         is accepted by API endpoint
57
58       - A valid "regular" (not from template) request, yields a template that a
59         Cypress is able to deploy.
60
61       These two tests are, technically,  cyclic.
62
63       Currently the only test below is shortcutting the both tests, by checking
64       that feeding a Cypress input yields a Template that is the same. This is
65       not perfect, but currently what we have.
66
67      */
68
69     @Override
70     public UserCredentials getUserCredentials() {
71         User user = usersService.getUser(Users.SILVIA_ROBBINS_TYLER_SILVIA);
72         return new UserCredentials(user.credentials.userId, user.credentials.password, Users.SILVIA_ROBBINS_TYLER_SILVIA, "", "");
73     }
74
75     @BeforeMethod
76     public void setUp() {
77         registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), RegistrationStrategy.CLEAR_THEN_SET);
78     }
79
80     @AfterMethod
81     protected void dropAllFromNameCounter() {
82         AsyncJobsService asyncJobsService = new AsyncJobsService();
83         asyncJobsService.muteAllAsyncJobs();
84         asyncJobsService.dropAllFromNameCounter();
85     }
86
87     protected String templateTopologyUri(String jobId) {
88         return uri.toASCIIString() + "/instantiationTemplates/templateTopology/" + jobId;
89     }
90
91     @Test
92     public void templateTopology_givenDeployFromCypressE2E_getTemplateTopologyDataIsEquivalent() {
93         templateTopology_givenDeploy_templateTopologyIsEquivalentToBody(
94             fileAsJsonNode("asyncInstantiation/templates__instance_template.json"));
95     }
96
97     @Test
98     public void templateTopology_givenDeployFromEditedTemplateCypressE2E_getTemplateTopologyDataIsEquivalentToOriginalTemplate() {
99         templateTopology_givenDeploy_templateTopologyIsEquivalent(
100             fileAsJsonNode("asyncInstantiation/templates__instance_from_template__set_without_modify1.json"),
101             fileAsJsonNode("asyncInstantiation/templates__instance_template.json"));
102     }
103
104     private ObjectNode templateInfoFromFile() {
105         return fileAsJsonNode("asyncInstantiation/vidRequestCreateBulkOfMacro__template_info.json");
106     }
107
108     @Test
109     public void templateTopology_givenDeploy_OriginalTemplateNotChanged() {
110         String uuidOriginTemplate = postAsyncInstanceRequest(fileAsJsonNode("asyncInstantiation/templates__instance_template.json"));
111         JsonNode originTemplateBeforeDeploy = restTemplate.getForObject(templateTopologyUri(uuidOriginTemplate), JsonNode.class);
112
113         ObjectNode changedNode = originTemplateBeforeDeploy.deepCopy();
114         changedNode.put("instanceName", "Cloned_Node_Instance_Name");
115         postAsyncInstanceRequest(changedNode);
116
117         JsonNode originTemplateAfterDeploy = restTemplate.getForObject(templateTopologyUri(uuidOriginTemplate), JsonNode.class);
118         assertThat(cleanupTemplate(originTemplateBeforeDeploy), jsonEquals(cleanupTemplate(originTemplateAfterDeploy)));
119
120     }
121
122     @Test
123     @FeatureTogglingTest(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)
124     public void templateTopology_givenDeploy_getServiceInfoHoldsRequestSummary() {
125         ObjectNode request =
126             fileAsJsonNode(CREATE_BULK_OF_MACRO_REQUEST)
127                 .put("bulkSize", 1)
128                 .put("pause", false);
129
130         String jobId = postAsyncInstanceRequest(request);
131
132         assertThat(fetchRecentTemplateInfo(request.at("/modelInfo/modelVersionId").asText()), allOf(
133             jsonPartEquals("jobId", jobId),
134             jsonPartEquals("requestSummary", ImmutableMap.of(
135                 "vnf", 1L,
136                 "vfModule", 2L,
137                 "volumeGroup", 1L
138             ))));
139     }
140
141     @Test
142     @FeatureTogglingTest(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)
143     public void templateTopology_givenDeploy_getServiceInfoReturnsCypressE2EFile() {
144         ObjectNode request =
145             fileAsJsonNode(CREATE_BULK_OF_MACRO_REQUEST)
146                 .put("bulkSize", 1)
147                 .put("pause", false);
148
149         String jobId = postAsyncInstanceRequest(request);
150
151         assertThat(fetchRecentTemplateInfo(request.at("/modelInfo/modelVersionId").asText()), allOf(
152             jsonPartEquals("jobId", jobId),
153             jsonEquals(templateInfoFromFile()).when(IGNORING_VALUES), // Assert only field types
154             jsonEquals(templateInfoFromFile()).whenIgnoringPaths(
155                 // Ignore the fields where values are always changing
156                 "id", "templateId", "jobId",
157                 "created", "createdBulkDate",
158                 "modified", "statusModifiedDate",
159                 "jobStatus"
160             )));
161     }
162
163     private JsonNode fetchRecentTemplateInfo(String serviceModelId) {
164         return stream(restTemplate.getForObject(getTemplateInfoUrl(serviceModelId), JsonNode[].class))
165             .findFirst()
166             .orElseGet(() -> {
167                 throw new AssertionError(getTemplateInfoUrl(serviceModelId) + " returned zero results");
168             });
169     }
170
171     private ObjectNode fileAsJsonNode(String fileName) {
172         try {
173             return objectMapper.readValue(
174                 convertRequest(objectMapper, fileName),
175                 ObjectNode.class);
176         } catch (IOException e) {
177             return ExceptionUtils.rethrow(e);
178         }
179     }
180
181     public void templateTopology_givenDeploy_templateTopologyIsEquivalentToBody(JsonNode body) {
182         templateTopology_givenDeploy_templateTopologyIsEquivalent(body, body);
183     }
184
185     public void templateTopology_givenDeploy_templateTopologyIsEquivalent(JsonNode body, JsonNode expectedTemplateTopology) {
186         String uuid1 = postAsyncInstanceRequest(body);
187         JsonNode templateTopology1 = restTemplate.getForObject(templateTopologyUri(uuid1), JsonNode.class);
188
189         assertThat(cleanupTemplate(templateTopology1), jsonEquals(cleanupTemplate(expectedTemplateTopology)));
190     }
191
192     private JsonNode cleanupTemplate(JsonNode templateTopology) {
193         return Stream.of(templateTopology)
194             .map(this::removeTrackById)
195             .map(this::removeNullValues)
196             .findAny().get();
197     }
198
199     private JsonNode removeTrackById(JsonNode node) {
200         return removeAny(node, it -> it.getKey().equals("trackById"));
201     }
202
203     private JsonNode removeNullValues(JsonNode node) {
204         return removeAny(node, it -> it.getValue().isNull());
205     }
206
207     private JsonNode removeAny(JsonNode node, Predicate<Entry<String, JsonNode>> entryPredicate) {
208         if (node.isObject()) {
209             ((ObjectNode) node).remove(
210                 Streams.fromIterator(node.fields())
211                     .filter(entryPredicate)
212                     .map(Entry::getKey)
213                     .collect(Collectors.toList())
214             );
215
216             for (JsonNode child : node) {
217                 removeAny(child, entryPredicate);
218             }
219         }
220
221         return node;
222     }
223
224     private <T> String postAsyncInstanceRequest(T body) {
225         String[] jobsUuids = (String[]) restTemplate.exchange(
226             getCreateBulkUri(),
227             HttpMethod.POST,
228             new HttpEntity<>(body),
229             new ParameterizedTypeReference<MsoResponseWrapper2<String[]>>() {
230             })
231             .getBody().getEntity();
232
233         assertThat(jobsUuids, arrayWithSize(greaterThan(0)));
234         return jobsUuids[0];
235     }
236
237 }