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.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;
25 import java.util.concurrent.atomic.AtomicBoolean;
26 import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
27 import org.openecomp.sdc.logging.spi.LoggingContextService;
28 import org.testng.annotations.Test;
34 public class RunnableContextPropagationTest extends BaseContextPropagationTest {
36 @Test(enabled = ENABLED, dataProvider = PROVIDER)
37 public void contextNotCopiedToChildThreadByDefault(LoggingContextService ctx)
38 throws InterruptedException {
40 Map<ContextField, String> values = putUniqueValues(ctx);
41 AtomicBoolean complete = new AtomicBoolean(false);
43 // create thread right away without copying context
44 Thread thread = new Thread(() -> {
45 assertContextEmpty("Data unexpectedly copied to a child thread. " +
46 "Are you using an old version of SLF4J diagnostic context implementation (e.g. logback)?");
53 assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
54 assertTrue(complete.get(), EXPECT_INNER_RUN);
57 @Test(enabled = ENABLED, dataProvider = PROVIDER)
58 public void contextCopiedWhenToRunnableCalled(LoggingContextService ctx)
59 throws InterruptedException {
61 Map<ContextField, String> values = putUniqueValues(ctx);
62 AtomicBoolean complete = new AtomicBoolean(false);
64 // pass the runnable to the context service first
65 Thread thread = new Thread(ctx.copyToRunnable(() -> {
66 assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
73 assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
74 assertTrue(complete.get(), EXPECT_INNER_RUN);
77 @Test(enabled = ENABLED, dataProvider = PROVIDER)
78 public void copiedContextRetainedEvenWhenAnotherPushed(LoggingContextService ctx)
79 throws InterruptedException {
81 Map<ContextField, String> innerValues = putUniqueValues(ctx);
82 AtomicBoolean innerComplete = new AtomicBoolean(false);
84 // should run with the context of main thread
85 Runnable inner = ctx.copyToRunnable(() -> {
86 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
87 innerComplete.set(true);
90 // pushes its context, but the inner must run with its own context
91 AtomicBoolean outerComplete = new AtomicBoolean(false);
92 Thread outer = new Thread(() -> {
93 Map<ContextField, String> outerValues = putUniqueValues(ctx);
95 assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
96 outerComplete.set(true);
102 assertContextFields(innerValues, EXPECT_RETAINED_IN_CURRENT);
103 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
104 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
107 @Test(enabled = ENABLED, dataProvider = PROVIDER)
108 public void contextRemainsEmptyWhenParentWasEmpty(LoggingContextService ctx)
109 throws InterruptedException {
112 assertContextEmpty(EXPECT_EMPTY);
114 final AtomicBoolean complete = new AtomicBoolean(false);
115 Runnable runnable = ctx.copyToRunnable(() -> {
116 assertContextEmpty(EXPECT_EMPTY);
120 Thread thread = new Thread(runnable);
124 assertContextEmpty(EXPECT_EMPTY);
125 assertTrue(complete.get(), EXPECT_INNER_RUN);
128 @Test(enabled = ENABLED, dataProvider = PROVIDER)
129 public void childThreadCleanedUpAfterRunnableRuns(LoggingContextService ctx)
132 Map<ContextField, String> innerValues = putUniqueValues(ctx);
133 AtomicBoolean innerComplete = new AtomicBoolean(false);
134 // should run with the context of main thread
135 Runnable inner = ctx.copyToRunnable(() -> {
136 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
137 innerComplete.set(true);
140 // pushes its own context, but runs the inner
141 AtomicBoolean outerComplete = new AtomicBoolean(false);
142 Thread outer = new Thread(() -> {
143 assertContextEmpty(EXPECT_NOT_COPIED);
145 assertContextEmpty(EXPECT_REMAIN_EMPTY);
146 outerComplete.set(true);
152 assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
153 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
154 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
157 @Test(enabled = ENABLED, dataProvider = PROVIDER)
158 public void childThreadCleanedUpAfterException(LoggingContextService ctx)
161 Map<ContextField, String> innerValues = putUniqueValues(ctx);
163 // should run with the context of main thread
164 AtomicBoolean innerComplete = new AtomicBoolean(false);
165 Runnable inner = ctx.copyToRunnable(() -> {
166 assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
167 innerComplete.set(true);
168 throw new IllegalArgumentException();
171 // pushes its own context, but runs the inner runnable
172 AtomicBoolean outerComplete = new AtomicBoolean(false);
173 AtomicBoolean exceptionThrown = new AtomicBoolean(false);
174 Thread outer = new Thread(() -> {
176 Map<ContextField, String> outerValues = putUniqueValues(ctx);
177 assertContextFields(outerValues, EXPECT_POPULATED);
181 } catch (IllegalArgumentException e) {
182 exceptionThrown.set(true);
184 assertContextFields(outerValues, EXPECT_REVERTED_ON_EXCEPTION);
185 outerComplete.set(true);
192 assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
193 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
194 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
195 assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);