2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.logging.ref.slf4j;
24 import java.util.HashMap;
26 import java.util.UUID;
28 import javax.xml.bind.DatatypeConverter;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import org.slf4j.event.Level;
34 import org.springframework.mock.web.MockHttpServletRequest;
35 import org.testng.Assert;
36 import org.testng.annotations.AfterMethod;
37 import org.testng.annotations.Test;
38 import static org.hamcrest.MatcherAssert.assertThat;
39 import static org.hamcrest.core.Is.is;
40 import static org.hamcrest.core.IsEqual.equalTo;
41 import static org.hamcrest.core.IsNot.not;
42 import static org.hamcrest.core.IsSame.sameInstance;
43 import static org.hamcrest.core.StringContains.containsString;
44 import static org.hamcrest.core.StringEndsWith.endsWith;
45 import static org.hamcrest.core.Every.everyItem;
46 import static org.hamcrest.core.IsInstanceOf.instanceOf;
47 import static org.hamcrest.core.IsNull.notNullValue;
48 import static org.hamcrest.core.IsNull.nullValue;
49 import static org.hamcrest.core.StringStartsWith.startsWith;
50 import static org.hamcrest.beans.HasProperty.hasProperty;
51 import static org.hamcrest.number.IsCloseTo.closeTo;
52 import static org.hamcrest.number.OrderingComparison.greaterThan;
53 import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
54 import static org.hamcrest.number.OrderingComparison.lessThan;
55 import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;
56 import static org.hamcrest.collection.IsArray.array;
57 import static org.hamcrest.collection.IsArrayContaining.hasItemInArray;
58 import static org.hamcrest.collection.IsArrayContainingInAnyOrder.arrayContainingInAnyOrder;
59 import static org.hamcrest.collection.IsIn.isIn;
60 import static org.hamcrest.collection.IsIn.isOneOf;
61 import static org.hamcrest.collection.IsMapContaining.hasKey;
62 import static org.hamcrest.collection.IsMapContaining.hasEntry;
63 import static org.hamcrest.collection.IsMapContaining.hasValue;
64 import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
65 import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
66 import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString;
67 import static org.hamcrest.text.IsEmptyString.isEmptyString;
68 import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder;
69 import static org.hamcrest.xml.HasXPath.hasXPath;
71 import org.testng.Assert;
72 import org.testng.annotations.Test;
74 import static org.hamcrest.MatcherAssert.assertThat;
75 import static org.hamcrest.core.Is.is;
76 import static org.hamcrest.core.IsNot.not;
77 import static org.hamcrest.core.IsNull.notNullValue;
78 import static org.hamcrest.core.IsNull.nullValue;
79 import static org.hamcrest.core.IsSame.sameInstance;
82 * Tests for {@link ONAPLogAdapter}.
84 public class ONAPLogAdapterTest {
87 * Ensure that MDCs are cleared after each testcase.
90 public void resetMDCs() {
98 public void testCheckNotNull() {
100 ONAPLogAdapter.checkNotNull("");
103 ONAPLogAdapter.checkNotNull(null);
104 Assert.fail("Should throw NullPointerException");
106 catch (final NullPointerException e) {
112 * Test defaulting of nulls.
115 public void testDefaultToEmpty() {
116 assertThat(ONAPLogAdapter.defaultToEmpty("123"), is("123"));
117 assertThat(ONAPLogAdapter.defaultToEmpty(Integer.valueOf(1984)), is("1984"));
118 assertThat(ONAPLogAdapter.defaultToEmpty(null), is(""));
122 * Test defaulting of nulls.
125 public void testDefaultToUUID() {
126 assertThat(ONAPLogAdapter.defaultToUUID("123"), is("123"));
127 UUID.fromString(ONAPLogAdapter.defaultToUUID(null));
134 public void testEntering() {
136 final Logger logger = LoggerFactory.getLogger(this.getClass());
137 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
138 final MockHttpServletRequest http = new MockHttpServletRequest();
139 http.setRequestURI("uri123");
140 http.setServerName("local123");
141 http.setRemoteAddr("remote123");
142 http.addHeader("X-ONAP-RequestID", "request123");
143 http.addHeader("X-InvocationID", "invocation123");
144 http.addHeader("X-ONAP-PartnerName", "partner123");
147 adapter.getServiceDescriptor().setServiceName("uri123");
148 adapter.entering(http);
149 final Map<String, String> mdcs = MDC.getCopyOfContextMap();
150 assertThat(mdcs.get("RequestID"), is("request123"));
151 assertThat(mdcs.get("InvocationID"), is("invocation123"));
152 assertThat(mdcs.get("PartnerName"), is("partner123"));
153 assertThat(mdcs.get("ServiceName"), is("uri123"));
154 assertThat(mdcs.get("ServerFQDN"), is("local123"));
155 assertThat(mdcs.get("ClientIPAddress"), is("remote123"));
157 // Timestamp format and value:
159 final String invokeTimestampString = mdcs.get("InvokeTimestamp");
160 assertThat(invokeTimestampString, notNullValue());
161 assertThat(invokeTimestampString, endsWith("Z"));
162 final long invokeTimestamp = DatatypeConverter.parseDateTime(invokeTimestampString).getTimeInMillis();
163 assertThat(Math.abs(System.currentTimeMillis() - invokeTimestamp), lessThan(5000L));
171 * Test ENTERING with an EMPTY_STRING serviceName.
174 public void testEnteringWithEMPTY_STRING_serviceName() {
176 final Logger logger = LoggerFactory.getLogger(this.getClass());
177 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
178 final MockHttpServletRequest http = new MockHttpServletRequest();
179 http.setRequestURI("uri123");
180 http.setServerName("local123");
181 http.setRemoteAddr("remote123");
182 http.addHeader("X-ONAP-RequestID", "request123");
183 http.addHeader("X-InvocationID", "invocation123");
184 http.addHeader("X-ONAP-PartnerName", "partner123");
187 // an empty string should kick in setting the actual service name (treated same as null)
188 adapter.getServiceDescriptor().setServiceName("");
189 adapter.entering(http);
190 final Map<String, String> mdcs = MDC.getCopyOfContextMap();
191 assertThat(mdcs.get("RequestID"), is("request123"));
192 assertThat(mdcs.get("InvocationID"), is("invocation123"));
193 assertThat(mdcs.get("PartnerName"), is("partner123"));
194 assertThat(mdcs.get("ServiceName"), is("uri123"));
195 assertThat(mdcs.get("ServerFQDN"), is("local123"));
196 assertThat(mdcs.get("ClientIPAddress"), is("remote123"));
198 // Timestamp format and value:
200 final String invokeTimestampString = mdcs.get("InvokeTimestamp");
201 assertThat(invokeTimestampString, notNullValue());
202 assertThat(invokeTimestampString, endsWith("Z"));
203 final long invokeTimestamp = DatatypeConverter.parseDateTime(invokeTimestampString).getTimeInMillis();
204 assertThat(Math.abs(System.currentTimeMillis() - invokeTimestamp), lessThan(5000L));
212 public void testSetServiceDescriptor() {
213 final ONAPLogAdapter.ServiceDescriptor override = new ONAPLogAdapter.ServiceDescriptor();
214 final Logger logger = LoggerFactory.getLogger(this.getClass());
215 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
216 final ONAPLogAdapter.ServiceDescriptor before = adapter.getServiceDescriptor();
217 adapter.setServiceDescriptor(override);
218 final ONAPLogAdapter.ServiceDescriptor after = adapter.getServiceDescriptor();
219 assertThat(after, not(sameInstance(before)));
220 assertThat(after, is(override));
224 public void testSetResponseDescriptor() {
225 final ONAPLogAdapter.ResponseDescriptor override = new ONAPLogAdapter.ResponseDescriptor();
226 final Logger logger = LoggerFactory.getLogger(this.getClass());
227 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
228 final ONAPLogAdapter.ResponseDescriptor before = adapter.getResponseDescriptor();
229 adapter.setResponseDescriptor(override);
230 final ONAPLogAdapter.ResponseDescriptor after = adapter.getResponseDescriptor();
231 assertThat(after, not(sameInstance(before)));
232 assertThat(after, is(override));
236 public void testUnwrap() {
237 final Logger logger = LoggerFactory.getLogger(this.getClass());
238 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
239 assertThat(adapter.unwrap(), is(logger));
246 public void testExiting() {
248 final Logger logger = LoggerFactory.getLogger(this.getClass());
249 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
252 MDC.put("somekey", "somevalue");
253 assertThat(MDC.get("somekey"), is("somevalue"));
255 assertThat(MDC.get("somekey"), nullValue());
266 public void testInvokeSyncAsyncNull() {
268 final Logger logger = LoggerFactory.getLogger(this.getClass());
269 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
271 final UUID syncUUID = adapter.invoke(ONAPLogConstants.InvocationMode.SYNCHRONOUS);
272 assertThat(syncUUID, notNullValue());
274 final UUID asyncUUID = adapter.invoke(ONAPLogConstants.InvocationMode.SYNCHRONOUS);
275 assertThat(asyncUUID, notNullValue());
277 final UUID agnosticUUID = adapter.invoke((ONAPLogConstants.InvocationMode)null);
278 assertThat(agnosticUUID, notNullValue());
283 * Test INVOKE, with RequestAdapter.
286 public void testInvokeWithAdapter() throws Exception {
288 final Logger logger = LoggerFactory.getLogger(this.getClass());
289 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
291 final Map<String, String> headers = new HashMap<>();
292 final ONAPLogAdapter.RequestBuilder builder = new ONAPLogAdapter.RequestBuilder<ONAPLogAdapter.RequestBuilder>() {
294 public ONAPLogAdapter.RequestBuilder setHeader(final String name, final String value) {
295 headers.put(name, value);
301 final UUID uuid = adapter.invoke(builder, ONAPLogConstants.InvocationMode.SYNCHRONOUS);
302 assertThat(uuid, notNullValue());
303 assertThat(headers.get(ONAPLogConstants.Headers.INVOCATION_ID), is(uuid.toString()));
304 assertThat(headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME), is(true));
305 assertThat(headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID), is(true));
313 * Test INVOKE, with RequestAdapter.
316 public void testInvokeWithAdapterAndNull() throws Exception {
318 final Logger logger = LoggerFactory.getLogger(this.getClass());
319 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
321 final Map<String, String> headers = new HashMap<>();
322 final ONAPLogAdapter.RequestBuilder builder = new ONAPLogAdapter.RequestBuilder<ONAPLogAdapter.RequestBuilder>() {
324 public ONAPLogAdapter.RequestBuilder setHeader(final String name, final String value) {
325 headers.put(name, value);
331 final UUID uuid = adapter.invoke(builder);
332 assertThat(uuid, notNullValue());
333 assertThat(headers.get(ONAPLogConstants.Headers.INVOCATION_ID), is(uuid.toString()));
334 assertThat(headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME), is(true));
335 assertThat(headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID), is(true));
343 public void testHttpServletRequestAdapter() {
345 final UUID uuid = UUID.randomUUID();
346 final MockHttpServletRequest request = new MockHttpServletRequest();
347 request.addHeader("uuid", uuid.toString());
348 request.setRequestURI("/ctx0");
349 request.setServerName("srv0");
351 final ONAPLogAdapter.HttpServletRequestAdapter adapter
352 = new ONAPLogAdapter.HttpServletRequestAdapter(request);
353 assertThat(adapter.getHeader("uuid"), is(uuid.toString()));
354 assertThat(adapter.getRequestURI(), is("/ctx0"));
355 assertThat(adapter.getServerAddress(), is("srv0"));
359 public void testServiceDescriptor() {
360 final String uuid = UUID.randomUUID().toString();
362 final ONAPLogAdapter.ServiceDescriptor adapter
363 = new ONAPLogAdapter.ServiceDescriptor();
364 adapter.setServiceUUID(uuid);
365 adapter.setServiceName("name0");
367 assertThat(MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME), nullValue());
368 assertThat(MDC.get(ONAPLogConstants.MDCs.INSTANCE_UUID), nullValue());
372 assertThat(MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME), is("name0"));
373 assertThat(MDC.get(ONAPLogConstants.MDCs.INSTANCE_UUID), is(uuid));
377 public void testResponseDescriptor() {
378 final String uuid = UUID.randomUUID().toString();
380 final ONAPLogAdapter.ResponseDescriptor adapter
381 = new ONAPLogAdapter.ResponseDescriptor();
382 adapter.setResponseCode("code0");
383 adapter.setResponseDescription("desc0");
384 adapter.setResponseSeverity(Level.INFO);
385 adapter.setResponseStatus(ONAPLogConstants.ResponseStatus.COMPLETE);
387 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_CODE), nullValue());
388 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION), nullValue());
389 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_SEVERITY), nullValue());
390 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE), nullValue());
394 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_CODE), is("code0"));
395 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION), is("desc0"));
396 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_SEVERITY), is("INFO"));
397 assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE), is("COMPLETE"));
401 * Exercise the contract, for a caller that's happy to have their
402 * service name automatically derived. (This validates nothing
403 * and achieves nothing; it's just to provide an example of minimal usage).
406 public void testContract() {
408 // Note no wrapper around HttpServletRequest, which will work for
409 // most invocations (since they come via HTTP), but otherwise
410 // can implement your own RequestAdapter.
412 final Logger logger = LoggerFactory.getLogger(this.getClass());
413 final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
414 final MockHttpServletRequest http = new MockHttpServletRequest();
416 // Immediately log ENTERING marker, with global MDCs.
418 adapter.entering(http);
421 // Generate (and log) an invocationID, then use it to
422 // invoke another component.
424 final RESTClient client = new RESTClient(); // implements ONAPLogAdapter.RequestBuilder<RESTClient>.
425 adapter.invoke(client, ONAPLogConstants.InvocationMode.SYNCHRONOUS);
426 final RESTRequest request = null; // TODO: build real request.
427 final RESTResponse response = client.execute(request); // TODO: handle real response.
429 // Set response details prior to #exiting.
430 // (Obviously there'd be errorhandling, etc. IRL).
432 adapter.getResponseDescriptor()
433 .setResponseCode((String)null)
434 .setResponseSeverity(Level.INFO)
435 .setResponseStatus(ONAPLogConstants.ResponseStatus.COMPLETE);
439 // Return, logging EXIT marker, with response MDCs.
446 * Dummy class, for example code.
448 static class RESTClient implements ONAPLogAdapter.RequestBuilder<RESTClient> {
451 public RESTClient setHeader(final String name, final String value) {
455 RESTResponse execute(RESTRequest request) {
461 * Dummy class, for example code.
463 static class RESTRequest {
468 * Dummy class, for example code.
470 static class RESTResponse {