1 /*******************************************************************************
2 * ============LICENSE_START==================================================
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
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====================================================
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 ******************************************************************************/
23 package org.onap.dmaap.datarouter.provisioning;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.Mockito.contains;
27 import static org.mockito.Mockito.eq;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
33 import ch.qos.logback.classic.spi.ILoggingEvent;
34 import ch.qos.logback.core.read.ListAppender;
35 import jakarta.servlet.ServletInputStream;
36 import jakarta.servlet.ServletOutputStream;
37 import jakarta.servlet.http.HttpServletRequest;
38 import jakarta.servlet.http.HttpServletResponse;
39 import java.sql.Connection;
40 import java.sql.SQLException;
41 import java.util.HashSet;
43 import javax.persistence.EntityManager;
44 import javax.persistence.EntityManagerFactory;
45 import javax.persistence.Persistence;
46 import org.apache.commons.lang3.reflect.FieldUtils;
47 import org.jetbrains.annotations.NotNull;
48 import org.json.JSONArray;
49 import org.json.JSONObject;
50 import org.junit.AfterClass;
51 import org.junit.Before;
52 import org.junit.BeforeClass;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Mock;
56 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
57 import org.onap.dmaap.datarouter.authz.Authorizer;
58 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
59 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
60 import org.onap.dmaap.datarouter.provisioning.utils.ProvDbUtils;
61 import org.powermock.core.classloader.annotations.PowerMockIgnore;
62 import org.powermock.modules.junit4.PowerMockRunner;
65 @RunWith(PowerMockRunner.class)
66 @PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*", "com.sun.org.apache.xalan.*"})
67 public class FeedServletTest extends DrServletTestBase {
69 private static FeedServlet feedServlet;
72 private HttpServletRequest request;
74 private HttpServletResponse response;
76 private static EntityManagerFactory emf;
77 private static EntityManager em;
79 private ListAppender<ILoggingEvent> listAppender;
82 public static void init() {
83 emf = Persistence.createEntityManagerFactory("dr-unit-tests");
84 em = emf.createEntityManager();
86 "org.onap.dmaap.datarouter.provserver.properties",
87 "src/test/resources/h2Database.properties");
91 public static void tearDownClass() {
98 public void setUp() throws Exception {
99 listAppender = setTestLogger(FeedServlet.class);
100 feedServlet = new FeedServlet();
101 setAuthoriserToReturnRequestIsAuthorized();
102 setUpValidAuthorisedRequest();
103 setUpValidSecurityOnHttpRequest();
104 setUpValidContentHeadersAndJSONOnHttpRequest();
108 public void Given_Request_Is_HTTP_DELETE_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
110 when(request.isSecure()).thenReturn(false);
111 feedServlet.doDelete(request, response);
112 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
113 verifyEnteringExitCalled(listAppender);
117 public void Given_Request_Is_HTTP_DELETE_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
119 setBehalfHeader(null);
120 feedServlet.doDelete(request, response);
121 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
125 public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
126 when(request.getPathInfo()).thenReturn(null);
127 feedServlet.doDelete(request, response);
128 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
132 public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
133 when(request.getPathInfo()).thenReturn("/123");
134 feedServlet.doDelete(request, response);
135 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
139 public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
140 setAuthoriserToReturnRequestNotAuthorized();
141 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", true, true);
142 feedServlet.doDelete(request, response);
143 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
147 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Fails_An_Internal_Server_Error_Is_Reported()
149 FeedServlet feedServlet = new FeedServlet() {
150 protected boolean doUpdate(Updateable bean) {
154 feedServlet.doDelete(request, response);
156 .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), anyString());
160 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
161 feedServlet.doDelete(request, response);
162 verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
163 reinsertFeedIntoDb();
164 verifyEnteringExitCalled(listAppender);
168 public void Given_Request_Is_HTTP_GET_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
170 when(request.isSecure()).thenReturn(false);
171 feedServlet.doGet(request, response);
172 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
173 verifyEnteringExitCalled(listAppender);
177 public void Given_Request_Is_HTTP_GET_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
179 setBehalfHeader(null);
180 feedServlet.doGet(request, response);
181 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
185 public void Given_Request_Is_HTTP_GET_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
187 when(request.getPathInfo()).thenReturn(null);
188 feedServlet.doGet(request, response);
189 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
193 public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
195 when(request.getPathInfo()).thenReturn("/123");
196 feedServlet.doGet(request, response);
197 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
201 public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
203 setAuthoriserToReturnRequestNotAuthorized();
204 when(request.getPathInfo()).thenReturn("/2");
205 feedServlet.doGet(request, response);
206 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
210 public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
211 ServletOutputStream outStream = mock(ServletOutputStream.class);
212 when(response.getOutputStream()).thenReturn(outStream);
213 when(request.getPathInfo()).thenReturn("/2");
214 feedServlet.doGet(request, response);
215 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
216 verifyEnteringExitCalled(listAppender);
220 public void Given_Request_Is_HTTP_PUT_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
222 when(request.isSecure()).thenReturn(false);
223 feedServlet.doPut(request, response);
224 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
225 verifyEnteringExitCalled(listAppender);
229 public void Given_Request_Is_HTTP_PUT_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
231 setBehalfHeader(null);
232 feedServlet.doPut(request, response);
233 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
237 public void Given_Request_Is_HTTP_PUT_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
239 when(request.getPathInfo()).thenReturn(null);
240 feedServlet.doPut(request, response);
241 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
245 public void Given_Request_Is_HTTP_PUT_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
247 when(request.getPathInfo()).thenReturn("/123");
248 feedServlet.doPut(request, response);
249 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
253 public void Given_Request_Is_HTTP_PUT_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated()
255 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed-fail; version=2.0");
256 when(request.getContentType()).thenReturn("stub_contentType");
257 when(request.getPathInfo()).thenReturn("/2");
258 feedServlet.doPut(request, response);
259 verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), anyString());
263 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
265 ServletInputStream inStream = mock(ServletInputStream.class);
266 when(request.getInputStream()).thenReturn(inStream);
267 when(request.getPathInfo()).thenReturn("/2");
268 FeedServlet feedServlet = new FeedServlet() {
269 public JSONObject getJSONfromInput(HttpServletRequest req) {
273 feedServlet.doPut(request, response);
274 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("Badly formed JSON"));
278 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Invalid_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
279 when(request.getPathInfo()).thenReturn("/2");
280 FeedServlet feedServlet = new FeedServlet() {
281 public JSONObject getJSONfromInput(HttpServletRequest req) {
282 return new JSONObject();
285 feedServlet.doPut(request, response);
286 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
290 public void Given_Request_Is_HTTP_PUT_And_Feed_Change_Is_Not_Publisher_Who_Requested_Feed_Bad_Request_Response_Is_Generated() throws Exception {
291 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
292 when(request.getPathInfo()).thenReturn("/2");
293 JSONObject JSObject = buildRequestJsonObject();
294 FeedServlet feedServlet = new FeedServlet() {
295 public JSONObject getJSONfromInput(HttpServletRequest req) {
296 JSONObject jo = new JSONObject();
297 jo.put("name", "stub_name");
298 jo.put("version", "1.0");
299 jo.put("authorization", JSObject);
303 feedServlet.doPut(request, response);
304 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("must be modified by the same publisher"));
308 public void Given_Request_Is_HTTP_PUT_And_Feed_Name_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
309 when(request.getPathInfo()).thenReturn("/2");
310 JSONObject JSObject = buildRequestJsonObject();
311 FeedServlet feedServlet = new FeedServlet() {
312 public JSONObject getJSONfromInput(HttpServletRequest req) {
313 JSONObject jo = new JSONObject();
314 jo.put("name", "not_stub_name");
315 jo.put("version", "1.0");
316 jo.put("authorization", JSObject);
320 feedServlet.doPut(request, response);
321 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("name of the feed may not be updated"));
325 public void Given_Request_Is_HTTP_PUT_And_Feed_Version_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
326 when(request.getPathInfo()).thenReturn("/2");
327 JSONObject JSObject = buildRequestJsonObject();
328 FeedServlet feedServlet = new FeedServlet() {
329 public JSONObject getJSONfromInput(HttpServletRequest req) {
330 JSONObject jo = new JSONObject();
331 jo.put("name", "Feed22");
332 jo.put("version", "v0.2");
333 jo.put("authorization", JSObject);
337 feedServlet.doPut(request, response);
338 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("version of the feed may not be updated"));
342 public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
343 setAuthoriserToReturnRequestNotAuthorized();
344 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", true, true);
345 when(request.getPathInfo()).thenReturn("/2");
346 JSONObject JSObject = buildRequestJsonObject();
347 FeedServlet feedServlet = new FeedServlet() {
348 public JSONObject getJSONfromInput(HttpServletRequest req) {
349 JSONObject jo = new JSONObject();
350 jo.put("name", "Feed22");
351 jo.put("version", "v0.1");
352 jo.put("authorization", JSObject);
356 feedServlet.doPut(request, response);
357 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Client certificate is missing."));
361 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
362 ServletOutputStream outStream = mock(ServletOutputStream.class);
363 when(response.getOutputStream()).thenReturn(outStream);
364 when(request.getPathInfo()).thenReturn("/2");
365 JSONObject JSObject = buildRequestJsonObject();
366 FeedServlet feedServlet = new FeedServlet() {
367 public JSONObject getJSONfromInput(HttpServletRequest req) {
368 JSONObject jo = new JSONObject();
369 jo.put("name", "Feed22");
370 jo.put("version", "v0.1");
371 jo.put("authorization", JSObject);
376 protected boolean doUpdate(Updateable bean) {
380 feedServlet.doPut(request, response);
381 verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), anyString());
385 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Suceeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
386 ServletOutputStream outStream = mock(ServletOutputStream.class);
387 when(response.getOutputStream()).thenReturn(outStream);
388 when(request.getPathInfo()).thenReturn("/2");
389 JSONObject JSObject = buildRequestJsonObject();
390 FeedServlet feedServlet = new FeedServlet() {
391 public JSONObject getJSONfromInput(HttpServletRequest req) {
392 JSONObject jo = new JSONObject();
393 jo.put("name", "Feed22");
394 jo.put("version", "v0.1");
395 jo.put("authorization", JSObject);
399 protected boolean doUpdate(Updateable bean) {
404 feedServlet.doPut(request, response);
405 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
406 verifyEnteringExitCalled(listAppender);
410 public void Given_Request_Is_HTTP_POST_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
411 feedServlet.doPost(request, response);
412 verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), anyString());
413 verifyEnteringExitCalled(listAppender);
417 private JSONObject buildRequestJsonObject() {
418 JSONObject JSObject = new JSONObject();
419 JSONArray endpointIDs = new JSONArray();
420 JSONObject JOEndpointIDs = new JSONObject();
421 JOEndpointIDs.put("id", "stub_endpoint_id");
422 JOEndpointIDs.put("password", "stub_endpoint_password");
423 endpointIDs.put(JOEndpointIDs);
425 JSONArray endpointAddresses = new JSONArray();
426 endpointAddresses.put("127.0.0.1");
428 JSObject.put("classification", "stub_classification");
429 JSObject.put("endpoint_ids", endpointIDs);
430 JSObject.put("endpoint_addrs", endpointAddresses);
434 private void setUpValidSecurityOnHttpRequest() throws Exception {
435 when(request.isSecure()).thenReturn(true);
436 Set<String> authAddressesAndNetworks = new HashSet<>();
437 authAddressesAndNetworks.add(("127.0.0.1"));
438 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,true);
439 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
442 private void setBehalfHeader(String headerValue) {
443 when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
446 private void setValidPathInfoInHttpHeader() {
447 when(request.getPathInfo()).thenReturn("/1");
450 private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
451 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
452 Authorizer authorizer = mock(Authorizer.class);
453 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
454 when(authorizer.decide(request)).thenReturn(authResponse);
455 when(authResponse.isAuthorized()).thenReturn(false);
458 private void setAuthoriserToReturnRequestIsAuthorized() throws IllegalAccessException {
459 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
460 Authorizer authorizer = mock(Authorizer.class);
461 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
462 when(authorizer.decide(request)).thenReturn(authResponse);
463 when(authResponse.isAuthorized()).thenReturn(true);
466 private void setUpValidAuthorisedRequest() throws Exception {
467 setUpValidSecurityOnHttpRequest();
468 setBehalfHeader("Stub_Value");
469 setValidPathInfoInHttpHeader();
472 private void setUpValidContentHeadersAndJSONOnHttpRequest() {
473 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
474 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
477 private void reinsertFeedIntoDb() throws SQLException {
478 Feed feed = new Feed("Feed1","v0.1", "First Feed for testing", "First Feed for testing");
481 feed.setDeleted(false);
482 try (Connection conn = ProvDbUtils.getInstance().getConnection()) {