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.spi.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.copyToRunnable(() -> {
 
  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.copyToRunnable(() -> {
 
  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.copyToRunnable(() -> {
 
 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.copyToRunnable(() -> {
 
 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.copyToRunnable(() -> {
 
 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);