Enrichment Service
[nonrtric.git] / enrichment-coordinator-service / src / test / java / org / oransc / enrichment / ApplicationTest.java
1 /*-
2  * ========================LICENSE_START=================================
3  * ONAP : ccsdk oran
4  * ======================================================================
5  * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved.
6  * ======================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ========================LICENSE_END===================================
19  */
20
21 package org.oransc.enrichment;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26
27 import com.google.gson.Gson;
28 import com.google.gson.GsonBuilder;
29 import com.google.gson.JsonElement;
30 import com.google.gson.JsonObject;
31 import com.google.gson.JsonPrimitive;
32
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36
37 import org.junit.jupiter.api.AfterEach;
38 import org.junit.jupiter.api.BeforeEach;
39 import org.junit.jupiter.api.Test;
40 import org.junit.jupiter.api.extension.ExtendWith;
41 import org.oransc.enrichment.clients.AsyncRestClient;
42 import org.oransc.enrichment.clients.ProducerJobInfo;
43 import org.oransc.enrichment.configuration.ApplicationConfig;
44 import org.oransc.enrichment.configuration.ImmutableWebClientConfig;
45 import org.oransc.enrichment.configuration.WebClientConfig;
46 import org.oransc.enrichment.controller.ProducerSimulatorController;
47 import org.oransc.enrichment.controllers.consumer.ConsumerConsts;
48 import org.oransc.enrichment.controllers.consumer.ConsumerEiJobInfo;
49 import org.oransc.enrichment.controllers.producer.ProducerConsts;
50 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo;
51 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo.ProducerEiTypeRegistrationInfo;
52 import org.oransc.enrichment.repository.EiJob;
53 import org.oransc.enrichment.repository.EiJobs;
54 import org.oransc.enrichment.repository.EiProducer;
55 import org.oransc.enrichment.repository.EiProducers;
56 import org.oransc.enrichment.repository.EiType;
57 import org.oransc.enrichment.repository.EiTypes;
58 import org.oransc.enrichment.repository.ImmutableEiJob;
59 import org.oransc.enrichment.repository.ImmutableEiProducer;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62 import org.springframework.beans.factory.annotation.Autowired;
63 import org.springframework.boot.test.context.SpringBootTest;
64 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
65 import org.springframework.boot.test.context.TestConfiguration;
66 import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
67 import org.springframework.boot.web.server.LocalServerPort;
68 import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
69 import org.springframework.context.ApplicationContext;
70 import org.springframework.context.annotation.Bean;
71 import org.springframework.http.HttpStatus;
72 import org.springframework.http.MediaType;
73 import org.springframework.http.ResponseEntity;
74 import org.springframework.test.context.TestPropertySource;
75 import org.springframework.test.context.junit.jupiter.SpringExtension;
76 import org.springframework.web.reactive.function.client.WebClientResponseException;
77
78 import reactor.core.publisher.Mono;
79 import reactor.test.StepVerifier;
80
81 @ExtendWith(SpringExtension.class)
82 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
83 @TestPropertySource(
84     properties = { //
85         "server.ssl.key-store=./config/keystore.jks", //
86         "app.webclient.trust-store=./config/truststore.jks"})
87 class ApplicationTest {
88     private static final Logger logger = LoggerFactory.getLogger(ApplicationTest.class);
89
90     @Autowired
91     ApplicationContext context;
92
93     @Autowired
94     EiJobs eiJobs;
95
96     @Autowired
97     EiTypes eiTypes;
98
99     @Autowired
100     EiProducers eiProducers;
101
102     @Autowired
103     ApplicationConfig applicationConfig;
104
105     @Autowired
106     ProducerSimulatorController producerSimulator;
107
108     private static Gson gson = new GsonBuilder() //
109         .serializeNulls() //
110         .create(); //
111
112     /**
113      * Overrides the BeanFactory.
114      */
115     @TestConfiguration
116     static class TestBeanFactory {
117         @Bean
118         public ServletWebServerFactory servletContainer() {
119             return new TomcatServletWebServerFactory();
120         }
121     }
122
123     @LocalServerPort
124     private int port;
125
126     @BeforeEach
127     void reset() {
128         this.eiJobs.clear();
129         this.eiTypes.clear();
130         this.eiProducers.clear();
131         this.producerSimulator.getTestResults().reset();
132     }
133
134     @AfterEach
135     void check() {
136         assertThat(this.producerSimulator.getTestResults().errorFound).isFalse();
137     }
138
139     @Test
140     void getEiTypes() throws Exception {
141         addEiType("test");
142         String url = ConsumerConsts.API_ROOT + "/eitypes";
143         String rsp = restClient().get(url).block();
144         assertThat(rsp).isEqualTo("[\"test\"]");
145     }
146
147     @Test
148     void getEiType() throws Exception {
149         addEiType("test");
150         String url = ConsumerConsts.API_ROOT + "/eitypes/test";
151         String rsp = restClient().get(url).block();
152         assertThat(rsp).contains("job_data_schema");
153     }
154
155     @Test
156     void getEiTypeNotFound() throws Exception {
157         String url = ConsumerConsts.API_ROOT + "/eitypes/junk";
158         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
159     }
160
161     @Test
162     void getEiJobsIds() throws Exception {
163         addEiJob("typeId", "jobId");
164         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs";
165         String rsp = restClient().get(url).block();
166         assertThat(rsp).isEqualTo("[\"jobId\"]");
167     }
168
169     @Test
170     void getEiJobTypeNotFound() throws Exception {
171         String url = ConsumerConsts.API_ROOT + "/eitypes/junk/eijobs";
172         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
173     }
174
175     @Test
176     void getEiJob() throws Exception {
177         addEiJob("typeId", "jobId");
178         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
179         String rsp = restClient().get(url).block();
180         assertThat(rsp).contains("job_data");
181     }
182
183     @Test
184     void getEiJobStatus() throws Exception {
185         addEiJob("typeId", "jobId");
186         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId/status";
187         String rsp = restClient().get(url).block();
188         assertThat(rsp).contains("ENABLED");
189     }
190
191     // Status TBD
192
193     @Test
194     void deleteEiJob() throws Exception {
195         addEiJob("typeId", "jobId");
196         assertThat(this.eiJobs.size()).isEqualTo(1);
197         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
198         restClient().delete(url).block();
199         assertThat(this.eiJobs.size()).isEqualTo(0);
200
201         ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
202         await().untilAsserted(() -> assertThat(simulatorResults.jobsStopped.size()).isEqualTo(1));
203         assertThat(simulatorResults.jobsStopped.get(0).id).isEqualTo("jobId");
204     }
205
206     @Test
207     void putEiJob() throws Exception {
208         addEiType("typeId");
209
210         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
211         String body = gson.toJson(eiJobInfo());
212         ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
213         assertThat(this.eiJobs.size()).isEqualTo(1);
214         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
215
216         ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
217         await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
218         ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
219         assertThat(request.id).isEqualTo("jobId");
220
221         resp = restClient().putForEntity(url, body).block();
222         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
223         EiJob job = this.eiJobs.getJob("jobId");
224         assertThat(job.owner()).isEqualTo("owner");
225     }
226
227     @Test
228     void getEiProducerTypes() throws Exception {
229         this.addEiJob("typeId", "jobId");
230         String url = ProducerConsts.API_ROOT + "/eitypes";
231
232         ResponseEntity<String> resp = restClient().getForEntity(url).block();
233         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
234     }
235
236     @Test
237     void putEiProducer() throws Exception {
238         String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
239         String body = gson.toJson(producerEiRegistratioInfo());
240
241         ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
242         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
243
244         assertThat(this.eiTypes.size()).isEqualTo(1);
245         EiType type = this.eiTypes.getType("typeId");
246         assertThat(type.getProducerIds().contains("eiProducerId")).isTrue();
247         assertThat(this.eiProducers.size()).isEqualTo(1);
248         assertThat(this.eiProducers.get("eiProducerId").eiTypes().iterator().next().getId().equals("typeId")).isTrue();
249
250         resp = restClient().putForEntity(url, body).block();
251         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
252     }
253
254     @Test
255     void putEiProducerExistingJob() throws Exception {
256         this.addEiJob("typeId", "jobId");
257         String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
258         String body = gson.toJson(producerEiRegistratioInfo());
259
260         ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
261         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
262
263         ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
264         await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
265         ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
266         assertThat(request.id).isEqualTo("jobId");
267     }
268
269     @Test
270     void getEiJobsForProducer() {
271         this.addEiJob("typeId", "jobId1");
272         this.addEiJob("typeId", "jobId2");
273
274         // PUT a consumer
275         String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
276         String body = gson.toJson(producerEiRegistratioInfo());
277         restClient().putForEntity(url, body).block();
278
279         url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId/eijobs";
280         ResponseEntity<String> resp = restClient().getForEntity(url).block();
281         assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
282
283         ProducerJobInfo[] parsedResp = gson.fromJson(resp.getBody(), ProducerJobInfo[].class);
284         assertThat(parsedResp[0].typeId).isEqualTo("typeId");
285         assertThat(parsedResp[1].typeId).isEqualTo("typeId");
286     }
287
288     @Test
289     void deleteEiProducer() throws Exception {
290         String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
291         String url2 = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId2";
292         String body = gson.toJson(producerEiRegistratioInfo());
293         restClient().putForEntity(url, body).block();
294         restClient().putForEntity(url2, body).block();
295         assertThat(this.eiProducers.size()).isEqualTo(2);
296         EiType type = this.eiTypes.getType("typeId");
297         assertThat(type.getProducerIds().contains("eiProducerId")).isTrue();
298         assertThat(type.getProducerIds().contains("eiProducerId2")).isTrue();
299
300         restClient().deleteForEntity(url).block();
301         assertThat(this.eiProducers.size()).isEqualTo(1);
302         assertThat(this.eiTypes.getType("typeId").getProducerIds().contains("eiProducerId")).isFalse();
303
304         restClient().deleteForEntity(url2).block();
305         assertThat(this.eiProducers.size()).isEqualTo(0);
306         assertThat(this.eiTypes.size()).isEqualTo(0);
307     }
308
309     ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo() {
310         return new ProducerEiTypeRegistrationInfo(jsonObject(), "typeId");
311     }
312
313     ProducerRegistrationInfo producerEiRegistratioInfo() {
314         Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
315         types.add(producerEiTypeRegistrationInfo());
316         return new ProducerRegistrationInfo(types, baseUrl() + ProducerSimulatorController.JOB_CREATED_URL,
317             baseUrl() + ProducerSimulatorController.JOB_DELETED_URL);
318     }
319
320     ConsumerEiJobInfo eiJobInfo() {
321         return new ConsumerEiJobInfo(jsonObject(), "owner");
322     }
323
324     JsonObject jsonObject() {
325         JsonObject jsonObj = new JsonObject();
326         JsonElement e = new JsonPrimitive(111);
327         jsonObj.add("param", e);
328         return jsonObj;
329     }
330
331     private EiJob addEiJob(String typeId, String jobId) {
332         EiType type = addEiType(typeId);
333         EiJob job = ImmutableEiJob.builder() //
334             .id(jobId) //
335             .type(type) //
336             .owner("owner") //
337             .jobData(jsonObject()) //
338             .build();
339         this.eiJobs.put(job);
340         return job;
341     }
342
343     private EiType addEiType(String typeId) {
344         EiType eiType = new EiType(typeId, jsonObject());
345         this.eiTypes.put(eiType); //
346         EiProducer producer = ImmutableEiProducer.builder() //
347             .id("producerId") //
348             .eiTypes(Arrays.asList(eiType)) //
349             .jobCreationCallbackUrl(baseUrl() + ProducerSimulatorController.JOB_CREATED_URL) //
350             .jobDeletionCallbackUrl(baseUrl() + ProducerSimulatorController.JOB_DELETED_URL) //
351             .build();
352         this.eiProducers.put(producer);
353         eiType.addProducer(producer);
354         return eiType;
355     }
356
357     private String baseUrl() {
358         return "https://localhost:" + this.port;
359     }
360
361     private AsyncRestClient restClient(boolean useTrustValidation) {
362         WebClientConfig config = this.applicationConfig.getWebClientConfig();
363         config = ImmutableWebClientConfig.builder() //
364             .keyStoreType(config.keyStoreType()) //
365             .keyStorePassword(config.keyStorePassword()) //
366             .keyStore(config.keyStore()) //
367             .keyPassword(config.keyPassword()) //
368             .isTrustStoreUsed(useTrustValidation) //
369             .trustStore(config.trustStore()) //
370             .trustStorePassword(config.trustStorePassword()) //
371             .build();
372
373         return new AsyncRestClient(baseUrl(), config);
374     }
375
376     private AsyncRestClient restClient() {
377         return restClient(false);
378     }
379
380     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
381         testErrorCode(request, expStatus, responseContains, true);
382     }
383
384     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
385         boolean expectApplicationProblemJsonMediaType) {
386         StepVerifier.create(request) //
387             .expectSubscription() //
388             .expectErrorMatches(
389                 t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) //
390             .verify();
391     }
392
393     private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
394         boolean expectApplicationProblemJsonMediaType) {
395         assertTrue(throwable instanceof WebClientResponseException);
396         WebClientResponseException responseException = (WebClientResponseException) throwable;
397         assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
398         assertThat(responseException.getResponseBodyAsString()).contains(responseContains);
399         if (expectApplicationProblemJsonMediaType) {
400             assertThat(responseException.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);
401         }
402         return true;
403     }
404
405 }