Add RequestId and InvocationId to DR
[dmaap/datarouter.git] / datarouter-node / src / test / java / org / onap / dmaap / datarouter / node / NodeServletTest.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 AT&T Intellectual Property. 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  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23 package org.onap.dmaap.datarouter.node;
24
25 import ch.qos.logback.classic.spi.ILoggingEvent;
26 import ch.qos.logback.core.read.ListAppender;
27 import ch.qos.logback.classic.Logger;
28 import org.apache.commons.lang3.reflect.FieldUtils;
29 import org.junit.*;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.powermock.api.mockito.PowerMockito;
33 import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
34 import org.powermock.modules.junit4.PowerMockRunner;
35 import org.slf4j.LoggerFactory;
36
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39
40 import java.util.*;
41
42 import static org.hamcrest.Matchers.notNullValue;
43 import static org.junit.Assert.assertEquals;
44 import static org.mockito.Matchers.eq;
45 import static org.mockito.Mockito.*;
46
47 @RunWith(PowerMockRunner.class)
48 @SuppressStaticInitializationFor("org.onap.dmaap.datarouter.node.NodeConfigManager")
49 public class NodeServletTest {
50
51     private NodeServlet nodeServlet;
52
53     @Mock
54     private HttpServletRequest request;
55
56     @Mock
57     private HttpServletResponse response;
58
59     ListAppender<ILoggingEvent> listAppender;
60
61     @Before
62     public void setUp() throws Exception{
63         listAppender = setTestLogger();
64         nodeServlet = new NodeServlet();
65         setBehalfHeader("Stub_Value");
66         when(request.getPathInfo()).thenReturn("2");
67         when(request.isSecure()).thenReturn(true);
68         setUpConfig();
69         setUpNodeMainDelivery();
70         when(request.getHeader("Authorization")).thenReturn("User1");
71         when(request.getHeader("X-ATT-DR-PUBLISH-ID")).thenReturn("User1");
72     }
73
74     @Test
75     public void Given_Request_Is_HTTP_GET_And_Config_Is_Down_Then_Service_Unavailable_Response_Is_Generated() throws Exception {
76         setNodeConfigManagerIsConfiguredToReturnFalse();
77         nodeServlet.doGet(request, response);
78         verify(response).sendError(eq(HttpServletResponse.SC_SERVICE_UNAVAILABLE));
79         verifyEnteringExitCalled(listAppender);
80     }
81
82     @Test
83     public void Given_Request_Is_HTTP_GET_And_Endpoint_Is_Internal_FetchProv_Then_No_Content_Response_Is_Generated() throws Exception {
84         when(request.getPathInfo()).thenReturn("/internal/fetchProv");
85         nodeServlet.doGet(request, response);
86         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
87         verifyEnteringExitCalled(listAppender);
88     }
89
90     @Test
91     public void Given_Request_Is_HTTP_GET_And_Endpoint_Is_ResetSubscription_Then_No_Content_Response_Is_Generated() throws Exception {
92         when(request.getPathInfo()).thenReturn("/internal/resetSubscription/1");
93         nodeServlet.doGet(request, response);
94         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
95         verifyEnteringExitCalled(listAppender);
96     }
97
98     @Test
99     public void Given_Request_Is_HTTP_GET_To_Invalid_Endpoint_Then_Not_Found_Response_Is_Generated() throws Exception {
100         when(request.getPathInfo()).thenReturn("/incorrect");
101         nodeServlet.doGet(request, response);
102         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND));
103         verifyEnteringExitCalled(listAppender);
104     }
105
106     @Test
107     public void Given_Request_Is_HTTP_PUT_And_Config_Is_Down_Then_Service_Unavailable_Response_Is_Generated() throws Exception {
108         setNodeConfigManagerIsConfiguredToReturnFalse();
109         nodeServlet.doPut(request, response);
110         verify(response).sendError(eq(HttpServletResponse.SC_SERVICE_UNAVAILABLE));
111         verifyEnteringExitCalled(listAppender);
112     }
113
114     @Test
115     public void Given_Request_Is_HTTP_PUT_And_Endpoint_Is_Incorrect_Then_Not_Found_Response_Is_Generated() throws Exception {
116         when(request.getPathInfo()).thenReturn("/incorrect/");
117         nodeServlet.doPut(request, response);
118         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
119         verifyEnteringExitCalled(listAppender);
120     }
121
122     @Test
123     public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Secure_Then_Forbidden_Response_Is_Generated() throws Exception {
124         when(request.isSecure()).thenReturn(false);
125         nodeServlet.doPut(request, response);
126         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
127         verifyEnteringExitCalled(listAppender);
128     }
129
130     @Test
131     public void Given_Request_Is_HTTP_PUT_And_File_Id_Is_Null_Then_Not_Found_Response_Is_Generated() throws Exception {
132         when(request.getPathInfo()).thenReturn(null);
133         nodeServlet.doPut(request, response);
134         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
135         verifyEnteringExitCalled(listAppender);
136     }
137
138     @Test
139     public void Given_Request_Is_HTTP_PUT_And_Authorization_Is_Null_Then_Forbidden_Response_Is_Generated() throws Exception {
140         when(request.getHeader("Authorization")).thenReturn(null);
141         nodeServlet.doPut(request, response);
142         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
143         verifyEnteringExitCalled(listAppender);
144     }
145
146     @Test
147     public void Given_Request_Is_HTTP_PUT_And_Publish_Does_Not_Include_File_Id_Then_Not_Found_Response_Is_Generated() throws Exception {
148         when(request.getPathInfo()).thenReturn("/publish/");
149         nodeServlet.doPut(request, response);
150         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
151         verifyEnteringExitCalled(listAppender);
152     }
153
154     @Test
155     public void Given_Request_Is_HTTP_PUT_And_Publish_Not_Permitted_Then_Forbidden_Response_Is_Generated() throws Exception {
156         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
157         setNodeConfigManagerIsPublishPermittedToReturnAReason();
158         nodeServlet.doPut(request, response);
159         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
160         verifyEnteringExitCalled(listAppender);
161     }
162
163     @Test
164     public void Given_Request_Is_HTTP_PUT_And_Internal_Publish_On_Same_Node_Then_Forbidden_Response_Is_Generated() throws Exception {
165         when(request.getPathInfo()).thenReturn("/internal/publish/1/fileName");
166         setNodeConfigManagerIsPublishPermittedToReturnAReason();
167         nodeServlet.doPut(request, response);
168         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN));
169         verifyEnteringExitCalled(listAppender);
170     }
171
172     @Test
173     public void Given_Request_Is_HTTP_PUT_And_Internal_Publish_But_Invalid_File_Id_Then_Not_Found_Response_Is_Generated() throws Exception {
174         when(request.getPathInfo()).thenReturn("/internal/publish/1/");
175         nodeServlet.doPut(request, response);
176         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
177         verifyEnteringExitCalled(listAppender);
178     }
179
180     @Test
181     public void Given_Request_Is_HTTP_PUT_On_Publish_And_Ingress_Node_Is_Provided_Then_Request_Is_Redirected() throws Exception {
182         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
183         setNodeConfigManagerToAllowRedirectOnIngressNode();
184         nodeServlet.doPut(request, response);
185         verify(response).sendRedirect(anyString());
186         verifyEnteringExitCalled(listAppender);
187     }
188
189     @Test
190     public void Given_Request_Is_HTTP_PUT_On_Publish_With_Meta_Data_Too_Long_Then_Bad_Request_Response_Is_Generated() throws Exception {
191         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
192         setHeadersForValidRequest(true);
193         nodeServlet.doPut(request, response);
194         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
195         verifyEnteringExitCalled(listAppender);
196     }
197
198     @Test
199     public void Given_Request_Is_HTTP_PUT_On_Publish_With_Meta_Data_Malformed_Then_Bad_Request_Response_Is_Generated() throws Exception {
200         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
201         setHeadersForValidRequest(false);
202         nodeServlet.doPut(request, response);
203         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
204         verifyEnteringExitCalled(listAppender);
205     }
206
207     @Test
208     public void Given_Request_Is_HTTP_DELETE_On_Publish_With_Meta_Data_Malformed_Then_Bad_Request_Response_Is_Generated() throws Exception {
209         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
210         setHeadersForValidRequest(false);
211         nodeServlet.doDelete(request, response);
212         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
213         verifyEnteringExitCalled(listAppender);
214     }
215
216
217     private void setBehalfHeader(String headerValue) {
218         when(request.getHeader("X-ATT-DR-ON-BEHALF-OF")).thenReturn(headerValue);
219     }
220
221     private ListAppender<ILoggingEvent> setTestLogger() {
222         Logger Logger = (Logger) LoggerFactory.getLogger(NodeServlet.class);
223         ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
224         listAppender.start();
225         Logger.addAppender(listAppender);
226         return listAppender;
227     }
228
229     private void verifyEnteringExitCalled(ListAppender<ILoggingEvent> listAppender) {
230         assertEquals("EELF0004I  Entering data router node component with RequestId and InvocationId", listAppender.list.get(0).getMessage());
231         assertEquals("EELF0005I  Exiting data router node component with RequestId and InvocationId", listAppender.list.get(2).getMessage());
232         assertEquals(3, listAppender.list.size());
233     }
234
235     private void setUpConfig() throws IllegalAccessException{
236         NodeConfigManager config = mock(NodeConfigManager.class);
237         PowerMockito.mockStatic(NodeConfigManager.class);
238         when(config.isShutdown()).thenReturn(false);
239         when(config.isConfigured()).thenReturn(true);
240         when(config.getSpoolDir()).thenReturn("spool/dir");
241         when(config.getLogDir()).thenReturn("log/dir");
242         when(config.getPublishId()).thenReturn("User1");
243         when(config.isAnotherNode(anyString(), anyString())).thenReturn(true);
244         when(config.getEventLogInterval()).thenReturn("40");
245         FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true);
246         FieldUtils.writeDeclaredStaticField(NodeMain.class, "nodeConfigManager", config, true);
247         PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config);
248     }
249
250
251     private void setUpNodeMainDelivery() throws IllegalAccessException{
252         Delivery delivery = mock(Delivery.class);
253         doNothing().when(delivery).resetQueue(anyObject());
254         FieldUtils.writeDeclaredStaticField(NodeMain.class, "delivery", delivery, true);
255     }
256
257     private void setNodeConfigManagerIsConfiguredToReturnFalse() throws IllegalAccessException{
258         NodeConfigManager config = mock(NodeConfigManager.class);
259         when(config.isConfigured()).thenReturn(false);
260         FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true);
261     }
262
263     private void setNodeConfigManagerIsPublishPermittedToReturnAReason() throws IllegalAccessException{
264         NodeConfigManager config = mock(NodeConfigManager.class);
265         when(config.isShutdown()).thenReturn(false);
266         when(config.isConfigured()).thenReturn(true);
267         when(config.getSpoolDir()).thenReturn("spool/dir");
268         when(config.getLogDir()).thenReturn("log/dir");
269         when(config.isPublishPermitted(anyString(), anyString(), anyString())).thenReturn("Not Permitted");
270         when(config.isAnotherNode(anyString(), anyString())).thenReturn(false);
271         FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true);
272     }
273
274     private void setNodeConfigManagerToAllowRedirectOnIngressNode() throws IllegalAccessException{
275         NodeConfigManager config = mock(NodeConfigManager.class);
276         when(config.isShutdown()).thenReturn(false);
277         when(config.isConfigured()).thenReturn(true);
278         when(config.getSpoolDir()).thenReturn("spool/dir");
279         when(config.getLogDir()).thenReturn("log/dir");
280         when(config.getPublishId()).thenReturn("User1");
281         when(config.isAnotherNode(anyString(), anyString())).thenReturn(true);
282         when(config.getAuthUser(anyString(), anyString())).thenReturn("User1");
283         when(config.getIngressNode(anyString(), anyString(), anyString())).thenReturn("NewNode");
284         when(config.getExtHttpsPort()).thenReturn(8080);
285         FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true);
286     }
287
288     private String createLargeMetaDataString() {
289         StringBuilder myString = new StringBuilder("meta");
290         for (int i = 0; i <= 4098; ++i) {
291             myString.append('x');
292         }
293         return myString.toString();
294     }
295
296     private void setHeadersForValidRequest(boolean isMetaTooLong) {
297         String metaDataString;
298         if (isMetaTooLong) {
299             metaDataString = createLargeMetaDataString();
300         } else {
301             metaDataString = "?#@><";
302         }
303         List<String> headers = new ArrayList<>();
304         headers.add("Content-Type");
305         headers.add("X-ATT-DR-ON-BEHALF-OF");
306         headers.add("X-ATT-DR-META");
307         Enumeration<String> headerNames = Collections.enumeration(headers);
308         when(request.getHeaderNames()).thenReturn(headerNames);
309         Enumeration<String> contentTypeHeader = Collections.enumeration(Arrays.asList("text/plain"));
310         Enumeration<String> behalfHeader = Collections.enumeration(Arrays.asList("User1"));
311         Enumeration<String> metaDataHeader = Collections.enumeration(Arrays.asList(metaDataString));
312         when(request.getHeaders("Content-Type")).thenReturn(contentTypeHeader);
313         when(request.getHeaders("X-ATT-DR-ON-BEHALF-OF")).thenReturn(behalfHeader);
314         when(request.getHeaders("X-ATT-DR-META")).thenReturn(metaDataHeader);
315     }
316 }