8502d95023da5997f8fb367e5b6c2b5ed5ba5acd
[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.context;
18
19 import org.slf4j.MDC;
20 import org.testng.annotations.Test;
21
22 import java.util.UUID;
23 import java.util.concurrent.atomic.AtomicBoolean;
24
25 import static org.testng.Assert.*;
26
27 /**
28  * @author evitaliy
29  * @since 12/09/2016.
30  */
31 public class MDCPropagationFactoryTest {
32
33   // Disable if an old version of MDC implementation is being used.
34   // MDCPropagationFactory should be used when MDC is not propagated to child threads.
35   // See https://jira.qos.ch/browse/LOGBACK-422 and https://jira.qos.ch/browse/LOGBACK-624
36   private static final boolean ENABLED = false;
37
38   @Test(enabled = ENABLED)
39   public void testNoPropagation() throws InterruptedException {
40
41     String uuid = UUID.randomUUID().toString();
42     AtomicBoolean complete = new AtomicBoolean(false);
43     MDC.put("data", uuid);
44
45     Runnable runnable = () -> {
46       assertNull(MDC.get("data"), "Data unexpectedly copied to a child thread. " +
47               "Are you using an old version of MDC implementation (e.g. logback)?");
48       complete.set(true);
49     };
50
51     Thread thread = new Thread(runnable);
52     thread.start();
53     thread.join();
54
55     assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread");
56     assertTrue(complete.get(), "Expected the inner thread to run");
57   }
58
59   @Test(enabled = ENABLED)
60   public void testPropagation() throws InterruptedException {
61
62     String uuid = UUID.randomUUID().toString();
63     AtomicBoolean complete = new AtomicBoolean(false);
64     MDC.put("data", uuid);
65
66     MDCPropagationService factory = new MDCPropagationService();
67     Runnable runnable = factory.create(() -> {
68       assertEquals(MDC.get("data"), uuid, "Expected data to be propagated to the child thread's MDC");
69       complete.set(true);
70     });
71
72     Thread thread = new Thread(runnable);
73     thread.start();
74
75     thread.join();
76
77     assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread");
78     assertTrue(complete.get(), "Expected the inner thread to run");
79   }
80
81   @Test(enabled = ENABLED)
82   public void testReplacement() throws InterruptedException {
83
84     String innerUuid = UUID.randomUUID().toString();
85     AtomicBoolean innerComplete = new AtomicBoolean(false);
86     AtomicBoolean outerComplete = new AtomicBoolean(false);
87
88     MDC.put("data", innerUuid);
89
90     MDCPropagationService factory = new MDCPropagationService();
91
92     // should run with the context of main thread
93     Runnable inner = factory.create(() -> {
94       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
95       innerComplete.set(true);
96     });
97
98     // pushes its own context, but runs the inner runnable
99     Runnable outer = () -> {
100       String outerUuid = UUID.randomUUID().toString();
101       MDC.put("data", outerUuid);
102       inner.run();
103       assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be replaced with stored data");
104       outerComplete.set(true);
105     };
106
107
108     Thread thread = new Thread(outer);
109     thread.start();
110     thread.join();
111
112     assertEquals(MDC.get("data"), innerUuid, "Expected data to be retained in this thread");
113     assertTrue(outerComplete.get(), "Expected the outer thread to run");
114     assertTrue(innerComplete.get(), "Expected the inner thread to run");
115   }
116
117   @Test(enabled = ENABLED)
118   public void testEmpty() throws InterruptedException {
119
120     final AtomicBoolean complete = new AtomicBoolean(false);
121
122     MDC.remove("data");
123     assertNull(MDC.get("data"), "Expected MDC data to be empty");
124
125     MDCPropagationService factory = new MDCPropagationService();
126     Runnable runnable = factory.create(() -> {
127       assertNull(MDC.get("data"), "Expected MDC data to be empty");
128       complete.set(true);
129     });
130
131     Thread thread = new Thread(runnable);
132     thread.start();
133     thread.join();
134
135     assertNull(MDC.get("data"), "Expected MDC data to be empty");
136     assertTrue(complete.get(), "Expected the inner thread to run");
137   }
138
139   @Test(enabled = ENABLED)
140   public void testCleanup() throws Exception {
141
142     String innerUuid = UUID.randomUUID().toString();
143     AtomicBoolean innerComplete = new AtomicBoolean(false);
144     AtomicBoolean outerComplete = new AtomicBoolean(false);
145
146     MDC.put("data", innerUuid);
147
148     MDCPropagationService factory = new MDCPropagationService();
149
150     // should run with the context of main thread
151     Runnable inner = factory.create(() -> {
152       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
153       innerComplete.set(true);
154     });
155
156     // pushes its own context, but runs the inner runnable
157     Runnable outer = () -> {
158       assertNull(MDC.get("data"), "Expected MDC data not to be copied to this thread");
159       inner.run();
160       assertNull(MDC.get("data"), "Expected MDC data to remain empty in this thread");
161       outerComplete.set(true);
162     };
163
164     Thread thread = new Thread(outer);
165     thread.start();
166     thread.join();
167
168     assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread");
169     assertTrue(outerComplete.get(), "Expected the outer thread to run");
170     assertTrue(innerComplete.get(), "Expected the inner thread to run");
171   }
172
173   @Test(enabled = ENABLED)
174   public void testCleanupAfterError() throws Exception {
175
176     String innerUuid = UUID.randomUUID().toString();
177     AtomicBoolean innerComplete = new AtomicBoolean(false);
178     AtomicBoolean outerComplete = new AtomicBoolean(false);
179     AtomicBoolean exceptionThrown = new AtomicBoolean(false);
180
181     MDC.put("data", innerUuid);
182
183     MDCPropagationService factory = new MDCPropagationService();
184
185     // should run with the context of main thread
186     Runnable inner = factory.create(() -> {
187       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
188       innerComplete.set(true);
189       throw new RuntimeException();
190     });
191
192     // pushes its own context, but runs the inner runnable
193     Runnable outer = () -> {
194
195       String outerUuid = UUID.randomUUID().toString();
196       MDC.put("data", outerUuid);
197       assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be populated in this thread");
198
199       try {
200         inner.run();
201       } catch (RuntimeException e) {
202         exceptionThrown.set(true);
203       } finally {
204         assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be reverted even in case of exception");
205         outerComplete.set(true);
206       }
207     };
208
209     Thread thread = new Thread(outer);
210     thread.start();
211     thread.join();
212
213     assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread");
214     assertTrue(outerComplete.get(), "Expected the outer thread to run");
215     assertTrue(innerComplete.get(), "Expected the inner thread to run");
216     assertTrue(exceptionThrown.get(), "Expected the inner class to throw exception");
217   }
218
219 }