58d52bfa0fc6bd442ae7c4b4ec62a27debc16495
[sdc.git] /
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.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextEmpty;
20 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextFields;
21 import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.putUniqueValues;
22 import static org.testng.Assert.assertTrue;
23
24 import java.util.Map;
25 import java.util.concurrent.Callable;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.Future;
29 import java.util.concurrent.TimeUnit;
30 import java.util.concurrent.atomic.AtomicBoolean;
31 import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
32 import org.openecomp.sdc.logging.spi.LoggingContextService;
33 import org.testng.annotations.Test;
34
35 /**
36  * @author evitaliy
37  * @since 08 Jan 18
38  */
39 public class CallableContextPropagationTest extends BaseContextPropagationTest {
40
41     @Test(enabled = ENABLED, dataProvider = PROVIDER)
42     public void testContextPropagated(LoggingContextService ctx) throws Exception {
43
44         Map<ContextField, String> values = putUniqueValues(ctx);
45         AtomicBoolean complete = new AtomicBoolean(false);
46
47         // pass the callable to the context service first
48         execute(ctx.copyToCallable(() -> {
49             assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
50             complete.set(true);
51             return null;
52         }));
53
54         assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
55         assertTrue(complete.get(), EXPECT_INNER_RUN);
56     }
57
58     @Test(enabled = ENABLED, dataProvider = PROVIDER)
59     public void testContextReplacement(LoggingContextService ctx) throws Exception {
60
61         Map<ContextField, String> innerValues = putUniqueValues(ctx);
62         AtomicBoolean innerComplete = new AtomicBoolean(false);
63
64         // should run with the context of main thread
65         Callable inner = ctx.copyToCallable(() -> {
66             assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
67             innerComplete.set(true);
68             return null;
69         });
70
71         // pushes its own context, but the inner must run with its own context
72         AtomicBoolean outerComplete = new AtomicBoolean(false);
73         execute(() -> {
74             Map<ContextField, String> outerValues = putUniqueValues(ctx);
75             inner.call();
76             assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
77             outerComplete.set(true);
78             return null;
79         });
80
81         assertContextFields(innerValues, EXPECT_RETAINED_IN_CURRENT);
82         assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
83         assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
84     }
85
86     @Test(enabled = ENABLED, dataProvider = PROVIDER)
87     public void testContextRemainsEmpty(LoggingContextService ctx) throws Exception {
88
89         ctx.clear();
90         assertContextEmpty(EXPECT_EMPTY);
91
92         final AtomicBoolean complete = new AtomicBoolean(false);
93         execute(ctx.copyToCallable(() -> {
94             assertContextEmpty(EXPECT_EMPTY);
95             complete.set(true);
96             return null;
97         }));
98
99         assertContextEmpty(EXPECT_EMPTY);
100         assertTrue(complete.get(), EXPECT_INNER_RUN);
101     }
102
103     @Test(enabled = ENABLED, dataProvider = PROVIDER)
104     public void testContextCleanedUp(LoggingContextService ctx) throws Exception {
105
106         Map<ContextField, String> innerValues = putUniqueValues(ctx);
107
108         AtomicBoolean innerComplete = new AtomicBoolean(false);
109         // should run with the context of main thread
110         Callable inner = ctx.copyToCallable((() -> {
111             assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
112             innerComplete.set(true);
113             return null;
114         }));
115
116         // pushes its own context, but runs the inner
117         AtomicBoolean outerComplete = new AtomicBoolean(false);
118         execute(() -> {
119             assertContextEmpty(EXPECT_NOT_COPIED);
120             inner.call();
121             assertContextEmpty(EXPECT_REMAIN_EMPTY);
122             outerComplete.set(true);
123             return null;
124         });
125
126         assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
127         assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
128         assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
129     }
130
131     @Test(enabled = ENABLED, dataProvider = PROVIDER)
132     public void testCleanupAfterError(LoggingContextService ctx) throws Exception {
133
134         Map<ContextField, String> innerValues = putUniqueValues(ctx);
135
136         // should run with the context of main thread
137         AtomicBoolean innerComplete = new AtomicBoolean(false);
138         Callable inner = ctx.copyToCallable(() -> {
139             assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
140             innerComplete.set(true);
141             throw new IllegalArgumentException();
142         });
143
144         // pushes its own context, but runs the inner callable
145         AtomicBoolean outerComplete = new AtomicBoolean(false);
146         AtomicBoolean exceptionThrown = new AtomicBoolean(false);
147         execute(() -> {
148
149             Map<ContextField, String> outerValues = putUniqueValues(ctx);
150             assertContextFields(outerValues, EXPECT_POPULATED);
151
152             try {
153                 inner.call();
154             } catch (IllegalArgumentException e) {
155                 exceptionThrown.set(true);
156             } finally {
157                 assertContextFields(outerValues, EXPECT_REVERTED_ON_EXCEPTION);
158                 outerComplete.set(true);
159             }
160
161             return null;
162         });
163
164         assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
165         assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
166         assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
167         assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);
168     }
169
170     private void execute(Callable<Object> callable) throws Exception {
171
172         ExecutorService executor = Executors.newSingleThreadExecutor();
173
174         try {
175             Future<Object> future = executor.submit(callable);
176             future.get(10, TimeUnit.SECONDS);
177         } finally {
178             executor.shutdown();
179         }
180     }
181 }