2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 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=========================================================
21 package org.onap.policy.common.endpoints.http.server.test;
23 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.Matchers.any;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
33 import java.io.IOException;
34 import java.io.PrintWriter;
35 import java.net.HttpURLConnection;
37 import java.util.Arrays;
38 import java.util.Base64;
39 import java.util.Properties;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.ws.rs.Consumes;
42 import javax.ws.rs.POST;
43 import javax.ws.rs.Path;
44 import javax.ws.rs.Produces;
45 import javax.ws.rs.core.MediaType;
46 import javax.ws.rs.core.Response;
48 import org.junit.After;
49 import org.junit.AfterClass;
50 import org.junit.Before;
51 import org.junit.BeforeClass;
52 import org.junit.Test;
53 import org.mockito.ArgumentCaptor;
54 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
55 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactory;
56 import org.onap.policy.common.endpoints.http.server.JsonExceptionMapper;
57 import org.onap.policy.common.endpoints.http.server.RestServer;
58 import org.onap.policy.common.endpoints.http.server.RestServer.Factory;
59 import org.onap.policy.common.endpoints.http.server.YamlMessageBodyHandler;
60 import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter;
61 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
62 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
63 import org.onap.policy.common.gson.GsonMessageBodyHandler;
64 import org.onap.policy.common.utils.coder.StandardCoder;
65 import org.onap.policy.common.utils.network.NetworkUtil;
66 import org.powermock.reflect.Whitebox;
68 public class RestServerTest {
69 private static final String SERVER1 = "my-server-A";
70 private static final String SERVER2 = "my-server-B";
71 private static final String FACTORY_FIELD = "factory";
72 private static final String HOST = "my-host";
73 private static final String PARAM_NAME = "my-param";
74 private static final String PASS = "my-pass";
75 private static final Integer PORT = 9876;
76 private static final String USER = "my-user";
77 private static Factory saveFactory;
79 private RestServer realRest;
80 private RestServer rest;
81 private HttpServletServer server1;
82 private HttpServletServer server2;
83 private Factory factory;
84 private HttpServletServerFactory serverFactory;
85 private RestServerParameters params;
88 public static void setUpBeforeClass() {
89 saveFactory = Whitebox.getInternalState(RestServer.class, FACTORY_FIELD);
93 public static void tearDownAfterClass() {
94 Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, saveFactory);
101 public void setUp() {
102 server1 = mock(HttpServletServer.class);
103 server2 = mock(HttpServletServer.class);
104 factory = mock(Factory.class);
105 serverFactory = mock(HttpServletServerFactory.class);
106 params = mock(RestServerParameters.class);
108 when(factory.getServerFactory()).thenReturn(serverFactory);
109 when(serverFactory.build(any())).thenReturn(Arrays.asList(server1, server2));
111 when(server1.getName()).thenReturn(SERVER1);
112 when(server2.getName()).thenReturn(SERVER2);
114 when(params.getHost()).thenReturn(HOST);
115 when(params.getName()).thenReturn(PARAM_NAME);
116 when(params.getPassword()).thenReturn(PASS);
117 when(params.getPort()).thenReturn(PORT);
118 when(params.getUserName()).thenReturn(USER);
119 when(params.isAaf()).thenReturn(true);
120 when(params.isHttps()).thenReturn(true);
122 Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, factory);
128 * Stops the rest server.
131 public void tearDown() {
132 if (realRest != null) {
138 public void testRestServer() {
139 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
142 verify(server1).start();
143 verify(server2).start();
146 verify(server1).stop();
147 verify(server2).stop();
151 public void testRestServer_NoAaf() {
152 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
153 verify(server1, never()).addFilterClass(any(), any());
154 verify(server2, never()).addFilterClass(any(), any());
158 public void testRestServer_OnlyOneAaf() {
159 when(server2.isAaf()).thenReturn(true);
161 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
163 verify(server1, never()).addFilterClass(any(), any());
164 verify(server2).addFilterClass(null, Filter.class.getName());
168 public void testRestServer_BothAaf() {
169 when(server1.isAaf()).thenReturn(true);
170 when(server2.isAaf()).thenReturn(true);
172 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
174 verify(server1).addFilterClass(null, Filter.class.getName());
175 verify(server2).addFilterClass(null, Filter.class.getName());
179 public void testRestServer_BothAaf_NoFilter() {
180 when(server1.isAaf()).thenReturn(true);
181 when(server2.isAaf()).thenReturn(true);
183 rest = new RestServer(params, null, Provider1.class, Provider2.class);
185 verify(server1, never()).addFilterClass(any(), any());
186 verify(server2, never()).addFilterClass(any(), any());
190 public void testRestServer_MissingProviders() {
191 assertThatIllegalArgumentException().isThrownBy(() -> new RestServer(params, Filter.class));
195 public void testGetServerProperties_testGetProviderNames() {
196 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
198 ArgumentCaptor<Properties> cap = ArgumentCaptor.forClass(Properties.class);
199 verify(serverFactory).build(cap.capture());
201 Properties props = cap.getValue();
202 String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + PARAM_NAME;
204 assertEquals(HOST, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX));
205 assertEquals(String.valueOf(PORT),
206 props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX));
207 assertEquals(Provider1.class.getName() + "," + Provider2.class.getName(),
208 props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX));
209 assertEquals("false", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX));
210 assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX));
211 assertEquals(USER, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX));
212 assertEquals(PASS, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX));
213 assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX));
214 assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_AAF_SUFFIX));
215 assertEquals(String.join(",", GsonMessageBodyHandler.class.getName(), YamlMessageBodyHandler.class.getName(),
216 JsonExceptionMapper.class.getName()),
217 props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER));
221 public void testInvalidJson() throws Exception {
222 when(params.getHost()).thenReturn("localhost");
223 when(params.getPort()).thenReturn(NetworkUtil.allocPort());
224 when(params.isHttps()).thenReturn(false);
225 when(params.isAaf()).thenReturn(false);
228 Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, saveFactory);
230 realRest = new RestServer(params, null, RealProvider.class) {
232 protected Properties getServerProperties(RestServerParameters restServerParameters, String names) {
233 Properties props = super.getServerProperties(restServerParameters, names);
235 String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
236 + restServerParameters.getName();
237 props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "false");
244 assertTrue(NetworkUtil.isTcpPortOpen(params.getHost(), params.getPort(), 100, 100));
246 assertEquals(200, roundTrip(new StandardCoder().encode(new MyRequest())));
247 assertEquals(400, roundTrip("{'bogus-json'"));
250 private int roundTrip(String request) throws IOException {
251 URL url = new URL("http://" + params.getHost() + ":" + params.getPort() + "/request");
252 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
253 conn.setDoInput(true);
254 conn.setDoOutput(true);
255 conn.setRequestMethod("POST");
256 String auth = params.getUserName() + ":" + params.getPassword();
257 conn.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
258 conn.setRequestProperty("Content-type", MediaType.APPLICATION_JSON);
261 try (PrintWriter wtr = new PrintWriter(conn.getOutputStream())) {
265 return conn.getResponseCode();
269 public void testToString() {
270 rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
271 assertNotNull(rest.toString());
275 public void testFactory() {
276 assertNotNull(saveFactory);
277 assertNotNull(saveFactory.getServerFactory());
280 private static class Filter extends AafAuthFilter {
282 protected String getPermissionType(HttpServletRequest request) {
287 protected String getPermissionInstance(HttpServletRequest request) {
292 private static class Provider1 {
293 private Provider1() {
298 private static class Provider2 {
299 private Provider2() {
305 @Produces(MediaType.APPLICATION_JSON)
306 @Consumes(MediaType.APPLICATION_JSON)
307 public static class RealProvider {
310 public Response decision(MyRequest body) {
311 return Response.status(Response.Status.OK).entity(new MyResponse()).build();
316 public static class MyRequest {
321 public static class MyResponse {
322 private String text = "hello";