2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 Nokia. All rights reserved.s
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
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.onap.dcae.restapi;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.google.common.reflect.TypeToken;
25 import com.google.gson.Gson;
26 import com.networknt.schema.JsonSchema;
27 import io.vavr.collection.HashMap;
28 import org.apache.http.HttpStatus;
29 import org.jetbrains.annotations.NotNull;
30 import org.json.JSONObject;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.ArgumentCaptor;
35 import org.mockito.Mock;
36 import org.mockito.junit.MockitoJUnitRunner;
37 import org.onap.dcae.ApplicationSettings;
38 import org.onap.dcae.JSonSchemasSupplier;
39 import org.onap.dcae.common.EventSender;
40 import org.onap.dcae.common.EventTransformation;
41 import org.onap.dcae.common.HeaderUtils;
42 import org.onap.dcae.common.JsonDataLoader;
43 import org.onap.dcae.common.validator.StndDefinedDataValidator;
44 import org.onap.dcae.common.publishing.DMaaPEventPublisher;
45 import org.slf4j.Logger;
46 import org.springframework.http.ResponseEntity;
47 import org.springframework.mock.web.MockHttpServletRequest;
48 import org.springframework.web.context.request.RequestContextHolder;
49 import org.springframework.web.context.request.ServletRequestAttributes;
51 import java.io.FileReader;
52 import java.io.IOException;
53 import java.lang.reflect.Type;
54 import java.util.List;
57 import static org.assertj.core.api.Assertions.assertThat;
58 import static org.mockito.ArgumentMatchers.any;
59 import static org.mockito.ArgumentMatchers.anyString;
60 import static org.mockito.ArgumentMatchers.eq;
61 import static org.mockito.Mockito.never;
62 import static org.mockito.Mockito.times;
63 import static org.mockito.Mockito.verify;
64 import static org.mockito.Mockito.when;
66 @RunWith(MockitoJUnitRunner.class)
67 public class VesRestControllerTest {
69 private static final String EVENT_TRANSFORM_FILE_PATH = "/eventTransform.json";
70 private static final String ACCEPTED = "Accepted";
71 private static final String VERSION_V7 = "v7";
72 public static final String VES_FAULT_TOPIC = "ves-fault";
73 public static final String VES_3_GPP_FAULT_SUPERVISION_TOPIC = "ves-3gpp-fault-supervision";
75 private VesRestController vesRestController;
78 private ApplicationSettings applicationSettings;
81 private Logger logger;
84 private HeaderUtils headerUtils;
87 private DMaaPEventPublisher eventPublisher;
90 private StndDefinedDataValidator stndDefinedDataValidator;
94 final HashMap<String, String[]> streamIds = HashMap.of(
95 "fault", new String[]{VES_FAULT_TOPIC},
96 "3GPP-FaultSupervision", new String[]{VES_3_GPP_FAULT_SUPERVISION_TOPIC}
98 this.vesRestController = new VesRestController(applicationSettings, logger,
99 new EventSender(eventPublisher, streamIds), headerUtils, stndDefinedDataValidator);
103 public void shouldReportThatApiVersionIsNotSupported() {
105 when(applicationSettings.isVersionSupported("v20")).thenReturn(false);
106 MockHttpServletRequest request = givenMockHttpServletRequest();
109 final ResponseEntity<String> event = vesRestController.event("", "v20", request);
112 assertThat(event.getStatusCodeValue()).isEqualTo(HttpStatus.SC_BAD_REQUEST);
113 assertThat(event.getBody()).isEqualTo("API version v20 is not supported");
114 verifyThatEventWasNotSend();
118 public void shouldTransformEventAccordingToEventTransformFile() throws IOException {
120 configureEventTransformations();
121 configureHeadersForEventListener();
123 MockHttpServletRequest request = givenMockHttpServletRequest();
125 String validEvent = JsonDataLoader.loadContent("/ves7_valid_30_1_1_event.json");
128 final ResponseEntity<String> response = vesRestController.event(validEvent, VERSION_V7, request);
131 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
132 assertThat(response.getBody()).isEqualTo(ACCEPTED);
133 verifyThatTransformedEventWasSend(eventPublisher, validEvent);
138 public void shouldSendBatchOfEvents() throws IOException {
140 configureEventTransformations();
141 configureHeadersForEventListener();
143 MockHttpServletRequest request = givenMockHttpServletRequest();
145 String validEvent = JsonDataLoader.loadContent("/ves7_batch_valid.json");
148 final ResponseEntity<String> response = vesRestController.events(validEvent, VERSION_V7, request);
151 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
152 assertThat(response.getBody()).isEqualTo(ACCEPTED);
153 verify(eventPublisher, times(2)).sendEvent(any(),any());
157 public void shouldSendStndDomainEventIntoDomainStream() throws IOException {
159 configureEventTransformations();
160 configureHeadersForEventListener();
162 MockHttpServletRequest request = givenMockHttpServletRequest();
163 configureSchemasSupplierForStndDefineEvent();
165 String validEvent = JsonDataLoader.loadContent("/ves_stdnDefined_valid.json");
168 final ResponseEntity<String> response = vesRestController.event(validEvent, VERSION_V7, request);
171 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
172 assertThat(response.getBody()).isEqualTo(ACCEPTED);
173 verify(eventPublisher).sendEvent(any(),eq(VES_3_GPP_FAULT_SUPERVISION_TOPIC));
178 public void shouldReportThatStndDomainEventHasntGotNamespaceParameter() throws IOException {
180 configureEventTransformations();
181 configureHeadersForEventListener();
183 MockHttpServletRequest request = givenMockHttpServletRequest();
184 configureSchemasSupplierForStndDefineEvent();
186 String validEvent = JsonDataLoader.loadContent("/ves_stdnDefined_missing_namespace_invalid.json");
189 final ResponseEntity<String> response = vesRestController.event(validEvent, VERSION_V7, request);
192 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_BAD_REQUEST);
196 "Mandatory input %1 %2 is missing from request",
197 List.of("attribute", "event.commonEventHeader.stndDefinedNamespace")
199 verifyThatEventWasNotSend();
203 public void shouldReportThatStndDomainEventNamespaceParameterIsEmpty() throws IOException {
205 configureEventTransformations();
206 configureHeadersForEventListener();
208 MockHttpServletRequest request = givenMockHttpServletRequest();
209 configureSchemasSupplierForStndDefineEvent();
211 String validEvent = JsonDataLoader.loadContent("/ves_stdnDefined_empty_namespace_invalid.json");
214 final ResponseEntity<String> response = vesRestController.event(validEvent, VERSION_V7, request);
217 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_BAD_REQUEST);
221 "Mandatory input %1 %2 is empty in request",
222 List.of("attribute", "event.commonEventHeader.stndDefinedNamespace")
224 verifyThatEventWasNotSend();
228 public void shouldNotSendStndDomainEventWhenTopicCannotBeFoundInConfiguration() throws IOException {
230 configureEventTransformations();
231 configureHeadersForEventListener();
233 MockHttpServletRequest request = givenMockHttpServletRequest();
234 String validEvent = JsonDataLoader.loadContent("/ves_stdnDefined_valid_unknown_topic.json");
237 final ResponseEntity<String> response = vesRestController.event(validEvent, VERSION_V7, request);
240 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
241 assertThat(response.getBody()).isEqualTo(ACCEPTED);
242 verifyThatEventWasNotSend();
246 public void shouldExecuteStndDefinedValidationWhenFlagIsOnTrue() throws IOException {
248 configureEventTransformations();
249 configureHeadersForEventListener();
251 MockHttpServletRequest request = givenMockHttpServletRequest();
252 String validEvent = JsonDataLoader.loadContent("/ves7_batch_with_stndDefined_valid.json");
253 when(applicationSettings.getExternalSchemaValidationCheckflag()).thenReturn(true);
256 final ResponseEntity<String> response = vesRestController.events(validEvent, VERSION_V7, request);
259 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
260 assertThat(response.getBody()).isEqualTo(ACCEPTED);
261 verify(stndDefinedDataValidator, times(2)).validate(any());
265 public void shouldNotExecuteStndDefinedValidationWhenFlagIsOnFalse() throws IOException {
267 configureEventTransformations();
268 configureHeadersForEventListener();
270 MockHttpServletRequest request = givenMockHttpServletRequest();
271 String validEvent = JsonDataLoader.loadContent("/ves7_batch_with_stndDefined_valid.json");
272 when(applicationSettings.getExternalSchemaValidationCheckflag()).thenReturn(false);
275 final ResponseEntity<String> response = vesRestController.events(validEvent, VERSION_V7, request);
278 assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED);
279 assertThat(response.getBody()).isEqualTo(ACCEPTED);
280 verify(stndDefinedDataValidator, times(0)).validate(any());
283 private void verifyThatEventWasNotSend() {
284 verify(eventPublisher, never()).sendEvent(any(), any());
287 private void configureSchemasSupplierForStndDefineEvent() {
288 String collectorSchemaFile = "{\"v7\":\"./etc/CommonEventFormat_30.2_ONAP.json\"}";
289 final io.vavr.collection.Map<String, JsonSchema> loadedJsonSchemas = new JSonSchemasSupplier().loadJsonSchemas(collectorSchemaFile);
291 when(applicationSettings.eventSchemaValidationEnabled()).thenReturn(true);
292 when(applicationSettings.jsonSchema(eq(VERSION_V7))).thenReturn(loadedJsonSchemas.get(VERSION_V7).get());
295 private void verifyErrorResponse(ResponseEntity<String> response, String messageId, String messageText, List<String> variables) throws com.fasterxml.jackson.core.JsonProcessingException {
296 final Map<String, ?> errorDetails = fetchErrorDetails(response);
297 assertThat((Map<String, String>)errorDetails).containsEntry("messageId", messageId);
298 assertThat((Map<String, String>)errorDetails).containsEntry("text", messageText);
299 assertThat((Map<String, List<String>>)errorDetails).containsEntry("variables", variables);
302 private Map<String, ?> fetchErrorDetails(ResponseEntity<String> response) throws com.fasterxml.jackson.core.JsonProcessingException {
303 final String body = response.getBody();
304 ObjectMapper mapper = new ObjectMapper();
305 Map<String, Map<String, Map<String,String>>> map = mapper.readValue(body, Map.class);
306 return map.get("requestError").get("ServiceException");
309 private void configureEventTransformations() throws IOException {
310 final List<EventTransformation> eventTransformations = loadEventTransformations();
311 when(applicationSettings.isVersionSupported(VERSION_V7)).thenReturn(true);
312 when(applicationSettings.eventTransformingEnabled()).thenReturn(true);
313 when(applicationSettings.getEventTransformations()).thenReturn(eventTransformations);
316 private void configureHeadersForEventListener() {
317 when(headerUtils.getRestApiIdentify(anyString())).thenReturn("eventListener");
318 when(headerUtils.getApiVerFilePath(anyString())).thenReturn(
319 this.getClass().getResource("/api_version_config.json").getPath()
323 private void verifyThatTransformedEventWasSend(DMaaPEventPublisher eventPublisher, String eventBeforeTransformation) {
324 // event before transformation
325 assertThat(eventBeforeTransformation).contains("\"version\": \"4.0.1\"");
326 assertThat(eventBeforeTransformation).contains("\"faultFieldsVersion\": \"4.0\"");
328 ArgumentCaptor<JSONObject> argument = ArgumentCaptor.forClass(JSONObject.class);
329 ArgumentCaptor<String> domain = ArgumentCaptor.forClass(String.class);
330 verify(eventPublisher).sendEvent(argument.capture(), domain.capture());
332 final String transformedEvent = argument.getValue().toString();
333 final String eventSentAtTopic = domain.getValue();
335 // event after transformation
336 assertThat(transformedEvent).contains("\"priority\":\"High\",\"version\":3,");
337 assertThat(transformedEvent).contains(",\"faultFieldsVersion\":3,\"specificProblem");
338 assertThat(eventSentAtTopic).isEqualTo(VES_FAULT_TOPIC);
342 private MockHttpServletRequest givenMockHttpServletRequest() {
343 MockHttpServletRequest request = new MockHttpServletRequest();
344 request.setContentType("application/json");
346 RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
350 private List<EventTransformation> loadEventTransformations() throws IOException {
351 Type EVENT_TRANSFORM_LIST_TYPE = new TypeToken<List<EventTransformation>>() {
354 try (FileReader fr = new FileReader(this.getClass().getResource(EVENT_TRANSFORM_FILE_PATH).getPath())) {
355 return new Gson().fromJson(fr, EVENT_TRANSFORM_LIST_TYPE);