Unique identifier for test execution
[sdc.git] / openecomp-be / lib / openecomp-sdc-externaltesting-lib / openecomp-sdc-externaltesting-impl / src / test / java / org / openecomp / core / externaltesting / impl / ExternalTestingManagerImplTest.java
1 /*
2  * Copyright © 2019 iconectiv
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
17 package org.openecomp.core.externaltesting.impl;
18
19 import com.fasterxml.jackson.core.type.TypeReference;
20 import com.fasterxml.jackson.databind.ObjectMapper;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.IOException;
24 import java.nio.charset.Charset;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.UUID;
31 import org.apache.commons.io.FileUtils;
32 import org.apache.commons.io.IOUtils;
33 import org.apache.commons.lang3.tuple.Pair;
34 import org.junit.Assert;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.mockito.ArgumentMatchers;
39 import org.mockito.InjectMocks;
40 import org.mockito.Mock;
41 import org.mockito.Mockito;
42 import org.mockito.MockitoAnnotations;
43 import org.mockito.junit.MockitoJUnitRunner;
44 import org.openecomp.core.externaltesting.api.ClientConfiguration;
45 import org.openecomp.core.externaltesting.api.ExternalTestingManager;
46 import org.openecomp.core.externaltesting.api.RemoteTestingEndpointDefinition;
47 import org.openecomp.core.externaltesting.api.TestTreeNode;
48 import org.openecomp.core.externaltesting.api.VtpNameDescriptionPair;
49 import org.openecomp.core.externaltesting.api.VtpTestCase;
50 import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest;
51 import org.openecomp.core.externaltesting.api.VtpTestExecutionResponse;
52 import org.openecomp.core.externaltesting.errors.ExternalTestingException;
53 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
54 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
55 import org.openecomp.sdc.versioning.VersioningManager;
56 import org.openecomp.sdc.versioning.dao.types.Version;
57 import org.springframework.core.ParameterizedTypeReference;
58 import org.springframework.http.HttpHeaders;
59 import org.springframework.http.HttpMethod;
60 import org.springframework.http.HttpStatus;
61 import org.springframework.http.MediaType;
62 import org.springframework.http.ResponseEntity;
63 import org.springframework.util.LinkedMultiValueMap;
64 import org.springframework.web.client.HttpServerErrorException;
65 import org.springframework.web.client.HttpStatusCodeException;
66 import org.springframework.web.client.ResourceAccessException;
67 import org.springframework.web.client.RestTemplate;
68
69 @RunWith(MockitoJUnitRunner.class)
70 public class ExternalTestingManagerImplTest {
71
72   @Mock
73   private RestTemplate restTemplate;
74
75   @Mock
76   private VersioningManager versioningManager;
77
78   @Mock
79   private VendorSoftwareProductManager vendorSoftwareProductManager;
80
81   @Mock
82   private OrchestrationTemplateCandidateManager candidateManager;
83
84   @InjectMocks
85   private ExternalTestingManagerImpl mgr = new ExternalTestingManagerImpl();
86
87   @SuppressWarnings("unchecked")
88   private ExternalTestingManagerImpl configTestManager(boolean loadConfig) throws IOException {
89
90     MockitoAnnotations.initMocks(this);
91
92     if (loadConfig) {
93       mgr.init();
94     }
95
96     ObjectMapper mapper = new ObjectMapper();
97
98     // read mock data for API calls.
99
100     File scenarioFile = new File("src/test/data/scenarios.json");
101     TypeReference<List<VtpNameDescriptionPair>> typ = new TypeReference<List<VtpNameDescriptionPair>>() { };
102     List<VtpNameDescriptionPair> scenarios = mapper.readValue(scenarioFile, typ);
103
104     File testSuitesFile = new File("src/test/data/testsuites.json");
105     List<VtpNameDescriptionPair> testSuites =
106             mapper.readValue(testSuitesFile, new TypeReference<List<VtpNameDescriptionPair>>() { });
107
108     File testCasesFile = new File("src/test/data/testcases.json");
109     List<VtpTestCase> testCases = mapper.readValue(testCasesFile, new TypeReference<List<VtpTestCase>>() { });
110
111     File testCaseFile = new File("src/test/data/testcase-sriov.json");
112     VtpTestCase testCase = mapper.readValue(testCaseFile, VtpTestCase.class);
113
114     File runResultFile = new File("src/test/data/runresult.json");
115     List<VtpTestExecutionResponse> runResults =
116             mapper.readValue(runResultFile, new TypeReference<List<VtpTestExecutionResponse>>() { });
117
118     File priorExecutionFile = new File("src/test/data/priorexecution.json");
119     VtpTestExecutionResponse priorExecution = mapper.readValue(priorExecutionFile, VtpTestExecutionResponse.class);
120
121     // create an error response as well
122     String notFound = FileUtils.readFileToString(new File("src/test/data/notfound.json"), "UTF-8");
123
124     ParameterizedTypeReference<List<VtpNameDescriptionPair>> listOfPairType =
125             new ParameterizedTypeReference<List<VtpNameDescriptionPair>>() { };
126     ParameterizedTypeReference<List<VtpTestCase>> listOfCasesType =
127             new ParameterizedTypeReference<List<VtpTestCase>>() { };
128     ParameterizedTypeReference<VtpTestCase> caseType = new ParameterizedTypeReference<VtpTestCase>() { };
129
130     HttpHeaders headers = new HttpHeaders();
131     headers.setContentType(MediaType.parseMediaType("application/problem+json"));
132
133     byte[] csar = IOUtils.toByteArray(new FileInputStream("src/test/data/csar.zip"));
134     byte[] heat = IOUtils.toByteArray(new FileInputStream("src/test/data/heat.zip"));
135
136     List<Version> versionList = new ArrayList<>();
137     versionList.add(new Version(UUID.randomUUID().toString()));
138
139     Mockito.when(candidateManager.get(ArgumentMatchers.contains("csar"), ArgumentMatchers.any()))
140             .thenReturn(Optional.of(Pair.of("Processed.zip", csar)));
141
142     Mockito.when(candidateManager.get(ArgumentMatchers.contains("heat"), ArgumentMatchers.any()))
143             .thenReturn(Optional.empty());
144
145     Mockito.when(vendorSoftwareProductManager.get(ArgumentMatchers.contains("heat"), ArgumentMatchers.any()))
146             .thenReturn(Optional.of(Pair.of("Processed.zip", heat)));
147
148
149     Mockito.when(vendorSoftwareProductManager.get(ArgumentMatchers.contains("missing"), ArgumentMatchers.any()))
150             .thenReturn(Optional.empty());
151
152     Mockito.when(candidateManager.get(ArgumentMatchers.contains("missing"), ArgumentMatchers.any()))
153             .thenReturn(Optional.empty());
154
155
156     Mockito.when(versioningManager.list(ArgumentMatchers.contains("missing"))).thenReturn(versionList);
157
158
159     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("/scenarios"), ArgumentMatchers.eq(HttpMethod.GET),
160             ArgumentMatchers.any(), ArgumentMatchers.eq(listOfPairType)))
161             .thenReturn(new ResponseEntity(scenarios, HttpStatus.OK));
162
163     Mockito.when(restTemplate
164                          .exchange(ArgumentMatchers.endsWith("/testsuites"), ArgumentMatchers.eq(HttpMethod.GET),
165                                  ArgumentMatchers.any(), ArgumentMatchers.eq(listOfPairType)))
166             .thenReturn(new ResponseEntity(testSuites, HttpStatus.OK));
167
168     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("/testcases"), ArgumentMatchers.eq(HttpMethod.GET),
169             ArgumentMatchers.any(), ArgumentMatchers.eq(listOfCasesType)))
170             .thenReturn(new ResponseEntity(testCases, HttpStatus.OK));
171
172     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("/sriov"), ArgumentMatchers.eq(HttpMethod.GET),
173             ArgumentMatchers.any(), ArgumentMatchers.eq(caseType)))
174             .thenReturn(new ResponseEntity(testCase, HttpStatus.OK));
175
176
177     // POST for execution
178
179     Mockito.when(restTemplate
180                          .exchange(ArgumentMatchers.contains("executions"), ArgumentMatchers.eq(HttpMethod.POST),
181                                  ArgumentMatchers.any(), ArgumentMatchers
182                                                                  .eq(new ParameterizedTypeReference<List<VtpTestExecutionResponse>>() { })))
183             .thenReturn(new ResponseEntity(runResults, HttpStatus.OK));
184
185
186     Mockito.when(restTemplate
187                          .exchange(ArgumentMatchers.contains("/executions/"), ArgumentMatchers.eq(HttpMethod.GET),
188                                  ArgumentMatchers.any(), ArgumentMatchers
189                                                                  .eq(new ParameterizedTypeReference<VtpTestExecutionResponse>() { })))
190             .thenReturn(new ResponseEntity(priorExecution, HttpStatus.OK));
191
192
193     HttpStatusCodeException missingException =
194             new HttpServerErrorException(HttpStatus.NOT_FOUND, "Not Found", headers, notFound.getBytes(),
195                     Charset.defaultCharset());
196     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("/missing"), ArgumentMatchers.eq(HttpMethod.GET),
197             ArgumentMatchers.any(), ArgumentMatchers.eq(caseType))).thenThrow(missingException);
198
199
200     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("/sitedown"), ArgumentMatchers.eq(HttpMethod.GET),
201             ArgumentMatchers.any(), ArgumentMatchers.eq(caseType)))
202             .thenThrow(new ResourceAccessException("Remote site is down"));
203
204     Mockito.when(restTemplate.exchange(ArgumentMatchers.endsWith("throwexception"),
205             ArgumentMatchers.eq(HttpMethod.POST), ArgumentMatchers.any(),
206             ArgumentMatchers.eq(new ParameterizedTypeReference<List<VtpTestExecutionResponse>>() { })))
207             .thenThrow(missingException);
208
209
210     return mgr;
211   }
212
213   @Before
214   public void setConfigLocation() {
215     System.setProperty("config.location", "src/test/data");
216   }
217
218   @Test
219   public void testManager() throws IOException {
220     ExternalTestingManager m = configTestManager(true);
221
222     ClientConfiguration config = m.getConfig();
223     Assert.assertNotNull(config);
224
225     List<RemoteTestingEndpointDefinition> endpoints = m.getEndpoints();
226     Assert.assertEquals("two endpoints", 2, endpoints.size());
227
228
229     // this will exercise the internal APIs as well.
230     TestTreeNode root = m.getTestCasesAsTree();
231     Assert.assertEquals("two scenarios", 2, root.getChildren().size());
232
233
234     // handle case where remote endpoint is down.
235     try {
236       m.getTestCase("repository", "scen", "suite", "sitedown");
237       Assert.fail("not expected to retrieve sitedown test case");
238     } catch (ExternalTestingException e) {
239       // expecting this exception.
240       Assert.assertNotNull(e.getDetail());
241       Assert.assertNotEquals(0, e.getHttpStatus());
242       Assert.assertNotNull(e.getMessageCode());
243     }
244
245     // get a particular test case
246     try {
247       m.getTestCase("repository", "scen", "suite", "missing");
248       Assert.fail("not expected to retrieve missing test case");
249     } catch (ExternalTestingException e) {
250       // expecting this exception.
251       Assert.assertNotNull(e.getDetail());
252       Assert.assertNotEquals(0, e.getHttpStatus());
253       Assert.assertNotNull(e.getMessageCode());
254     }
255   }
256
257   @Test
258   public void testManagerExecution() throws IOException {
259     ExternalTestingManager m = configTestManager(true);
260
261     // execute a test.
262     List<VtpTestExecutionRequest> requests = new ArrayList<>();
263     VtpTestExecutionRequest req = new VtpTestExecutionRequest();
264     req.setEndpoint("repository");
265     requests.add(req);
266
267     // send a request with the endpoint defined.
268     List<VtpTestExecutionResponse> responses = m.execute(requests, "vspId", "vspVersionId", "rid", null);
269     Assert.assertEquals(1, responses.size());
270
271     // send a request for a prior execution.
272     VtpTestExecutionResponse execRsp = m.getExecution("repository", "execId");
273     Assert.assertEquals("COMPLETE", execRsp.getStatus());
274   }
275
276   @Test
277   public void testMissingConfig() throws IOException {
278     // directory exists but no config file should be found here.
279     System.setProperty("config.location", "src/test");
280     ExternalTestingManager m = configTestManager(true);
281     Assert.assertFalse("missing config client enabled false", m.getConfig().isEnabled());
282     Assert.assertEquals("missing config no endpoints", 0, m.getEndpoints().size());
283   }
284
285   @Test
286   public void testMissingEndpoint() throws IOException {
287     ExternalTestingManager m = configTestManager(true);
288
289     // execute a test.
290     List<VtpTestExecutionRequest> requests = new ArrayList<>();
291     VtpTestExecutionRequest req = new VtpTestExecutionRequest();
292     req.setEndpoint("repository");
293     requests.add(req);
294
295     // send a request with the endpoint defined.
296     try {
297       m.execute(requests, "vspId", "vspVersionId", "throwexception", null);
298     } catch (ExternalTestingException e) {
299       // expected.
300     }
301   }
302
303
304   @Test
305   public void testManagerConfigOverrides() throws IOException {
306     ExternalTestingManager m = configTestManager(false);
307
308     ClientConfiguration cc = new ClientConfiguration();
309     cc.setEnabled(true);
310     m.setConfig(cc);
311     Assert.assertTrue(m.getConfig().isEnabled());
312
313     List<RemoteTestingEndpointDefinition> lst = new ArrayList<>();
314     lst.add(new RemoteTestingEndpointDefinition());
315     lst.get(0).setEnabled(true);
316     m.setEndpoints(lst);
317     Assert.assertEquals(1, m.getEndpoints().size());
318   }
319
320   @Test
321   public void testManagerErrorCases() throws IOException {
322     ExternalTestingManager m = configTestManager(false);
323     ClientConfiguration emptyConfig = m.getConfig();
324     Assert.assertFalse("empty configuration should have client enabled of false", emptyConfig.isEnabled());
325
326     try {
327       m.getEndpoints();
328       Assert.assertTrue("should have exception here", true);
329     } catch (ExternalTestingException e) {
330       // eat the exception cause this is what should happen.
331     }
332   }
333
334   @Test
335   public void testExecutionDistribution() throws IOException {
336     ExternalTestingManager m = configTestManager(true);
337
338     VtpTestExecutionRequest r1 = new VtpTestExecutionRequest();
339     r1.setScenario("scenario1");
340     r1.setEndpoint("vtp");
341
342     VtpTestExecutionRequest r2 = new VtpTestExecutionRequest();
343     r2.setScenario("scenario2");
344     r2.setEndpoint("vtp");
345
346     VtpTestExecutionRequest r3 = new VtpTestExecutionRequest();
347     r3.setScenario("scenario3");
348     r3.setEndpoint("repository");
349
350     List<VtpTestExecutionResponse> results =
351             m.execute(Arrays.asList(r1, r2, r3), "vspId", "vspVersionId", "rid", null);
352     Assert.assertEquals("three in two out merged", 2, results.size());
353   }
354
355   @Test
356   public void testArchiveProcessing() throws IOException {
357     ExternalTestingManagerImpl m = configTestManager(true);
358     VtpTestExecutionRequest r1 = new VtpTestExecutionRequest();
359     r1.setScenario("scenario1");
360     r1.setEndpoint("vtp");
361     r1.setParameters(new HashMap<>());
362
363     LinkedMultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
364     m.attachArchiveContent(r1, body, "something.with.csar.content", UUID.randomUUID().toString());
365     r1.setParameters(new HashMap<>());
366     LinkedMultiValueMap<String, Object> body2 = new LinkedMultiValueMap<>();
367     m.attachArchiveContent(r1, body2, "something.with.heat.content", UUID.randomUUID().toString());
368
369     // now, let's handle a missing archive.
370     r1.setParameters(new HashMap<>());
371     LinkedMultiValueMap<String, Object> body3 = new LinkedMultiValueMap<>();
372     try {
373       m.attachArchiveContent(r1, body3, "something.with.missing.content", UUID.randomUUID().toString());
374       Assert.fail("expected to receive an exception here");
375     } catch (ExternalTestingException ex) {
376       Assert.assertEquals(500, ex.getHttpStatus());
377     }
378
379   }
380 }