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 ch.qos.logback.classic.spi.ILoggingEvent;
26 import ch.qos.logback.core.read.ListAppender;
27 import org.apache.commons.lang3.reflect.FieldUtils;
28 import org.jetbrains.annotations.NotNull;
29 import org.json.JSONArray;
30 import org.json.JSONObject;
31 import org.junit.AfterClass;
32 import org.junit.Before;
33 import org.junit.BeforeClass;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.mockito.Mock;
37 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
38 import org.onap.dmaap.datarouter.authz.Authorizer;
39 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
40 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
41 import org.onap.dmaap.datarouter.provisioning.utils.DB;
42 import org.powermock.modules.junit4.PowerMockRunner;
44 import javax.persistence.EntityManager;
45 import javax.persistence.EntityManagerFactory;
46 import javax.persistence.Persistence;
47 import javax.servlet.ServletInputStream;
48 import javax.servlet.ServletOutputStream;
49 import javax.servlet.http.HttpServletRequest;
50 import javax.servlet.http.HttpServletResponse;
51 import java.sql.SQLException;
52 import java.util.HashSet;
55 import static org.hamcrest.Matchers.notNullValue;
56 import static org.mockito.Mockito.*;
57 import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
60 @RunWith(PowerMockRunner.class)
61 public class FeedServletTest extends DrServletTestBase {
63 private static FeedServlet feedServlet;
66 private HttpServletRequest request;
68 private HttpServletResponse response;
70 private static EntityManagerFactory emf;
71 private static EntityManager em;
74 private ListAppender<ILoggingEvent> listAppender;
77 public static void init() {
78 emf = Persistence.createEntityManagerFactory("dr-unit-tests");
79 em = emf.createEntityManager();
81 "org.onap.dmaap.datarouter.provserver.properties",
82 "src/test/resources/h2Database.properties");
86 public static void tearDownClass() {
93 public void setUp() throws Exception {
94 listAppender = setTestLogger(FeedServlet.class);
95 feedServlet = new FeedServlet();
97 setAuthoriserToReturnRequestIsAuthorized();
98 setUpValidAuthorisedRequest();
99 setUpValidSecurityOnHttpRequest();
100 setUpValidContentHeadersAndJSONOnHttpRequest();
104 public void Given_Request_Is_HTTP_DELETE_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
106 when(request.isSecure()).thenReturn(false);
107 feedServlet.doDelete(request, response);
108 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
109 verifyEnteringExitCalled(listAppender);
113 public void Given_Request_Is_HTTP_DELETE_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
115 setBehalfHeader(null);
116 feedServlet.doDelete(request, response);
117 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
121 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 {
122 when(request.getPathInfo()).thenReturn(null);
123 feedServlet.doDelete(request, response);
124 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
128 public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
129 when(request.getPathInfo()).thenReturn("/123");
130 feedServlet.doDelete(request, response);
131 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
135 public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
136 setAuthoriserToReturnRequestNotAuthorized();
137 feedServlet.doDelete(request, response);
138 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
142 public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
143 when(request.getPathInfo()).thenReturn("/2");
144 feedServlet.doDelete(request, response);
145 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
149 public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() {
150 when(request.getPathInfo()).thenReturn("/3");
151 when(request.isUserInRole("org.onap.dmaap-dr.feed|*|delete")).thenReturn(true);
152 feedServlet.doDelete(request, response);
153 verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
154 verifyEnteringExitCalled(listAppender);
158 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Fails_An_Internal_Server_Error_Is_Reported()
160 FeedServlet feedServlet = new FeedServlet() {
161 protected boolean doUpdate(Updateable bean) {
165 feedServlet.doDelete(request, response);
167 .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
171 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
172 feedServlet.doDelete(request, response);
173 verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
174 reinsertFeedIntoDb();
175 verifyEnteringExitCalled(listAppender);
179 public void Given_Request_Is_HTTP_GET_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
181 when(request.isSecure()).thenReturn(false);
182 feedServlet.doGet(request, response);
183 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
184 verifyEnteringExitCalled(listAppender);
188 public void Given_Request_Is_HTTP_GET_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
190 setBehalfHeader(null);
191 feedServlet.doGet(request, response);
192 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
196 public void Given_Request_Is_HTTP_GET_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
198 when(request.getPathInfo()).thenReturn(null);
199 feedServlet.doGet(request, response);
200 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
204 public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
206 when(request.getPathInfo()).thenReturn("/123");
207 feedServlet.doGet(request, response);
208 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
212 public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
214 setAuthoriserToReturnRequestNotAuthorized();
215 when(request.getPathInfo()).thenReturn("/2");
216 feedServlet.doGet(request, response);
217 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
221 public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
222 ServletOutputStream outStream = mock(ServletOutputStream.class);
223 when(response.getOutputStream()).thenReturn(outStream);
224 when(request.getPathInfo()).thenReturn("/2");
225 feedServlet.doGet(request, response);
226 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
227 verifyEnteringExitCalled(listAppender);
231 public void Given_Request_Is_HTTP_PUT_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
233 when(request.isSecure()).thenReturn(false);
234 feedServlet.doPut(request, response);
235 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
236 verifyEnteringExitCalled(listAppender);
240 public void Given_Request_Is_HTTP_PUT_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
242 setBehalfHeader(null);
243 feedServlet.doPut(request, response);
244 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
248 public void Given_Request_Is_HTTP_PUT_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
250 when(request.getPathInfo()).thenReturn(null);
251 feedServlet.doPut(request, response);
252 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
256 public void Given_Request_Is_HTTP_PUT_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
258 when(request.getPathInfo()).thenReturn("/123");
259 feedServlet.doPut(request, response);
260 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
264 public void Given_Request_Is_HTTP_PUT_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated()
266 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed-fail; version=2.0");
267 when(request.getContentType()).thenReturn("stub_contentType");
268 when(request.getPathInfo()).thenReturn("/2");
269 feedServlet.doPut(request, response);
270 verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
274 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
276 ServletInputStream inStream = mock(ServletInputStream.class);
277 when(request.getInputStream()).thenReturn(inStream);
278 when(request.getPathInfo()).thenReturn("/2");
279 FeedServlet feedServlet = new FeedServlet() {
280 protected JSONObject getJSONfromInput(HttpServletRequest req) {
284 feedServlet.doPut(request, response);
285 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("Badly formed JSON"));
289 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Invalid_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
290 when(request.getPathInfo()).thenReturn("/2");
291 FeedServlet feedServlet = new FeedServlet() {
292 protected JSONObject getJSONfromInput(HttpServletRequest req) {
293 return new JSONObject();
296 feedServlet.doPut(request, response);
297 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
301 public void Given_Request_Is_HTTP_PUT_And_Feed_Change_Is_Not_Publisher_Who_Requested_Feed_Bad_Request_Response_Is_Generated() throws Exception {
302 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
303 when(request.getPathInfo()).thenReturn("/2");
304 JSONObject JSObject = buildRequestJsonObject();
305 FeedServlet feedServlet = new FeedServlet() {
306 protected JSONObject getJSONfromInput(HttpServletRequest req) {
307 JSONObject jo = new JSONObject();
308 jo.put("name", "stub_name");
309 jo.put("version", "1.0");
310 jo.put("authorization", JSObject);
314 feedServlet.doPut(request, response);
315 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("must be modified by the same publisher"));
319 public void Given_Request_Is_HTTP_PUT_And_Feed_Name_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
320 when(request.getPathInfo()).thenReturn("/2");
321 JSONObject JSObject = buildRequestJsonObject();
322 FeedServlet feedServlet = new FeedServlet() {
323 protected JSONObject getJSONfromInput(HttpServletRequest req) {
324 JSONObject jo = new JSONObject();
325 jo.put("name", "not_stub_name");
326 jo.put("version", "1.0");
327 jo.put("authorization", JSObject);
331 feedServlet.doPut(request, response);
332 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("name of the feed may not be updated"));
336 public void Given_Request_Is_HTTP_PUT_And_Feed_Version_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
337 when(request.getPathInfo()).thenReturn("/2");
338 JSONObject JSObject = buildRequestJsonObject();
339 FeedServlet feedServlet = new FeedServlet() {
340 protected JSONObject getJSONfromInput(HttpServletRequest req) {
341 JSONObject jo = new JSONObject();
342 jo.put("name", "AafFeed");
343 jo.put("version", "v0.2");
344 jo.put("authorization", JSObject);
348 feedServlet.doPut(request, response);
349 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("version of the feed may not be updated"));
353 public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
354 setAuthoriserToReturnRequestNotAuthorized();
355 when(request.getPathInfo()).thenReturn("/2");
356 JSONObject JSObject = buildRequestJsonObject();
357 FeedServlet feedServlet = new FeedServlet() {
358 protected JSONObject getJSONfromInput(HttpServletRequest req) {
359 JSONObject jo = new JSONObject();
360 jo.put("name", "AafFeed");
361 jo.put("version", "v0.1");
362 jo.put("authorization", JSObject);
366 feedServlet.doPut(request, response);
367 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access"));
371 public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
372 when(request.getPathInfo()).thenReturn("/2");
373 JSONObject JSObject = buildRequestJsonObject();
374 FeedServlet feedServlet = new FeedServlet() {
375 protected JSONObject getJSONfromInput(HttpServletRequest req) {
376 JSONObject jo = new JSONObject();
377 jo.put("name", "AafFeed");
378 jo.put("version", "v0.1");
379 jo.put("authorization", JSObject);
380 jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
384 feedServlet.doPut(request, response);
385 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
389 public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_With_Permissions_Then_STATUS_OK__Response_Is_Generated() throws Exception {
390 ServletOutputStream outStream = mock(ServletOutputStream.class);
391 when(response.getOutputStream()).thenReturn(outStream);
392 when(request.getPathInfo()).thenReturn("/2");
393 when(request.isUserInRole("org.onap.dmaap-dr.feed|*|edit")).thenReturn(true);
394 JSONObject JSObject = buildRequestJsonObject();
395 FeedServlet feedServlet = new FeedServlet() {
396 protected JSONObject getJSONfromInput(HttpServletRequest req) {
397 JSONObject jo = new JSONObject();
398 jo.put("name", "AafFeed");
399 jo.put("version", "v0.1");
400 jo.put("authorization", JSObject);
401 jo.put("aaf_instance", "*");
405 protected boolean doUpdate(Updateable bean) {
410 feedServlet.doPut(request, response);
411 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
412 verifyEnteringExitCalled(listAppender);
416 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
417 ServletOutputStream outStream = mock(ServletOutputStream.class);
418 when(response.getOutputStream()).thenReturn(outStream);
419 when(request.getPathInfo()).thenReturn("/2");
420 JSONObject JSObject = buildRequestJsonObject();
421 FeedServlet feedServlet = new FeedServlet() {
422 protected JSONObject getJSONfromInput(HttpServletRequest req) {
423 JSONObject jo = new JSONObject();
424 jo.put("name", "AafFeed");
425 jo.put("version", "v0.1");
426 jo.put("authorization", JSObject);
431 protected boolean doUpdate(Updateable bean) {
435 feedServlet.doPut(request, response);
436 verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
440 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Suceeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
441 ServletOutputStream outStream = mock(ServletOutputStream.class);
442 when(response.getOutputStream()).thenReturn(outStream);
443 when(request.getPathInfo()).thenReturn("/2");
444 JSONObject JSObject = buildRequestJsonObject();
445 FeedServlet feedServlet = new FeedServlet() {
446 protected JSONObject getJSONfromInput(HttpServletRequest req) {
447 JSONObject jo = new JSONObject();
448 jo.put("name", "AafFeed");
449 jo.put("version", "v0.1");
450 jo.put("authorization", JSObject);
454 protected boolean doUpdate(Updateable bean) {
459 feedServlet.doPut(request, response);
460 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
461 verifyEnteringExitCalled(listAppender);
465 public void Given_Request_Is_HTTP_POST_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
466 feedServlet.doPost(request, response);
467 verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), argThat(notNullValue(String.class)));
468 verifyEnteringExitCalled(listAppender);
472 private JSONObject buildRequestJsonObject() {
473 JSONObject JSObject = new JSONObject();
474 JSONArray endpointIDs = new JSONArray();
475 JSONObject JOEndpointIDs = new JSONObject();
476 JOEndpointIDs.put("id", "stub_endpoint_id");
477 JOEndpointIDs.put("password", "stub_endpoint_password");
478 endpointIDs.put(JOEndpointIDs);
480 JSONArray endpointAddresses = new JSONArray();
481 endpointAddresses.put("127.0.0.1");
483 JSObject.put("classification", "stub_classification");
484 JSObject.put("endpoint_ids", endpointIDs);
485 JSObject.put("endpoint_addrs", endpointAddresses);
489 private void setUpValidSecurityOnHttpRequest() throws Exception {
490 when(request.isSecure()).thenReturn(true);
491 Set<String> authAddressesAndNetworks = new HashSet<>();
492 authAddressesAndNetworks.add(("127.0.0.1"));
493 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,true);
494 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
497 private void setBehalfHeader(String headerValue) {
498 when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
501 private void setValidPathInfoInHttpHeader() {
502 when(request.getPathInfo()).thenReturn("/1");
505 private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
506 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
507 Authorizer authorizer = mock(Authorizer.class);
508 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
509 when(authorizer.decide(request)).thenReturn(authResponse);
510 when(authResponse.isAuthorized()).thenReturn(false);
513 private void setAuthoriserToReturnRequestIsAuthorized() throws IllegalAccessException {
514 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
515 Authorizer authorizer = mock(Authorizer.class);
516 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
517 when(authorizer.decide(request)).thenReturn(authResponse);
518 when(authResponse.isAuthorized()).thenReturn(true);
521 private void setUpValidAuthorisedRequest() throws Exception {
522 setUpValidSecurityOnHttpRequest();
523 setBehalfHeader("Stub_Value");
524 setValidPathInfoInHttpHeader();
527 private void setUpValidContentHeadersAndJSONOnHttpRequest() {
528 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
529 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
532 private void reinsertFeedIntoDb() throws SQLException {
533 Feed feed = new Feed("Feed1","v0.1", "First Feed for testing", "First Feed for testing");
536 feed.setDeleted(false);
537 feed.doUpdate(db.getConnection());