2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.logging.slf4j;
19 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EMPTY;
20 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EXCEPTION_FROM_INNER;
21 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_INNER_RUN;
22 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_NOT_COPIED;
23 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_OUTER_RUN;
24 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_POPULATED;
25 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_PROPAGATED_TO_CHILD;
26 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REMAIN_EMPTY;
27 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REPLACED_WITH_STORED;
28 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_CURRENT;
29 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_PARENT;
30 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REVERTED_ON_EXCEPTION;
31 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.IS_SUITABLE_LOGBACK_VERSION;
32 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextEmpty;
33 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextFields;
34 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.putUniqueValues;
35 import static org.testng.Assert.assertTrue;
38 import java.util.concurrent.Callable;
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.Executors;
41 import java.util.concurrent.Future;
42 import java.util.concurrent.TimeUnit;
43 import java.util.concurrent.atomic.AtomicBoolean;
44 import org.openecomp.sdc.logging.spi.LoggingContextService;
45 import org.testng.annotations.Test;
48 * Tests propagation of logging fields to Callable via the logging service.
53 @SuppressWarnings("DefaultAnnotationParam") // see the comment to ENABLED
54 public class CallableContextPropagationTest {
56 private final LoggingContextService ctxService = new SLF4JLoggingServiceProvider();
58 @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
59 public void testContextPropagated() throws Exception {
61 Map<ContextField, String> values = putUniqueValues();
62 AtomicBoolean complete = new AtomicBoolean(false);
64 // pass the callable to the context service first
65 execute(ctxService.copyToCallable(() -> {
66 assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
71 assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
72 assertTrue(complete.get(), EXPECT_INNER_RUN);
75 @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
76 public void testContextReplacement() throws Exception {
78 Map<ContextField, String> innerValues = putUniqueValues();
79 AtomicBoolean innerComplete = new AtomicBoolean(false);
81 // should run with the context of main thread
82 Callable inner = ctxService.copyToCallable(() -> {
83 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
84 innerComplete.set(true);
88 // pushes its own context, but the inner must run with its own context
89 AtomicBoolean outerComplete = new AtomicBoolean(false);
91 Map<ContextField, String> outerValues = putUniqueValues();
93 assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
94 outerComplete.set(true);
98 assertContextFields(innerValues, EXPECT_RETAINED_IN_CURRENT);
99 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
100 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
103 @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
104 public void testContextRemainsEmpty() throws Exception {
107 assertContextEmpty(EXPECT_EMPTY);
109 final AtomicBoolean complete = new AtomicBoolean(false);
110 execute(ctxService.copyToCallable(() -> {
111 assertContextEmpty(EXPECT_EMPTY);
116 assertContextEmpty(EXPECT_EMPTY);
117 assertTrue(complete.get(), EXPECT_INNER_RUN);
120 @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
121 public void testContextCleanedUp() throws Exception {
123 Map<ContextField, String> innerValues = putUniqueValues();
125 AtomicBoolean innerComplete = new AtomicBoolean(false);
126 // should run with the context of main thread
127 Callable inner = ctxService.copyToCallable((() -> {
128 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
129 innerComplete.set(true);
133 // pushes its own context, but runs the inner
134 AtomicBoolean outerComplete = new AtomicBoolean(false);
136 assertContextEmpty(EXPECT_NOT_COPIED);
138 assertContextEmpty(EXPECT_REMAIN_EMPTY);
139 outerComplete.set(true);
143 assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
144 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
145 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
148 @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
149 public void testCleanupAfterError() throws Exception {
151 Map<ContextField, String> innerValues = putUniqueValues();
153 // should run with the context of main thread
154 AtomicBoolean innerComplete = new AtomicBoolean(false);
155 Callable inner = ctxService.copyToCallable(() -> {
156 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
157 innerComplete.set(true);
158 throw new IllegalArgumentException();
161 // pushes its own context, but runs the inner callable
162 AtomicBoolean outerComplete = new AtomicBoolean(false);
163 AtomicBoolean exceptionThrown = new AtomicBoolean(false);
166 Map<ContextField, String> outerValues = putUniqueValues();
167 assertContextFields(outerValues, EXPECT_POPULATED);
171 } catch (IllegalArgumentException e) {
172 exceptionThrown.set(true);
174 assertContextFields(outerValues, EXPECT_REVERTED_ON_EXCEPTION);
175 outerComplete.set(true);
181 assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
182 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
183 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
184 assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);
187 private void execute(Callable<Object> callable) throws Exception {
189 ExecutorService executor = Executors.newSingleThreadExecutor();
192 Future<Object> future = executor.submit(callable);
193 future.get(10, TimeUnit.SECONDS);