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 org.openecomp.sdc.logging.provider.LoggingContextService;
20 import org.testng.annotations.Test;
22 import java.util.UUID;
23 import java.util.concurrent.atomic.AtomicBoolean;
25 import static org.testng.Assert.assertEquals;
26 import static org.testng.Assert.assertNull;
27 import static org.testng.Assert.assertTrue;
33 public class RunnableContextPropagationTest extends BaseContextPropagationTest {
35 @Test(enabled = ENABLED, dataProvider = PROVIDER)
36 public void contextNotCopiedToChildThreadByDefault(LoggingContextService ctx)
37 throws InterruptedException {
39 String random = UUID.randomUUID().toString();
42 AtomicBoolean complete = new AtomicBoolean(false);
44 // create thread right away without copying context
45 Thread thread = new Thread(() -> {
46 assertNull(ctx.get(KEY), "Data unexpectedly copied to a child thread. " +
47 "Are you using an old version of SLF4J diagnostic context implementation (e.g. logback)?");
54 assertEquals(ctx.get(KEY), random, EXPECT_RETAINED_IN_CURRENT);
55 assertTrue(complete.get(), EXPECT_INNER_RUN);
58 @Test(enabled = ENABLED, dataProvider = PROVIDER)
59 public void contextCopiedWhenToRunnableCalled(LoggingContextService ctx)
60 throws InterruptedException {
62 String uuid = UUID.randomUUID().toString();
65 AtomicBoolean complete = new AtomicBoolean(false);
67 // pass the runnable to the context service first
68 Thread thread = new Thread(ctx.toRunnable(() -> {
69 assertEquals(ctx.get(KEY), uuid, EXPECT_PROPAGATED_TO_CHILD);
76 assertEquals(ctx.get(KEY), uuid, EXPECT_RETAINED_IN_CURRENT);
77 assertTrue(complete.get(), EXPECT_INNER_RUN);
80 @Test(enabled = ENABLED, dataProvider = PROVIDER)
81 public void copiedContextRetainedEvenWhenAnotherPushed(LoggingContextService ctx)
82 throws InterruptedException {
84 String innerRandom = UUID.randomUUID().toString();
85 ctx.put(KEY, innerRandom);
87 AtomicBoolean innerComplete = new AtomicBoolean(false);
89 // should run with the context of main thread
90 Runnable inner = ctx.toRunnable(() -> {
91 assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
92 innerComplete.set(true);
95 // pushes its context, but the inner must run with its own context
96 AtomicBoolean outerComplete = new AtomicBoolean(false);
97 Thread outer = new Thread(() -> {
98 String outerUuid = UUID.randomUUID().toString();
99 ctx.put(KEY, outerUuid);
101 assertEquals(ctx.get(KEY), outerUuid, EXPECT_REPLACED_WITH_STORED);
102 outerComplete.set(true);
108 assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_CURRENT);
109 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
110 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
113 @Test(enabled = ENABLED, dataProvider = PROVIDER)
114 public void contextRemainsEmptyWhenParentWasEmpty(LoggingContextService ctx)
115 throws InterruptedException {
118 assertNull(ctx.get(KEY), EXPECT_EMPTY);
120 final AtomicBoolean complete = new AtomicBoolean(false);
121 Runnable runnable = ctx.toRunnable(() -> {
122 assertNull(ctx.get(KEY), EXPECT_EMPTY);
126 Thread thread = new Thread(runnable);
130 assertNull(ctx.get(KEY), EXPECT_EMPTY);
131 assertTrue(complete.get(), EXPECT_INNER_RUN);
134 @Test(enabled = ENABLED, dataProvider = PROVIDER)
135 public void childThreadCleanedUpAfterRunnableRuns(LoggingContextService ctx)
138 String innerRandom = UUID.randomUUID().toString();
139 ctx.put(KEY, innerRandom);
141 AtomicBoolean innerComplete = new AtomicBoolean(false);
142 // should run with the context of main thread
143 Runnable inner = ctx.toRunnable(() -> {
144 assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
145 innerComplete.set(true);
148 // pushes its own context, but runs the inner
149 AtomicBoolean outerComplete = new AtomicBoolean(false);
150 Thread outer = new Thread(() -> {
151 assertNull(ctx.get(KEY), EXPECT_NOT_COPIED);
153 assertNull(ctx.get(KEY), EXPECT_REMAIN_EMPTY);
154 outerComplete.set(true);
160 assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
161 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
162 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
165 @Test(enabled = ENABLED, dataProvider = PROVIDER)
166 public void childThreadCleanedUpAfterException(LoggingContextService ctx)
169 String innerRandom = UUID.randomUUID().toString();
170 ctx.put(KEY, innerRandom);
172 // should run with the context of main thread
173 AtomicBoolean innerComplete = new AtomicBoolean(false);
174 Runnable inner = ctx.toRunnable(() -> {
175 assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
176 innerComplete.set(true);
177 throw new IllegalArgumentException();
180 // pushes its own context, but runs the inner runnable
181 AtomicBoolean outerComplete = new AtomicBoolean(false);
182 AtomicBoolean exceptionThrown = new AtomicBoolean(false);
183 Thread outer = new Thread(() -> {
185 String outerUuid = UUID.randomUUID().toString();
186 ctx.put(KEY, outerUuid);
187 assertEquals(ctx.get(KEY), outerUuid, EXPECT_POPULATED);
191 } catch (IllegalArgumentException e) {
192 exceptionThrown.set(true);
194 assertEquals(ctx.get(KEY), outerUuid, EXPECT_REVERTED_ON_EXCEPTION);
195 outerComplete.set(true);
202 assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
203 assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
204 assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
205 assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);