Added oparent to sdc main
[sdc.git] / openecomp-be / lib / openecomp-sdc-logging-lib / openecomp-sdc-logging-core / src / test / java / org / openecomp / sdc / logging / slf4j / CallableContextPropagationTest.java
1 /*
2  * Copyright © 2016-2017 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.openecomp.sdc.logging.slf4j;
18
19 import static org.junit.Assert.assertTrue;
20 import static org.junit.Assume.assumeTrue;
21 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EMPTY;
22 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EXCEPTION_FROM_INNER;
23 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_INNER_RUN;
24 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_NOT_COPIED;
25 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_OUTER_RUN;
26 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_POPULATED;
27 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_PROPAGATED_TO_CHILD;
28 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REMAIN_EMPTY;
29 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REPLACED_WITH_STORED;
30 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_CURRENT;
31 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_PARENT;
32 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REVERTED_ON_EXCEPTION;
33 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.IS_SUITABLE_LOGBACK_VERSION;
34 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextEmpty;
35 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextFields;
36 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.putUniqueValues;
37
38 import java.util.Map;
39 import java.util.concurrent.Callable;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.Executors;
42 import java.util.concurrent.Future;
43 import java.util.concurrent.TimeUnit;
44 import java.util.concurrent.atomic.AtomicBoolean;
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.openecomp.sdc.logging.spi.LoggingContextService;
48
49 /**
50  * Tests propagation of logging fields to Callable via the logging service.
51  * 
52  * @author evitaliy
53  * @since 08 Jan 18
54  */
55 @SuppressWarnings("DefaultAnnotationParam") // see the comment to ENABLED
56 public class CallableContextPropagationTest {
57
58     private final LoggingContextService ctxService = new SLF4JLoggingServiceProvider();
59
60     @Before
61     public void checkSuitableLogbackVersion() {
62         assumeTrue(IS_SUITABLE_LOGBACK_VERSION);
63     }
64
65     @Test
66     public void testContextPropagated() throws Exception {
67
68         Map<ContextField, String> values = putUniqueValues();
69         AtomicBoolean complete = new AtomicBoolean(false);
70
71         // pass the callable to the context service first
72         execute(ctxService.copyToCallable(() -> {
73             assertContextFields(EXPECT_PROPAGATED_TO_CHILD, values);
74             complete.set(true);
75             return null;
76         }));
77
78         assertContextFields(EXPECT_RETAINED_IN_CURRENT, values);
79         assertTrue(EXPECT_INNER_RUN, complete.get());
80     }
81
82     @Test
83     public void testContextReplacement() throws Exception {
84
85         Map<ContextField, String> innerValues = putUniqueValues();
86         AtomicBoolean innerComplete = new AtomicBoolean(false);
87
88         // should run with the context of main thread
89         Callable inner = ctxService.copyToCallable(() -> {
90             assertContextFields(EXPECT_PROPAGATED_TO_CHILD, innerValues);
91             innerComplete.set(true);
92             return null;
93         });
94
95         // pushes its own context, but the inner must run with its own context
96         AtomicBoolean outerComplete = new AtomicBoolean(false);
97         execute(() -> {
98             Map<ContextField, String> outerValues = putUniqueValues();
99             inner.call();
100             assertContextFields(EXPECT_REPLACED_WITH_STORED, outerValues);
101             outerComplete.set(true);
102             return null;
103         });
104
105         assertContextFields(EXPECT_RETAINED_IN_CURRENT, innerValues);
106         assertTrue(EXPECT_OUTER_RUN, outerComplete.get());
107         assertTrue(EXPECT_INNER_RUN, innerComplete.get());
108     }
109
110     @Test
111     public void testContextRemainsEmpty() throws Exception {
112
113         ctxService.clear();
114         assertContextEmpty(EXPECT_EMPTY);
115
116         final AtomicBoolean complete = new AtomicBoolean(false);
117         execute(ctxService.copyToCallable(() -> {
118             assertContextEmpty(EXPECT_EMPTY);
119             complete.set(true);
120             return null;
121         }));
122
123         assertContextEmpty(EXPECT_EMPTY);
124         assertTrue(EXPECT_INNER_RUN, complete.get());
125     }
126
127     @Test
128     public void testContextCleanedUp() throws Exception {
129
130         Map<ContextField, String> innerValues = putUniqueValues();
131
132         AtomicBoolean innerComplete = new AtomicBoolean(false);
133         // should run with the context of main thread
134         Callable inner = ctxService.copyToCallable((() -> {
135             assertContextFields(EXPECT_PROPAGATED_TO_CHILD, innerValues);
136             innerComplete.set(true);
137             return null;
138         }));
139
140         // pushes its own context, but runs the inner
141         AtomicBoolean outerComplete = new AtomicBoolean(false);
142         execute(() -> {
143             assertContextEmpty(EXPECT_NOT_COPIED);
144             inner.call();
145             assertContextEmpty(EXPECT_REMAIN_EMPTY);
146             outerComplete.set(true);
147             return null;
148         });
149
150         assertContextFields(EXPECT_RETAINED_IN_PARENT, innerValues);
151         assertTrue(EXPECT_OUTER_RUN, outerComplete.get());
152         assertTrue(EXPECT_INNER_RUN, innerComplete.get());
153     }
154
155     @Test
156     public void testCleanupAfterError() throws Exception {
157
158         Map<ContextField, String> innerValues = putUniqueValues();
159
160         // should run with the context of main thread
161         AtomicBoolean innerComplete = new AtomicBoolean(false);
162         Callable inner = ctxService.copyToCallable(() -> {
163             assertContextFields(EXPECT_PROPAGATED_TO_CHILD, innerValues);
164             innerComplete.set(true);
165             throw new IllegalArgumentException();
166         });
167
168         // pushes its own context, but runs the inner callable
169         AtomicBoolean outerComplete = new AtomicBoolean(false);
170         AtomicBoolean exceptionThrown = new AtomicBoolean(false);
171         execute(() -> {
172
173             Map<ContextField, String> outerValues = putUniqueValues();
174             assertContextFields(EXPECT_POPULATED, outerValues);
175
176             try {
177                 inner.call();
178             } catch (IllegalArgumentException e) {
179                 exceptionThrown.set(true);
180             } finally {
181                 assertContextFields(EXPECT_REVERTED_ON_EXCEPTION, outerValues);
182                 outerComplete.set(true);
183             }
184
185             return null;
186         });
187
188         assertContextFields(EXPECT_RETAINED_IN_PARENT, innerValues);
189         assertTrue(EXPECT_OUTER_RUN, outerComplete.get());
190         assertTrue(EXPECT_INNER_RUN, innerComplete.get());
191         assertTrue(EXPECT_EXCEPTION_FROM_INNER, exceptionThrown.get());
192     }
193
194     private void execute(Callable<Object> callable) throws Exception {
195
196         ExecutorService executor = Executors.newSingleThreadExecutor();
197
198         try {
199             Future<Object> future = executor.submit(callable);
200             future.get(10, TimeUnit.SECONDS);
201         } finally {
202             executor.shutdown();
203         }
204     }
205 }