c0aa1d018ab59bf6560e713b16b3969c60961fff
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.logging.context;
22
23 import org.slf4j.MDC;
24 import org.testng.annotations.Test;
25
26 import java.util.UUID;
27 import java.util.concurrent.atomic.AtomicBoolean;
28
29 import static org.testng.Assert.*;
30
31 /**
32  * @author evitaliy
33  * @since 12/09/2016.
34  */
35 public class MDCPropagationFactoryTest {
36
37   // Disable if an old version of MDC implementation is being used.
38   // MDCPropagationFactory should be used when MDC is not propagated to child threads.
39   // See https://jira.qos.ch/browse/LOGBACK-422 and https://jira.qos.ch/browse/LOGBACK-624
40   private static final boolean ENABLED = false;
41
42   @Test(enabled = ENABLED)
43   public void testNoPropagation() throws InterruptedException {
44
45     String uuid = UUID.randomUUID().toString();
46     AtomicBoolean complete = new AtomicBoolean(false);
47     MDC.put("data", uuid);
48
49     Runnable runnable = () -> {
50       assertNull(MDC.get("data"), "Data unexpectedly copied to a child thread. " +
51               "Are you using an old version of MDC implementation (e.g. logback)?");
52       complete.set(true);
53     };
54
55     Thread thread = new Thread(runnable);
56     thread.start();
57     thread.join();
58
59     assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread");
60     assertTrue(complete.get(), "Expected the inner thread to run");
61   }
62
63   @Test(enabled = ENABLED)
64   public void testPropagation() throws InterruptedException {
65
66     String uuid = UUID.randomUUID().toString();
67     AtomicBoolean complete = new AtomicBoolean(false);
68     MDC.put("data", uuid);
69
70     MDCPropagationService factory = new MDCPropagationService();
71     Runnable runnable = factory.create(() -> {
72       assertEquals(MDC.get("data"), uuid, "Expected data to be propagated to the child thread's MDC");
73       complete.set(true);
74     });
75
76     Thread thread = new Thread(runnable);
77     thread.start();
78
79     thread.join();
80
81     assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread");
82     assertTrue(complete.get(), "Expected the inner thread to run");
83   }
84
85   @Test(enabled = ENABLED)
86   public void testReplacement() throws InterruptedException {
87
88     String innerUuid = UUID.randomUUID().toString();
89     AtomicBoolean innerComplete = new AtomicBoolean(false);
90     AtomicBoolean outerComplete = new AtomicBoolean(false);
91
92     MDC.put("data", innerUuid);
93
94     MDCPropagationService factory = new MDCPropagationService();
95
96     // should run with the context of main thread
97     Runnable inner = factory.create(() -> {
98       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
99       innerComplete.set(true);
100     });
101
102     // pushes its own context, but runs the inner runnable
103     Runnable outer = () -> {
104       String outerUuid = UUID.randomUUID().toString();
105       MDC.put("data", outerUuid);
106       inner.run();
107       assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be replaced with stored data");
108       outerComplete.set(true);
109     };
110
111
112     Thread thread = new Thread(outer);
113     thread.start();
114     thread.join();
115
116     assertEquals(MDC.get("data"), innerUuid, "Expected data to be retained in this thread");
117     assertTrue(outerComplete.get(), "Expected the outer thread to run");
118     assertTrue(innerComplete.get(), "Expected the inner thread to run");
119   }
120
121   @Test(enabled = ENABLED)
122   public void testEmpty() throws InterruptedException {
123
124     final AtomicBoolean complete = new AtomicBoolean(false);
125
126     MDC.remove("data");
127     assertNull(MDC.get("data"), "Expected MDC data to be empty");
128
129     MDCPropagationService factory = new MDCPropagationService();
130     Runnable runnable = factory.create(() -> {
131       assertNull(MDC.get("data"), "Expected MDC data to be empty");
132       complete.set(true);
133     });
134
135     Thread thread = new Thread(runnable);
136     thread.start();
137     thread.join();
138
139     assertNull(MDC.get("data"), "Expected MDC data to be empty");
140     assertTrue(complete.get(), "Expected the inner thread to run");
141   }
142
143   @Test(enabled = ENABLED)
144   public void testCleanup() throws Exception {
145
146     String innerUuid = UUID.randomUUID().toString();
147     AtomicBoolean innerComplete = new AtomicBoolean(false);
148     AtomicBoolean outerComplete = new AtomicBoolean(false);
149
150     MDC.put("data", innerUuid);
151
152     MDCPropagationService factory = new MDCPropagationService();
153
154     // should run with the context of main thread
155     Runnable inner = factory.create(() -> {
156       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
157       innerComplete.set(true);
158     });
159
160     // pushes its own context, but runs the inner runnable
161     Runnable outer = () -> {
162       assertNull(MDC.get("data"), "Expected MDC data not to be copied to this thread");
163       inner.run();
164       assertNull(MDC.get("data"), "Expected MDC data to remain empty in this thread");
165       outerComplete.set(true);
166     };
167
168     Thread thread = new Thread(outer);
169     thread.start();
170     thread.join();
171
172     assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread");
173     assertTrue(outerComplete.get(), "Expected the outer thread to run");
174     assertTrue(innerComplete.get(), "Expected the inner thread to run");
175   }
176
177   @Test(enabled = ENABLED)
178   public void testCleanupAfterError() throws Exception {
179
180     String innerUuid = UUID.randomUUID().toString();
181     AtomicBoolean innerComplete = new AtomicBoolean(false);
182     AtomicBoolean outerComplete = new AtomicBoolean(false);
183     AtomicBoolean exceptionThrown = new AtomicBoolean(false);
184
185     MDC.put("data", innerUuid);
186
187     MDCPropagationService factory = new MDCPropagationService();
188
189     // should run with the context of main thread
190     Runnable inner = factory.create(() -> {
191       assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC");
192       innerComplete.set(true);
193       throw new RuntimeException();
194     });
195
196     // pushes its own context, but runs the inner runnable
197     Runnable outer = () -> {
198
199       String outerUuid = UUID.randomUUID().toString();
200       MDC.put("data", outerUuid);
201       assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be populated in this thread");
202
203       try {
204         inner.run();
205       } catch (RuntimeException e) {
206         exceptionThrown.set(true);
207       } finally {
208         assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be reverted even in case of exception");
209         outerComplete.set(true);
210       }
211     };
212
213     Thread thread = new Thread(outer);
214     thread.start();
215     thread.join();
216
217     assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread");
218     assertTrue(outerComplete.get(), "Expected the outer thread to run");
219     assertTrue(innerComplete.get(), "Expected the inner thread to run");
220     assertTrue(exceptionThrown.get(), "Expected the inner class to throw exception");
221   }
222
223 }