2 * ========================LICENSE_START=================================
5 * Copyright (C) 2020 Nordix Foundation
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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===================================
21 package org.oransc.enrichment;
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;
27 import com.fasterxml.jackson.core.JsonProcessingException;
28 import com.fasterxml.jackson.databind.JsonMappingException;
29 import com.google.gson.Gson;
30 import com.google.gson.GsonBuilder;
31 import com.google.gson.JsonParser;
33 import java.io.FileNotFoundException;
34 import java.io.FileOutputStream;
35 import java.io.PrintStream;
36 import java.util.ArrayList;
37 import java.util.Collection;
39 import org.json.JSONObject;
40 import org.junit.jupiter.api.AfterEach;
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43 import org.junit.jupiter.api.extension.ExtendWith;
44 import org.oransc.enrichment.clients.AsyncRestClient;
45 import org.oransc.enrichment.clients.AsyncRestClientFactory;
46 import org.oransc.enrichment.configuration.ApplicationConfig;
47 import org.oransc.enrichment.configuration.ImmutableWebClientConfig;
48 import org.oransc.enrichment.configuration.WebClientConfig;
49 import org.oransc.enrichment.controller.ConsumerSimulatorController;
50 import org.oransc.enrichment.controller.ProducerSimulatorController;
51 import org.oransc.enrichment.controllers.consumer.ConsumerConsts;
52 import org.oransc.enrichment.controllers.consumer.ConsumerEiJobInfo;
53 import org.oransc.enrichment.controllers.consumer.ConsumerEiJobStatus;
54 import org.oransc.enrichment.controllers.consumer.ConsumerEiTypeInfo;
55 import org.oransc.enrichment.controllers.producer.ProducerConsts;
56 import org.oransc.enrichment.controllers.producer.ProducerJobInfo;
57 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo;
58 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo.ProducerEiTypeRegistrationInfo;
59 import org.oransc.enrichment.controllers.producer.ProducerStatusInfo;
60 import org.oransc.enrichment.exceptions.ServiceException;
61 import org.oransc.enrichment.repository.EiJob;
62 import org.oransc.enrichment.repository.EiJobs;
63 import org.oransc.enrichment.repository.EiProducers;
64 import org.oransc.enrichment.repository.EiType;
65 import org.oransc.enrichment.repository.EiTypes;
66 import org.oransc.enrichment.tasks.ProducerSupervision;
67 import org.springframework.beans.factory.annotation.Autowired;
68 import org.springframework.boot.test.context.SpringBootTest;
69 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
70 import org.springframework.boot.test.context.TestConfiguration;
71 import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
72 import org.springframework.boot.web.server.LocalServerPort;
73 import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
74 import org.springframework.context.ApplicationContext;
75 import org.springframework.context.annotation.Bean;
76 import org.springframework.http.HttpStatus;
77 import org.springframework.http.MediaType;
78 import org.springframework.http.ResponseEntity;
79 import org.springframework.test.context.TestPropertySource;
80 import org.springframework.test.context.junit.jupiter.SpringExtension;
81 import org.springframework.web.reactive.function.client.WebClientResponseException;
83 import reactor.core.publisher.Mono;
84 import reactor.test.StepVerifier;
86 @ExtendWith(SpringExtension.class)
87 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
90 "server.ssl.key-store=./config/keystore.jks", //
91 "app.webclient.trust-store=./config/truststore.jks", //
92 "app.vardata-directory=./target"})
93 class ApplicationTest {
94 private final String EI_TYPE_ID = "typeId";
95 private final String EI_PRODUCER_ID = "producerId";
96 private final String EI_JOB_PROPERTY = "\"property1\"";
97 private final String EI_JOB_ID = "jobId";
100 ApplicationContext context;
109 EiProducers eiProducers;
112 ApplicationConfig applicationConfig;
115 ProducerSimulatorController producerSimulator;
118 ConsumerSimulatorController consumerSimulator;
121 ProducerSupervision producerSupervision;
123 private static Gson gson = new GsonBuilder().create();
126 * Overrides the BeanFactory.
129 static class TestBeanFactory {
131 public ServletWebServerFactory servletContainer() {
132 return new TomcatServletWebServerFactory();
142 this.eiTypes.clear();
143 this.eiProducers.clear();
144 this.producerSimulator.getTestResults().reset();
145 this.consumerSimulator.getTestResults().reset();
150 assertThat(this.producerSimulator.getTestResults().errorFound).isFalse();
154 void createApiDoc() throws FileNotFoundException {
155 String url = "/v2/api-docs";
156 ResponseEntity<String> resp = restClient().getForEntity(url).block();
157 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
159 String indented = (new JSONObject(resp.getBody())).toString(4);
160 try (PrintStream out = new PrintStream(new FileOutputStream("../docs/offeredapis/swagger/ecs-api.json"))) {
166 void testGetEiTypes() throws Exception {
167 putEiProducerWithOneType(EI_PRODUCER_ID, "test");
168 String url = ConsumerConsts.API_ROOT + "/eitypes";
169 String rsp = restClient().get(url).block();
170 assertThat(rsp).isEqualTo("[\"test\"]");
174 void testGetEiTypesEmpty() throws Exception {
175 String url = ConsumerConsts.API_ROOT + "/eitypes";
176 String rsp = restClient().get(url).block();
177 assertThat(rsp).isEqualTo("[]");
181 void testGetEiType() throws Exception {
182 putEiProducerWithOneType(EI_PRODUCER_ID, "test");
183 String url = ConsumerConsts.API_ROOT + "/eitypes/test";
184 String rsp = restClient().get(url).block();
185 ConsumerEiTypeInfo info = gson.fromJson(rsp, ConsumerEiTypeInfo.class);
186 assertThat(info).isNotNull();
190 void testGetEiTypeNotFound() throws Exception {
191 String url = ConsumerConsts.API_ROOT + "/eitypes/junk";
192 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
196 void testGetEiJobsIds() throws Exception {
197 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
198 putEiJob(EI_TYPE_ID, "jobId");
199 final String JOB_ID_JSON = "[\"jobId\"]";
200 String url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=typeId";
201 String rsp = restClient().get(url).block();
202 assertThat(rsp).isEqualTo(JOB_ID_JSON);
204 url = ConsumerConsts.API_ROOT + "/eijobs?owner=owner";
205 rsp = restClient().get(url).block();
206 assertThat(rsp).isEqualTo(JOB_ID_JSON);
208 url = ConsumerConsts.API_ROOT + "/eijobs?owner=JUNK";
209 rsp = restClient().get(url).block();
210 assertThat(rsp).isEqualTo("[]");
212 url = ConsumerConsts.API_ROOT + "/eijobs";
213 rsp = restClient().get(url).block();
214 assertThat(rsp).isEqualTo(JOB_ID_JSON);
216 url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=typeId&&owner=owner";
217 rsp = restClient().get(url).block();
218 assertThat(rsp).isEqualTo(JOB_ID_JSON);
220 url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=JUNK";
221 rsp = restClient().get(url).block();
222 assertThat(rsp).isEqualTo("[]");
226 void testGetEiJob() throws Exception {
227 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
228 putEiJob(EI_TYPE_ID, "jobId");
229 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
230 String rsp = restClient().get(url).block();
231 ConsumerEiJobInfo info = gson.fromJson(rsp, ConsumerEiJobInfo.class);
232 assertThat(info.owner).isEqualTo("owner");
233 assertThat(info.eiTypeId).isEqualTo(EI_TYPE_ID);
237 void testGetEiJobNotFound() throws Exception {
238 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
239 String url = ConsumerConsts.API_ROOT + "/eijobs/junk";
240 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk");
244 void testGetEiJobStatus() throws Exception {
245 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
246 putEiJob(EI_TYPE_ID, "jobId");
248 verifyJobStatus("jobId", "ENABLED");
252 void testDeleteEiJob() throws Exception {
253 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
254 putEiJob(EI_TYPE_ID, "jobId");
255 assertThat(this.eiJobs.size()).isEqualTo(1);
256 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
257 restClient().delete(url).block();
258 assertThat(this.eiJobs.size()).isZero();
260 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
261 await().untilAsserted(() -> assertThat(simulatorResults.jobsStopped.size()).isEqualTo(1));
262 assertThat(simulatorResults.jobsStopped.get(0)).isEqualTo("jobId");
266 void testDeleteEiJobNotFound() throws Exception {
267 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
268 String url = ConsumerConsts.API_ROOT + "/eijobs/junk";
269 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk");
273 void testPutEiJob() throws Exception {
274 // Test that one producer accepting a job is enough
275 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
276 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
278 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
279 String body = gson.toJson(eiJobInfo());
280 ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
281 assertThat(this.eiJobs.size()).isEqualTo(1);
282 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
284 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
285 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
286 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
287 assertThat(request.id).isEqualTo("jobId");
289 assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(1);
291 resp = restClient().putForEntity(url, body).block();
292 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
293 EiJob job = this.eiJobs.getJob("jobId");
294 assertThat(job.owner()).isEqualTo("owner");
298 void putEiProducerWithOneType_rejecting() throws JsonMappingException, JsonProcessingException, ServiceException {
299 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
300 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
301 String body = gson.toJson(eiJobInfo());
302 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Job not accepted by any producers");
304 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
305 assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(1);
309 void testPutEiJob_jsonSchemavalidationError() throws Exception {
310 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
312 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
313 // The element with name "property1" is mandatory in the schema
314 ConsumerEiJobInfo jobInfo = new ConsumerEiJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner",
315 "targetUri", "jobStatusUrl");
316 String body = gson.toJson(jobInfo);
318 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
322 void testGetEiProducerTypes() throws Exception {
323 final String EI_TYPE_ID_2 = EI_TYPE_ID + "_2";
324 putEiProducerWithOneType("producer1", EI_TYPE_ID);
325 putEiJob(EI_TYPE_ID, "jobId");
326 putEiProducerWithOneType("producer2", EI_TYPE_ID_2);
327 putEiJob(EI_TYPE_ID_2, "jobId2");
328 String url = ProducerConsts.API_ROOT + "/eitypes";
330 ResponseEntity<String> resp = restClient().getForEntity(url).block();
331 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
332 assertThat(resp.getBody()).contains(EI_TYPE_ID);
333 assertThat(resp.getBody()).contains(EI_TYPE_ID_2);
337 void testReplacingEiProducerTypes() throws Exception {
338 final String REPLACED_TYPE_ID = "replaced";
339 putEiProducerWithOneType(EI_PRODUCER_ID, REPLACED_TYPE_ID);
340 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
342 String url = ProducerConsts.API_ROOT + "/eitypes";
344 ResponseEntity<String> resp = restClient().getForEntity(url).block();
345 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
346 assertThat(resp.getBody()).contains(EI_TYPE_ID);
347 assertThat(resp.getBody()).doesNotContain(REPLACED_TYPE_ID);
351 void testChangingEiTypeGetRejected() throws Exception {
352 putEiProducerWithOneType("producer1", "typeId1");
353 putEiProducerWithOneType("producer2", "typeId2");
354 putEiJob("typeId1", "jobId");
356 String url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
357 String body = gson.toJson(eiJobInfo("typeId2", "jobId"));
358 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT,
359 "Not allowed to change type for existing EI job");
363 void testPutEiProducer() throws Exception {
364 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
365 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
367 ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
368 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
370 assertThat(this.eiTypes.size()).isEqualTo(1);
371 EiType type = this.eiTypes.getType(EI_TYPE_ID);
372 assertThat(type.getProducerIds()).contains("eiProducerId");
373 assertThat(this.eiProducers.size()).isEqualTo(1);
374 assertThat(this.eiProducers.get("eiProducerId").getEiTypes().iterator().next().getId()).isEqualTo(EI_TYPE_ID);
376 resp = restClient().putForEntity(url, body).block();
377 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
379 resp = restClient().getForEntity(url).block();
380 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
381 assertThat(resp.getBody()).isEqualTo(body);
385 void testPutEiProducerExistingJob() throws Exception {
386 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
387 putEiJob(EI_TYPE_ID, "jobId");
388 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
389 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
390 restClient().putForEntity(url, body).block();
392 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
393 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(2));
394 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
395 assertThat(request.id).isEqualTo("jobId");
399 void testPutProducerAndEiJob() throws Exception {
400 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
401 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
402 restClient().putForEntity(url, body).block();
403 assertThat(this.eiTypes.size()).isEqualTo(1);
404 this.eiTypes.getType(EI_TYPE_ID);
406 url = ConsumerConsts.API_ROOT + "/eijobs/jobId";
407 body = gson.toJson(eiJobInfo());
408 restClient().putForEntity(url, body).block();
410 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
411 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
412 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
413 assertThat(request.id).isEqualTo("jobId");
417 void testGetEiJobsForProducer() throws JsonMappingException, JsonProcessingException, ServiceException {
418 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
419 putEiJob(EI_TYPE_ID, "jobId1");
420 putEiJob(EI_TYPE_ID, "jobId2");
423 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
424 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
425 restClient().putForEntity(url, body).block();
427 url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId/eijobs";
428 ResponseEntity<String> resp = restClient().getForEntity(url).block();
429 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
431 ProducerJobInfo[] parsedResp = gson.fromJson(resp.getBody(), ProducerJobInfo[].class);
432 assertThat(parsedResp[0].typeId).isEqualTo(EI_TYPE_ID);
433 assertThat(parsedResp[1].typeId).isEqualTo(EI_TYPE_ID);
437 void testDeleteEiProducer() throws Exception {
438 putEiProducerWithOneType("eiProducerId", EI_TYPE_ID);
439 putEiProducerWithOneType("eiProducerId2", EI_TYPE_ID);
441 assertThat(this.eiProducers.size()).isEqualTo(2);
442 EiType type = this.eiTypes.getType(EI_TYPE_ID);
443 assertThat(type.getProducerIds()).contains("eiProducerId");
444 assertThat(type.getProducerIds()).contains("eiProducerId2");
445 putEiJob(EI_TYPE_ID, "jobId");
446 assertThat(this.eiJobs.size()).isEqualTo(1);
448 deleteEiProducer("eiProducerId");
449 assertThat(this.eiProducers.size()).isEqualTo(1);
450 assertThat(this.eiTypes.getType(EI_TYPE_ID).getProducerIds()).doesNotContain("eiProducerId");
451 verifyJobStatus("jobId", "ENABLED");
453 deleteEiProducer("eiProducerId2");
454 assertThat(this.eiProducers.size()).isZero();
455 assertThat(this.eiTypes.size()).isZero();
456 verifyJobStatus("jobId", "DISABLED");
460 void testJobStatusNotifications() throws JsonMappingException, JsonProcessingException, ServiceException {
461 putEiProducerWithOneType("eiProducerId", EI_TYPE_ID);
462 putEiJob(EI_TYPE_ID, "jobId");
464 deleteEiProducer("eiProducerId");
465 assertThat(this.eiTypes.size()).isZero(); // The type is gone
466 assertThat(this.eiJobs.size()).isEqualTo(1); // The job remains
467 ConsumerSimulatorController.TestResults consumerResults = this.consumerSimulator.getTestResults();
468 await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(1));
469 assertThat(consumerResults.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.DISABLED);
471 putEiProducerWithOneType("eiProducerId", EI_TYPE_ID);
472 await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(2));
473 assertThat(consumerResults.status.get(1).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.ENABLED);
477 void testGetProducerEiType() throws JsonMappingException, JsonProcessingException, ServiceException {
478 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
479 String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID;
480 ResponseEntity<String> resp = restClient().getForEntity(url).block();
481 assertThat(resp.getBody()).contains(EI_PRODUCER_ID);
485 void testGetProducerIdentifiers() throws JsonMappingException, JsonProcessingException, ServiceException {
486 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
487 String url = ProducerConsts.API_ROOT + "/eiproducers";
488 ResponseEntity<String> resp = restClient().getForEntity(url).block();
489 assertThat(resp.getBody()).contains(EI_PRODUCER_ID);
493 void testProducerSupervision() throws JsonMappingException, JsonProcessingException, ServiceException {
494 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
498 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
499 putEiJob(EI_TYPE_ID, "jobId");
500 deleteEiProducer(EI_PRODUCER_ID);
503 assertThat(this.eiProducers.size()).isEqualTo(1);
504 assertThat(this.eiTypes.size()).isEqualTo(1);
505 assertProducerOpState("simulateProducerError", ProducerStatusInfo.OperationalState.ENABLED);
507 this.producerSupervision.createTask().blockLast();
508 this.producerSupervision.createTask().blockLast();
509 assertThat(this.eiProducers.size()).isEqualTo(1);
510 assertProducerOpState("simulateProducerError", ProducerStatusInfo.OperationalState.DISABLED);
512 // After 3 failed checks, the producer and the type shall be deregisterred
513 this.producerSupervision.createTask().blockLast();
514 assertThat(this.eiProducers.size()).isEqualTo(0);
515 assertThat(this.eiTypes.size()).isEqualTo(0);
517 // Job disabled status notification shall be received
518 ConsumerSimulatorController.TestResults consumerResults = this.consumerSimulator.getTestResults();
519 await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(1));
520 assertThat(consumerResults.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.DISABLED);
524 void testGetStatus() throws JsonMappingException, JsonProcessingException, ServiceException {
525 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
526 putEiProducerWithOneTypeRejecting("simulateProducerError2", EI_TYPE_ID);
528 String url = "/status";
529 ResponseEntity<String> resp = restClient().getForEntity(url).block();
530 assertThat(resp.getBody()).contains("hunky dory");
534 void testEiJobDatabase() throws Exception {
535 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
536 putEiJob(EI_TYPE_ID, "jobId1");
537 putEiJob(EI_TYPE_ID, "jobId2");
539 assertThat(this.eiJobs.size()).isEqualTo(2);
543 EiJobs jobs = new EiJobs(this.applicationConfig);
544 jobs.restoreJobsFromDatabase();
545 assertThat(jobs.size()).isEqualTo(2);
546 jobs.remove("jobId1");
547 jobs.remove("jobId2");
550 // Restore the jobs, no jobs in database
551 EiJobs jobs = new EiJobs(this.applicationConfig);
552 jobs.restoreJobsFromDatabase();
553 assertThat(jobs.size()).isEqualTo(0);
556 this.eiJobs.remove("jobId1"); // removing a job when the db file is gone
557 assertThat(this.eiJobs.size()).isEqualTo(1);
560 private void deleteEiProducer(String eiProducerId) {
561 String url = ProducerConsts.API_ROOT + "/eiproducers/" + eiProducerId;
562 restClient().deleteForEntity(url).block();
565 private void verifyJobStatus(String jobId, String expStatus) {
566 String url = ConsumerConsts.API_ROOT + "/eijobs/" + jobId + "/status";
567 String rsp = restClient().get(url).block();
568 assertThat(rsp).contains(expStatus);
571 private void assertProducerOpState(String producerId,
572 ProducerStatusInfo.OperationalState expectedOperationalState) {
573 String statusUrl = ProducerConsts.API_ROOT + "/eiproducers/" + producerId + "/status";
574 ResponseEntity<String> resp = restClient().getForEntity(statusUrl).block();
575 ProducerStatusInfo statusInfo = gson.fromJson(resp.getBody(), ProducerStatusInfo.class);
576 assertThat(statusInfo.opState).isEqualTo(expectedOperationalState);
579 ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo(String typeId)
580 throws JsonMappingException, JsonProcessingException {
581 return new ProducerEiTypeRegistrationInfo(jsonSchemaObject(), typeId);
584 ProducerRegistrationInfo producerEiRegistratioInfoRejecting(String typeId)
585 throws JsonMappingException, JsonProcessingException {
586 Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
587 types.add(producerEiTypeRegistrationInfo(typeId));
588 return new ProducerRegistrationInfo(types, //
589 baseUrl() + ProducerSimulatorController.JOB_ERROR_URL,
590 baseUrl() + ProducerSimulatorController.SUPERVISION_ERROR_URL);
593 ProducerRegistrationInfo producerEiRegistratioInfo(String typeId)
594 throws JsonMappingException, JsonProcessingException {
595 Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
596 types.add(producerEiTypeRegistrationInfo(typeId));
597 return new ProducerRegistrationInfo(types, //
598 baseUrl() + ProducerSimulatorController.JOB_URL, baseUrl() + ProducerSimulatorController.SUPERVISION_URL);
601 private ConsumerEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException {
602 return eiJobInfo(EI_TYPE_ID, EI_JOB_ID);
605 ConsumerEiJobInfo eiJobInfo(String typeId, String eiJobId) throws JsonMappingException, JsonProcessingException {
606 return new ConsumerEiJobInfo(typeId, jsonObject(), "owner", "targetUri",
607 baseUrl() + ConsumerSimulatorController.getJobStatusUrl(eiJobId));
610 private Object jsonObject(String json) {
612 return JsonParser.parseString(json).getAsJsonObject();
613 } catch (Exception e) {
614 throw new NullPointerException(e.toString());
618 private Object jsonSchemaObject() {
619 // a json schema with one mandatory property named "string"
620 String schemaStr = "{" //
621 + "\"$schema\": \"http://json-schema.org/draft-04/schema#\"," //
622 + "\"type\": \"object\"," //
623 + "\"properties\": {" //
624 + EI_JOB_PROPERTY + " : {" //
625 + " \"type\": \"string\"" //
628 + "\"required\": [" //
632 return jsonObject(schemaStr);
635 private Object jsonObject() {
636 return jsonObject("{ " + EI_JOB_PROPERTY + " : \"value\" }");
639 private EiJob putEiJob(String eiTypeId, String jobId)
640 throws JsonMappingException, JsonProcessingException, ServiceException {
642 String url = ConsumerConsts.API_ROOT + "/eijobs/" + jobId;
643 String body = gson.toJson(eiJobInfo(eiTypeId, jobId));
644 restClient().putForEntity(url, body).block();
646 return this.eiJobs.getJob(jobId);
649 private EiType putEiProducerWithOneTypeRejecting(String producerId, String eiTypeId)
650 throws JsonMappingException, JsonProcessingException, ServiceException {
651 String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
652 String body = gson.toJson(producerEiRegistratioInfoRejecting(eiTypeId));
654 restClient().putForEntity(url, body).block();
655 return this.eiTypes.getType(eiTypeId);
658 private EiType putEiProducerWithOneType(String producerId, String eiTypeId)
659 throws JsonMappingException, JsonProcessingException, ServiceException {
660 String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
661 String body = gson.toJson(producerEiRegistratioInfo(eiTypeId));
663 restClient().putForEntity(url, body).block();
664 return this.eiTypes.getType(eiTypeId);
667 private String baseUrl() {
668 return "https://localhost:" + this.port;
671 private AsyncRestClient restClient(boolean useTrustValidation) {
672 WebClientConfig config = this.applicationConfig.getWebClientConfig();
673 config = ImmutableWebClientConfig.builder() //
674 .keyStoreType(config.keyStoreType()) //
675 .keyStorePassword(config.keyStorePassword()) //
676 .keyStore(config.keyStore()) //
677 .keyPassword(config.keyPassword()) //
678 .isTrustStoreUsed(useTrustValidation) //
679 .trustStore(config.trustStore()) //
680 .trustStorePassword(config.trustStorePassword()) //
683 AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config);
684 return restClientFactory.createRestClient(baseUrl());
687 private AsyncRestClient restClient() {
688 return restClient(false);
691 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
692 testErrorCode(request, expStatus, responseContains, true);
695 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
696 boolean expectApplicationProblemJsonMediaType) {
697 StepVerifier.create(request) //
698 .expectSubscription() //
700 t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) //
704 private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
705 boolean expectApplicationProblemJsonMediaType) {
706 assertTrue(throwable instanceof WebClientResponseException);
707 WebClientResponseException responseException = (WebClientResponseException) throwable;
708 assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
709 assertThat(responseException.getResponseBodyAsString()).contains(responseContains);
710 if (expectApplicationProblemJsonMediaType) {
711 assertThat(responseException.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);