fd9b59f7476feb285c1b3de1a204b6f0fb8706d8
[policy/common.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
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
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
21 package org.onap.policy.common.endpoints.http.server.test;
22
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;
32
33 import java.io.IOException;
34 import java.io.PrintWriter;
35 import java.net.HttpURLConnection;
36 import java.net.URL;
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;
47 import lombok.Getter;
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.aaf.AafAuthFilter;
60 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
61 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
62 import org.onap.policy.common.gson.GsonMessageBodyHandler;
63 import org.onap.policy.common.utils.coder.StandardCoder;
64 import org.onap.policy.common.utils.network.NetworkUtil;
65 import org.powermock.reflect.Whitebox;
66
67 public class RestServerTest {
68     private static final String SERVER1 = "my-server-A";
69     private static final String SERVER2 = "my-server-B";
70     private static final String FACTORY_FIELD = "factory";
71     private static final String HOST = "my-host";
72     private static final String PARAM_NAME = "my-param";
73     private static final String PASS = "my-pass";
74     private static final Integer PORT = 9876;
75     private static final String USER = "my-user";
76     private static Factory saveFactory;
77
78     private RestServer realRest;
79     private RestServer rest;
80     private HttpServletServer server1;
81     private HttpServletServer server2;
82     private Factory factory;
83     private HttpServletServerFactory serverFactory;
84     private RestServerParameters params;
85
86     @BeforeClass
87     public static void setUpBeforeClass() {
88         saveFactory = Whitebox.getInternalState(RestServer.class, FACTORY_FIELD);
89     }
90
91     @AfterClass
92     public static void tearDownAfterClass() {
93         Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, saveFactory);
94     }
95
96     /**
97      * Initializes mocks.
98      */
99     @Before
100     public void setUp() {
101         server1 = mock(HttpServletServer.class);
102         server2 = mock(HttpServletServer.class);
103         factory = mock(Factory.class);
104         serverFactory = mock(HttpServletServerFactory.class);
105         params = mock(RestServerParameters.class);
106
107         when(factory.getServerFactory()).thenReturn(serverFactory);
108         when(serverFactory.build(any())).thenReturn(Arrays.asList(server1, server2));
109
110         when(server1.getName()).thenReturn(SERVER1);
111         when(server2.getName()).thenReturn(SERVER2);
112
113         when(params.getHost()).thenReturn(HOST);
114         when(params.getName()).thenReturn(PARAM_NAME);
115         when(params.getPassword()).thenReturn(PASS);
116         when(params.getPort()).thenReturn(PORT);
117         when(params.getUserName()).thenReturn(USER);
118         when(params.isAaf()).thenReturn(true);
119         when(params.isHttps()).thenReturn(true);
120
121         Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, factory);
122
123         realRest = null;
124     }
125
126     /**
127      * Stops the rest server.
128      */
129     @After
130     public void tearDown() {
131         if (realRest != null) {
132             realRest.stop();
133         }
134     }
135
136     @Test
137     public void testRestServer() {
138         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
139
140         rest.start();
141         verify(server1).start();
142         verify(server2).start();
143
144         rest.stop();
145         verify(server1).stop();
146         verify(server2).stop();
147     }
148
149     @Test
150     public void testRestServer_NoAaf() {
151         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
152         verify(server1, never()).addFilterClass(any(), any());
153         verify(server2, never()).addFilterClass(any(), any());
154     }
155
156     @Test
157     public void testRestServer_OnlyOneAaf() {
158         when(server2.isAaf()).thenReturn(true);
159
160         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
161
162         verify(server1, never()).addFilterClass(any(), any());
163         verify(server2).addFilterClass(null, Filter.class.getName());
164     }
165
166     @Test
167     public void testRestServer_BothAaf() {
168         when(server1.isAaf()).thenReturn(true);
169         when(server2.isAaf()).thenReturn(true);
170
171         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
172
173         verify(server1).addFilterClass(null, Filter.class.getName());
174         verify(server2).addFilterClass(null, Filter.class.getName());
175     }
176
177     @Test
178     public void testRestServer_BothAaf_NoFilter() {
179         when(server1.isAaf()).thenReturn(true);
180         when(server2.isAaf()).thenReturn(true);
181
182         rest = new RestServer(params, null, Provider1.class, Provider2.class);
183
184         verify(server1, never()).addFilterClass(any(), any());
185         verify(server2, never()).addFilterClass(any(), any());
186     }
187
188     @Test
189     public void testRestServer_MissingProviders() {
190         assertThatIllegalArgumentException().isThrownBy(() -> new RestServer(params, Filter.class));
191     }
192
193     @Test
194     public void testGetServerProperties_testGetProviderNames() {
195         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
196
197         ArgumentCaptor<Properties> cap = ArgumentCaptor.forClass(Properties.class);
198         verify(serverFactory).build(cap.capture());
199
200         Properties props = cap.getValue();
201         String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + PARAM_NAME;
202
203         assertEquals(HOST, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX));
204         assertEquals(String.valueOf(PORT),
205                         props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX));
206         assertEquals(Provider1.class.getName() + "," + Provider2.class.getName(),
207                         props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX));
208         assertEquals("false", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX));
209         assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX));
210         assertEquals(USER, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX));
211         assertEquals(PASS, props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX));
212         assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HTTPS_SUFFIX));
213         assertEquals("true", props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_AAF_SUFFIX));
214         assertEquals(String.join(",", GsonMessageBodyHandler.class.getName(), JsonExceptionMapper.class.getName()),
215                         props.getProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER));
216     }
217
218     @Test
219     public void testInvalidJson() throws Exception {
220         when(params.getHost()).thenReturn("localhost");
221         when(params.getPort()).thenReturn(NetworkUtil.allocPort());
222         when(params.isHttps()).thenReturn(false);
223         when(params.isAaf()).thenReturn(false);
224
225         // use real factory
226         Whitebox.setInternalState(RestServer.class, FACTORY_FIELD, saveFactory);
227
228         realRest = new RestServer(params, null, RealProvider.class) {
229             @Override
230             protected Properties getServerProperties(RestServerParameters restServerParameters, String names) {
231                 Properties props = super.getServerProperties(restServerParameters, names);
232
233                 String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
234                                 + restServerParameters.getName();
235                 props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "false");
236
237                 return props;
238             }
239         };
240
241         realRest.start();
242         assertTrue(NetworkUtil.isTcpPortOpen(params.getHost(), params.getPort(), 100, 100));
243
244         assertEquals(200, roundTrip(new StandardCoder().encode(new MyRequest())));
245         assertEquals(400, roundTrip("{'bogus-json'"));
246     }
247
248     private int roundTrip(String request) throws IOException {
249         URL url = new URL("http://" + params.getHost() + ":" + params.getPort() + "/request");
250         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
251         conn.setDoInput(true);
252         conn.setDoOutput(true);
253         conn.setRequestMethod("POST");
254         String auth = params.getUserName() + ":" + params.getPassword();
255         conn.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
256         conn.setRequestProperty("Content-type", MediaType.APPLICATION_JSON);
257         conn.connect();
258
259         try (PrintWriter wtr = new PrintWriter(conn.getOutputStream())) {
260             wtr.write(request);
261         }
262
263         return conn.getResponseCode();
264     }
265
266     @Test
267     public void testToString() {
268         rest = new RestServer(params, Filter.class, Provider1.class, Provider2.class);
269         assertNotNull(rest.toString());
270     }
271
272     @Test
273     public void testFactory() {
274         assertNotNull(saveFactory);
275         assertNotNull(saveFactory.getServerFactory());
276     }
277
278     private static class Filter extends AafAuthFilter {
279         @Override
280         protected String getPermissionType(HttpServletRequest request) {
281             return "";
282         }
283
284         @Override
285         protected String getPermissionInstance(HttpServletRequest request) {
286             return "";
287         }
288     }
289
290     private static class Provider1 {
291         private Provider1() {
292             // do nothing
293         }
294     }
295
296     private static class Provider2 {
297         private Provider2() {
298             // do nothing
299         }
300     }
301
302     @Path("/")
303     @Produces(MediaType.APPLICATION_JSON)
304     @Consumes(MediaType.APPLICATION_JSON)
305     public static class RealProvider {
306         @POST
307         @Path("/request")
308         public Response decision(MyRequest body) {
309             return Response.status(Response.Status.OK).entity(new MyResponse()).build();
310         }
311     }
312
313     @Getter
314     public static class MyRequest {
315         private String data;
316     }
317
318     @Getter
319     public static class MyResponse {
320         private String text = "hello";
321     }
322 }