3bd07174d1a15b6b8fa89f4f584fee15861c8c15
[so/libs.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 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 com.woorea.openstack.connector;
22
23 import static org.junit.Assert.assertTrue;
24 import static org.mockito.Matchers.any;
25 import static org.mockito.Mockito.doCallRealMethod;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.when;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.IOException;
31 import java.io.OutputStream;
32 import java.lang.reflect.Method;
33 import java.net.URI;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.logging.ConsoleHandler;
38 import java.util.logging.Level;
39 import java.util.logging.LogRecord;
40 import java.util.logging.Logger;
41 import java.util.logging.SimpleFormatter;
42
43 import javax.ws.rs.core.MultivaluedMap;
44
45 import org.junit.Before;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48 import org.mockito.invocation.InvocationOnMock;
49 import org.mockito.stubbing.Answer;
50
51 import com.sun.jersey.api.client.ClientHandler;
52 import com.sun.jersey.api.client.ClientRequest;
53 import com.sun.jersey.api.client.ClientRequestAdapter;
54 import com.sun.jersey.api.client.ClientResponse;
55 import com.sun.jersey.api.client.filter.ClientFilter;
56
57 public class JerseyLoggingFilterTest {
58
59         private static Logger logger;
60         private static LogFormatter logFormatter;
61         
62         @BeforeClass
63         public static void setUpClass() throws Exception {
64                 logger = Logger.getLogger(JerseyLoggingFilterTest.class.getSimpleName());
65                 logger.setLevel(Level.ALL);
66                 logger.setUseParentHandlers(false);
67
68                 ConsoleHandler handler = new ConsoleHandler();
69                 logFormatter = new LogFormatter();
70                 handler.setFormatter(logFormatter);
71                 handler.setLevel(Level.ALL);
72                 logger.addHandler(handler);
73         }
74
75         @Before
76         public void setUpTest() {
77                 logFormatter.clearLog();
78         }
79         
80         /**
81          * Tests a scenario with no request content (GET).
82          * @throws Exception for unexpected errors
83          */
84         @Test
85         public void testGET() throws Exception {
86                 String responseContent = "<response>Hello, I am Eliza.</response>";
87                 execute("GET", "http://www.onap.org/eliza", null, responseContent);
88         }
89         
90         /**
91          * Tests a scenario with request content (POST).
92          * @throws Exception for unexpected errors
93          */
94         @Test
95         public void testPOST() throws Exception {
96                 String requestContent = "<request>I feel sad.</request>";
97                 String responseContent = "<response>Do you often feel sad?</response>";
98                 execute("POST", "http://www.onap.org/eliza", requestContent, responseContent);
99         }
100
101         /**
102          * Runs a single test.
103          * @param httpMethod any HTTP method (POST, GET, ...)
104          * @param url any URL
105          * @param requestContent mock request content, possibly null
106          * @param responseContent mock response content, never null
107          * @throws Exception for unexpected errors
108          */
109         private void execute(String httpMethod, String url, String requestContent, String responseContent)
110                         throws Exception {
111                 JerseyLoggingFilter loggingFilter = new JerseyLoggingFilter(logger);
112
113                 // Mock multi-valued and single valued request headers
114
115                 HashMap<String, List<Object>> requestHeaderMap = new HashMap<>();
116                 requestHeaderMap.put("Accept", Arrays.asList(new Object[]{"application/xml","application/json"}));
117
118                 if (requestContent != null) {
119                         requestHeaderMap.put("Content-Type", Arrays.asList(new Object[]{"application/xml"}));
120                         requestHeaderMap.put("Content-Length", Arrays.asList(new Object[]{String.valueOf(requestContent.length())}));
121                 }
122
123                 @SuppressWarnings("unchecked")
124                 MultivaluedMap<String, Object> requestHeaders = mock(MultivaluedMap.class);
125                 when(requestHeaders.entrySet()).thenReturn(requestHeaderMap.entrySet());
126
127                 // Mock the request object
128
129                 ClientRequest request = mock(TestClientRequest.class);
130                 when(request.getURI()).thenReturn(new URI(url));
131                 when(request.getMethod()).thenReturn(httpMethod);
132                 when(request.getHeaders()).thenReturn(requestHeaders);
133
134                 if (requestContent != null) {
135                         when(request.getEntity()).thenReturn(requestContent.getBytes("UTF-8"));
136                 }
137
138                 doCallRealMethod().when(request).setAdapter(any(ClientRequestAdapter.class));
139                 when(request.getAdapter()).thenCallRealMethod();
140                 request.setAdapter(new DefaultClientRequestAdapter());
141
142                 // Mock multi-valued and single valued response headers
143
144                 HashMap<String, List<String>> responseHeaderMap = new HashMap<>();
145                 responseHeaderMap.put("Cache-Control", Arrays.asList(new String[]{"no-cache","no-store"}));
146                 responseHeaderMap.put("Content-Type", Arrays.asList(new String[]{"application/xml"}));
147                 responseHeaderMap.put("Content-Length", Arrays.asList(new String[]{String.valueOf(responseContent.length())}));
148                 @SuppressWarnings("unchecked")
149                 MultivaluedMap<String, String> responseHeaders = mock(MultivaluedMap.class);
150                 when(responseHeaders.entrySet()).thenReturn(responseHeaderMap.entrySet());
151
152                 // Mock the response object
153
154                 ClientResponse response = mock(ClientResponse.class);
155                 when(response.getStatus()).thenReturn(200);
156                 when(response.getHeaders()).thenReturn(responseHeaders);
157                 when(response.getEntityInputStream()).thenReturn(
158                                 new ByteArrayInputStream(responseContent.getBytes("UTF-8")));
159
160                 // Mock a handler that returns the response object and set
161                 // it to be the next filter after the logging filter.
162
163                 ClientFilter handler = mock(ClientFilter.class);
164                 when(handler.handle(request)).then(produceResponse(response));
165                 Method setNext = ClientFilter.class.getDeclaredMethod("setNext", new Class<?>[]{ClientHandler.class});
166                 setNext.setAccessible(true);
167                 setNext.invoke(loggingFilter, new Object[]{handler});
168
169                 // Run the request into the logging filter
170
171                 loggingFilter.handle(request);
172
173                 // Validate resulting the log content
174
175                 String log = logFormatter.getLog();
176
177                 assertContains(log, "* Client out-bound request");
178                 assertContains(log, "> " + httpMethod + " " + url);
179
180                 for (String header : requestHeaderMap.keySet()) {
181                         assertContains(log, "> " + header + ": ");
182                 }
183
184                 if (requestContent != null) {
185                         assertContains(log, requestContent);
186                 }
187
188                 assertContains(log, "* Client in-bound response");
189                 assertContains(log, "< 200");
190
191                 for (String header : responseHeaderMap.keySet()) {
192                         assertContains(log, "< " + header + ": ");
193                 }
194
195                 assertContains(log, responseContent);
196         }
197         
198         private void assertContains(String log, String expect) {
199                 assertTrue("Log does not contain '" + expect + "'", log.contains(expect));
200         }
201
202         private class DefaultClientRequestAdapter implements ClientRequestAdapter {
203                 @Override
204                 public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
205                         return out;
206                 }
207         }
208
209         private abstract class TestClientRequest extends ClientRequest {
210                 private ClientRequestAdapter adapter;
211
212                 @Override
213                 public ClientRequestAdapter getAdapter() {
214                         return adapter;
215                 }
216
217                 @Override
218                 public void setAdapter(ClientRequestAdapter adapter) {
219                         this.adapter = adapter;
220                 }
221         }
222         
223         private Answer<ClientResponse> produceResponse(final ClientResponse response) { 
224                 return new Answer<ClientResponse>() {
225                         public ClientResponse answer(InvocationOnMock invocation) throws IOException {
226                                 ClientRequest request = (ClientRequest) invocation.getArguments()[0];
227                                 byte[] entity = (byte[]) request.getEntity();
228
229                                 if (entity != null) {
230                                         ClientRequestAdapter adapter = request.getAdapter();
231         
232                                         OutputStream nullOutputStream = new OutputStream() {
233                                                 @Override
234                                                 public void write(int b) {
235                                                         // Discard
236                                                 }
237                                         };
238
239                                         OutputStream outputStream = adapter.adapt(request, nullOutputStream);
240                                         outputStream.write(entity);
241                                         outputStream.close();
242                                 }
243
244                                 return response;
245                         }
246                 };
247         }
248
249         private static class LogFormatter extends SimpleFormatter {
250                 StringBuilder buffer = new StringBuilder();
251
252                 public synchronized String getLog() {
253                         return buffer.toString();
254                 }
255
256                 public synchronized void clearLog() {
257                         buffer.setLength(0);
258                 }
259
260                 @Override
261                 public synchronized String format(LogRecord record) {
262                         String logData = super.format(record);
263                         buffer.append(logData);
264                         return logData;
265                 }
266         }
267 }