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.JSONObject;
30 import org.junit.AfterClass;
31 import org.junit.Before;
32 import org.junit.BeforeClass;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.mockito.Mock;
36 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
37 import org.onap.dmaap.datarouter.authz.Authorizer;
38 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
39 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
40 import org.onap.dmaap.datarouter.provisioning.utils.DB;
41 import org.powermock.api.mockito.PowerMockito;
42 import org.powermock.core.classloader.annotations.PrepareForTest;
43 import org.powermock.modules.junit4.PowerMockRunner;
45 import javax.persistence.EntityManager;
46 import javax.persistence.EntityManagerFactory;
47 import javax.persistence.Persistence;
48 import javax.servlet.ServletOutputStream;
49 import javax.servlet.http.HttpServletRequest;
50 import javax.servlet.http.HttpServletResponse;
51 import java.util.ArrayList;
52 import java.util.HashSet;
53 import java.util.List;
56 import static org.hamcrest.Matchers.notNullValue;
57 import static org.mockito.Mockito.*;
58 import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
61 @RunWith(PowerMockRunner.class)
62 @PrepareForTest(Subscription.class)
63 public class SubscribeServletTest extends DrServletTestBase {
64 private static SubscribeServlet subscribeServlet;
65 private static EntityManagerFactory emf;
66 private static EntityManager em;
70 private HttpServletRequest request;
72 private HttpServletResponse response;
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 {
95 listAppender = setTestLogger(SubscribeServlet.class);
96 subscribeServlet = new SubscribeServlet();
97 setAuthoriserToReturnRequestIsAuthorized();
98 setPokerToNotCreateTimersWhenDeleteFeedIsCalled();
99 setupValidAuthorisedRequest();
100 setUpValidSecurityOnHttpRequest();
101 setUpValidContentHeadersAndJSONOnHttpRequest();
105 public void Given_Request_Is_HTTP_DELETE_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
106 subscribeServlet.doDelete(request, response);
107 verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), argThat(notNullValue(String.class)));
108 verifyEnteringExitCalled(listAppender);
112 public void Given_Request_Is_HTTP_GET_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated() throws Exception {
113 when(request.isSecure()).thenReturn(false);
114 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isAddressAuthEnabled", "true", true);
115 subscribeServlet.doGet(request, response);
116 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
117 verifyEnteringExitCalled(listAppender);
121 public void Given_Request_Is_HTTP_GET_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated() throws Exception {
122 setBehalfHeader(null);
123 subscribeServlet.doGet(request, response);
124 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
129 public void Given_Request_Is_HTTP_GET_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
130 when(request.getPathInfo()).thenReturn(null);
131 subscribeServlet.doGet(request, response);
132 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
136 public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
137 when(request.getPathInfo()).thenReturn("/123");
138 subscribeServlet.doGet(request, response);
139 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
143 public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
144 ServletOutputStream outStream = mock(ServletOutputStream.class);
145 when(response.getOutputStream()).thenReturn(outStream);
146 when(request.getPathInfo()).thenReturn("/1");
147 PowerMockito.mockStatic(Subscription.class);
148 List<String> list = new ArrayList<>();
150 PowerMockito.when(Subscription.getSubscriptionUrlList(anyInt())).thenReturn(list);
151 subscribeServlet.doGet(request, response);
152 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
153 verifyEnteringExitCalled(listAppender);
158 public void Given_Request_Is_HTTP_PUT_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
159 subscribeServlet.doPut(request, response);
160 verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), argThat(notNullValue(String.class)));
161 verifyEnteringExitCalled(listAppender);
164 public void Given_Request_Is_HTTP_POST_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated() throws Exception {
165 when(request.isSecure()).thenReturn(false);
166 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isAddressAuthEnabled", "true", true);
167 subscribeServlet.doPost(request, response);
168 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
169 verifyEnteringExitCalled(listAppender);
173 public void Given_Request_Is_HTTP_POST_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated() throws Exception {
174 setBehalfHeader(null);
175 subscribeServlet.doPost(request, response);
176 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
181 public void Given_Request_Is_HTTP_POST_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
182 when(request.getPathInfo()).thenReturn(null);
183 subscribeServlet.doPost(request, response);
184 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
189 public void Given_Request_Is_HTTP_POST_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
190 when(request.getPathInfo()).thenReturn("/123");
191 subscribeServlet.doPost(request, response);
192 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
196 public void Given_Request_Is_HTTP_POST_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
197 setAuthoriserToReturnRequestNotAuthorized();
198 when(request.getPathInfo()).thenReturn("/1");
199 JSONObject JSObject = buildRequestJsonObject();
200 SubscribeServlet subscribeServlet = new SubscribeServlet() {
201 protected JSONObject getJSONfromInput(HttpServletRequest req) {
202 JSONObject jo = new JSONObject();
203 jo.put("name", "stub_name");
204 jo.put("version", "2.0");
205 jo.put("metadataOnly", true);
206 jo.put("suspend", true);
207 jo.put("delivery", JSObject);
208 jo.put("sync", false);
212 protected boolean doInsert(Insertable bean) {
216 subscribeServlet.doPost(request, response);
217 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
221 public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_Legacy_Feed_Then_Forbidden_Response_Is_Generated() throws Exception {
222 when(request.getPathInfo()).thenReturn("/1");
223 JSONObject JSObject = buildRequestJsonObject();
224 SubscribeServlet subscribeServlet = new SubscribeServlet() {
225 protected JSONObject getJSONfromInput(HttpServletRequest req) {
226 JSONObject jo = new JSONObject();
227 jo.put("name", "stub_name");
228 jo.put("version", "2.0");
229 jo.put("metadataOnly", true);
230 jo.put("suspend", true);
231 jo.put("delivery", JSObject);
232 jo.put("aaf_instance", "*");
233 jo.put("follow_redirect", false);
234 jo.put("sync", false);
238 protected boolean doInsert(Insertable bean) {
242 subscribeServlet.doPost(request, response);
243 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF Subscriber can not be added to legacy Feed"));
247 public void Given_Request_Is_HTTP_POST_And_Legacy_Subscriber_Added_To_AAF_Feed_And_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
248 setAuthoriserToReturnRequestNotAuthorized();
249 when(request.getPathInfo()).thenReturn("/2");
250 JSONObject JSObject = buildRequestJsonObject();
251 SubscribeServlet subscribeServlet = new SubscribeServlet() {
252 protected JSONObject getJSONfromInput(HttpServletRequest req) {
253 JSONObject jo = new JSONObject();
254 jo.put("name", "stub_name");
255 jo.put("version", "2.0");
256 jo.put("metadataOnly", true);
257 jo.put("suspend", true);
258 jo.put("delivery", JSObject);
259 jo.put("aaf_instance", "legacy");
260 jo.put("follow_redirect", false);
261 jo.put("sync", false);
265 subscribeServlet.doPost(request, response);
266 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access."));
270 public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
271 when(request.getPathInfo()).thenReturn("/2");
272 JSONObject JSObject = buildRequestJsonObject();
273 SubscribeServlet subscribeServlet = new SubscribeServlet() {
274 protected JSONObject getJSONfromInput(HttpServletRequest req) {
275 JSONObject jo = new JSONObject();
276 jo.put("name", "stub_name");
277 jo.put("version", "2.0");
278 jo.put("metadataOnly", true);
279 jo.put("suspend", true);
280 jo.put("delivery", JSObject);
281 jo.put("aaf_instance", "*");
282 jo.put("follow_redirect", false);
283 jo.put("sync", false);
287 subscribeServlet.doPost(request, response);
288 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
292 public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_With_Permissions_Then_OK_Response_Is_Generated() throws Exception {
293 ServletOutputStream outStream = mock(ServletOutputStream.class);
294 when(response.getOutputStream()).thenReturn(outStream);
295 when(request.getPathInfo()).thenReturn("/2");
296 when(request.isUserInRole("org.onap.dmaap-dr.feed|*|approveSub")).thenReturn(true);
297 PowerMockito.mockStatic(Subscription.class);
298 PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
299 JSONObject JSObject = buildRequestJsonObject();
300 SubscribeServlet subscribeServlet = new SubscribeServlet() {
301 protected JSONObject getJSONfromInput(HttpServletRequest req) {
302 JSONObject jo = new JSONObject();
303 jo.put("name", "stub_name");
304 jo.put("version", "2.0");
305 jo.put("metadataOnly", true);
306 jo.put("suspend", true);
307 jo.put("delivery", JSObject);
308 jo.put("aaf_instance", "*");
309 jo.put("follow_redirect", false);
310 jo.put("sync", false);
315 protected boolean doInsert(Insertable bean) {
319 subscribeServlet.doPost(request, response);
320 verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
321 verifyEnteringExitCalled(listAppender);
325 public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
326 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
327 when(request.getContentType()).thenReturn("stub_contentType");
328 when(request.getPathInfo()).thenReturn("/1");
329 subscribeServlet.doPost(request, response);
330 verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
334 public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
335 when(request.getPathInfo()).thenReturn("/1");
336 subscribeServlet.doPost(request, response);
337 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
341 public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated() throws Exception {
342 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 0, true);
343 when(request.getPathInfo()).thenReturn("/1");
344 SubscribeServlet subscribeServlet = new SubscribeServlet() {
345 protected JSONObject getJSONfromInput(HttpServletRequest req) {
346 return new JSONObject();
349 subscribeServlet.doPost(request, response);
350 verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
354 public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
355 when(request.getPathInfo()).thenReturn("/2");
356 PowerMockito.mockStatic(Subscription.class);
357 PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
358 JSONObject JSObject = buildRequestJsonObject();
359 SubscribeServlet subscribeServlet = new SubscribeServlet() {
360 protected JSONObject getJSONfromInput(HttpServletRequest req) {
361 JSONObject jo = new JSONObject();
362 jo.put("name", "stub_name");
363 jo.put("version", "2.0");
364 jo.put("metadataOnly", true);
365 jo.put("suspend", true);
366 jo.put("delivery", JSObject);
367 jo.put("aaf_instance", "legacy");
368 jo.put("follow_redirect", false);
369 jo.put("sync", false);
374 protected boolean doInsert(Insertable bean) {
378 subscribeServlet.doPost(request, response);
379 verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
383 private JSONObject buildRequestJsonObject() {
384 JSONObject JSObject = new JSONObject();
385 JSObject.put("url", "https://stub_address");
386 JSObject.put("use100", "true");
387 JSObject.put("password", "stub_password");
388 JSObject.put("user", "stub_user");
392 private void setUpValidSecurityOnHttpRequest() throws Exception {
393 when(request.isSecure()).thenReturn(true);
394 Set<String> authAddressesAndNetworks = new HashSet<>();
395 authAddressesAndNetworks.add(("127.0.0.1"));
396 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks, true);
397 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
398 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 100, true);
401 private void setBehalfHeader(String headerValue) {
402 when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
405 private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
406 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
407 Authorizer authorizer = mock(Authorizer.class);
408 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
409 when(authorizer.decide(request)).thenReturn(authResponse);
410 when(authResponse.isAuthorized()).thenReturn(false);
413 private void setAuthoriserToReturnRequestIsAuthorized() throws IllegalAccessException {
414 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
415 Authorizer authorizer = mock(Authorizer.class);
416 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
417 when(authorizer.decide(request)).thenReturn(authResponse);
418 when(authResponse.isAuthorized()).thenReturn(true);
421 private void setPokerToNotCreateTimersWhenDeleteFeedIsCalled() throws Exception {
422 Poker poker = mock(Poker.class);
423 FieldUtils.writeDeclaredStaticField(Poker.class, "poker", poker, true);
426 private void setupValidAuthorisedRequest() throws Exception {
427 setUpValidSecurityOnHttpRequest();
428 setBehalfHeader("Stub_Value");
431 private void setUpValidContentHeadersAndJSONOnHttpRequest() {
432 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
433 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");