fix - when retrieve topology we are using threadPool and the MDC values are not updated 46/98046/6
authorIttay Stern <ittay.stern@att.com>
Wed, 6 Nov 2019 12:27:53 +0000 (14:27 +0200)
committerIttay Stern <ittay.stern@att.com>
Thu, 7 Nov 2019 14:19:47 +0000 (14:19 +0000)
This time for homing-by-vnf-id parallel requests.

Issue-ID: VID-253

Change-Id: Ic0be1470445c6fef0e18f9b9d8f1604df508265b
Signed-off-by: Ittay Stern <ittay.stern@att.com>
15 files changed:
vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java
vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java
vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java
vid-app-common/src/main/java/org/onap/vid/utils/Logging.java
vid-app-common/src/main/java/org/onap/vid/utils/Unchecked.java
vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java
vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java
vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java
vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeTest.java
vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java
vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java
vid-app-common/src/test/java/org/onap/vid/utils/LoggingTest.java [deleted file]
vid-app-common/src/test/java/org/onap/vid/utils/LoggingUtilsTest.java
vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java
vid-automation/src/test/java/org/onap/vid/api/ServiceTreeApiTest.java

index 096dba3..c50578e 100644 (file)
@@ -58,7 +58,6 @@ import org.onap.vid.properties.VidProperties;
 import org.onap.vid.scheduler.SchedulerService;
 import org.onap.vid.scheduler.SchedulerServiceImpl;
 import org.onap.vid.services.AAIServiceTree;
-import org.onap.vid.services.AAITreeNodeBuilder;
 import org.onap.vid.services.AaiService;
 import org.onap.vid.services.AaiServiceImpl;
 import org.onap.vid.services.ChangeManagementService;
@@ -101,8 +100,8 @@ public class WebConfig implements WebMvcConfigurer {
 
     @Bean
     public AaiService getAaiService(AaiClientInterface aaiClient, AaiResponseTranslator aaiResponseTranslator,
-        AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) {
-        return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService);
+        AAIServiceTree aaiServiceTree, Logging logging, ExecutorService executorService) {
+        return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService, logging);
     }
 
     @Bean
index c843460..209f370 100644 (file)
@@ -59,6 +59,7 @@ import org.onap.vid.model.aaiTree.FailureAAITreeNode;
 import org.onap.vid.model.aaiTree.NodeType;
 import org.onap.vid.mso.model.CloudConfiguration;
 import org.onap.vid.properties.VidProperties;
+import org.onap.vid.utils.Logging;
 import org.onap.vid.utils.Streams;
 import org.onap.vid.utils.Tree;
 import org.onap.vid.utils.Unchecked;
@@ -71,7 +72,8 @@ import org.springframework.stereotype.Component;
 public class AAITreeNodeBuilder {
 
     private static final String RESULTS = "results";
-    private AaiClientInterface aaiClient;
+    private final AaiClientInterface aaiClient;
+    private final Logging logging;
 
     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodeBuilder.class);
 
@@ -97,8 +99,9 @@ public class AAITreeNodeBuilder {
     }
 
     @Inject
-    public AAITreeNodeBuilder(AaiClientInterface aaiClient) {
+    public AAITreeNodeBuilder(AaiClientInterface aaiClient, Logging logging) {
         this.aaiClient = aaiClient;
+        this.logging = logging;
     }
 
     List<AAITreeNode> buildNode(NodeType nodeType,
@@ -296,13 +299,7 @@ public class AAITreeNodeBuilder {
     }
 
     private <V> Callable<V> withCopyOfMDC(Callable<V> callable) {
-        //in order to be able to write the correct data while creating the node on a new thread
-        // save a copy of the current thread's context map, with keys and values of type String.
-        final Map<String, String> copyOfParentMDC = MDC.getCopyOfContextMap();
-        return () -> {
-            MDC.setContextMap(copyOfParentMDC);
-            return callable.call();
-        };
+        return logging.withMDC(MDC.getCopyOfContextMap(), callable);
     }
 
     private List<AAITreeNode> getChildNode(ExecutorService threadPool, ConcurrentSkipListSet<AAITreeNode> nodesAccumulator,
index b64a233..b3ac168 100644 (file)
@@ -87,7 +87,9 @@ import org.onap.vid.model.aaiTree.VpnBinding;
 import org.onap.vid.model.aaiTree.VpnBindingKt;
 import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.utils.Intersection;
+import org.onap.vid.utils.Logging;
 import org.onap.vid.utils.Tree;
+import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpMethod;
 
@@ -104,6 +106,7 @@ public class AaiServiceImpl implements AaiService {
     private AaiResponseTranslator aaiResponseTranslator;
     private AAIServiceTree aaiServiceTree;
     private ExecutorService executorService;
+    private final Logging logging;
 
 
     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class);
@@ -113,12 +116,13 @@ public class AaiServiceImpl implements AaiService {
         AaiClientInterface aaiClient,
         AaiResponseTranslator aaiResponseTranslator,
         AAIServiceTree aaiServiceTree,
-        ExecutorService executorService)
+        ExecutorService executorService, Logging logging)
     {
         this.aaiClient = aaiClient;
         this.aaiResponseTranslator = aaiResponseTranslator;
         this.aaiServiceTree = aaiServiceTree;
         this.executorService = executorService;
+        this.logging = logging;
     }
 
     private List<Service> convertModelToService(Model model) {
@@ -523,10 +527,12 @@ public class AaiServiceImpl implements AaiService {
                 .map(RelatedVnf::from)
                 .collect(Collectors.toList());
 
+        final Map<String, String> copyOfParentMDC = MDC.getCopyOfContextMap();
+
         try {
             return executorService.submit(() ->
                     convertedVnfs.parallelStream()
-                            .map(this::enrichRelatedVnfWithCloudRegionAndTenant)
+                            .map(logging.withMDC(copyOfParentMDC, this::enrichRelatedVnfWithCloudRegionAndTenant))
                             .collect(Collectors.toList())
             ).get();
         } catch (Exception e) {
index 0d8e588..43f059d 100644 (file)
@@ -33,8 +33,11 @@ import com.google.common.collect.ImmutableList;
 import io.joshworks.restclient.http.HttpResponse;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.function.Function;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
@@ -42,6 +45,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.portalsdk.core.util.SystemProperties;
 import org.onap.vid.exceptions.GenericUncheckedException;
+import org.onap.vid.utils.Unchecked.UncheckedThrowingSupplier;
+import org.slf4j.MDC;
 import org.springframework.http.HttpMethod;
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.RequestContextHolder;
@@ -197,5 +202,29 @@ public class Logging {
         }
     }
 
+    /**
+     * in order to be able to write the correct data while creating the node on a new thread save a copy of the current
+     * thread's context map, with keys and values of type String.
+     */
+    public <T> Callable<T> withMDC(Map<String, String> copyOfParentMDC, Callable<T> callable) {
+        return () -> withMDCInternal(copyOfParentMDC, callable::call);
+    }
+
+    /**
+     * in order to be able to write the correct data while creating the node on a new thread save a copy of the current
+     * thread's context map, with keys and values of type String.
+     */
+    public <T, U> Function<T, U> withMDC(Map<String, String> copyOfParentMDC, Function<T, U> function) {
+        return t -> withMDCInternal(copyOfParentMDC, () -> function.apply(t));
+    }
+
+    <T> T withMDCInternal(Map<String, String> copyOfParentMDC, UncheckedThrowingSupplier<T> supplier) {
+        try {
+            MDC.setContextMap(copyOfParentMDC);
+            return supplier.get();
+        } finally {
+            MDC.clear();
+        }
+    }
 
 }
index 23127b6..9fb15f6 100644 (file)
 
 package org.onap.vid.utils;
 
-import org.onap.vid.exceptions.GenericUncheckedException;
-
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.function.Supplier;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.onap.vid.exceptions.GenericUncheckedException;
 
 public class Unchecked {
     private Unchecked() {
@@ -39,5 +40,19 @@ public class Unchecked {
         }
     }
 
+    @FunctionalInterface
+    public interface UncheckedThrowingSupplier<T> extends Supplier<T> {
+
+        @Override
+        default T get() {
+            try {
+                return getThrows();
+            } catch (Exception e) {
+                return ExceptionUtils.rethrow(e);
+            }
+        }
+
+        T getThrows() throws Exception;
+    }
 
 }
index fcc314a..681f9d1 100644 (file)
@@ -40,7 +40,6 @@ import org.onap.vid.asdc.AsdcClient;
 import org.onap.vid.asdc.parser.ToscaParserImpl2;
 import org.onap.vid.asdc.parser.VidNotionsBuilder;
 import org.onap.vid.services.AAIServiceTree;
-import org.onap.vid.services.AAITreeNodeBuilder;
 import org.onap.vid.services.AaiService;
 import org.onap.vid.services.AaiServiceImpl;
 import org.onap.vid.services.VidService;
@@ -72,8 +71,8 @@ public class LocalWebConfig {
 
     @Bean
     public AaiService getAaiService(AaiClientInterface aaiClient, AaiResponseTranslator aaiResponseTranslator,
-        AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) {
-        return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService);
+        AAIServiceTree aaiServiceTree, Logging logging, ExecutorService executorService) {
+        return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService, logging);
     }
 
     @Bean
index a159efd..3a05a84 100644 (file)
@@ -47,6 +47,7 @@ import org.onap.vid.aai.util.TestWithAaiClient;
 import org.onap.vid.model.aaiTree.Network;
 import org.onap.vid.model.aaiTree.VpnBinding;
 import org.onap.vid.testUtils.TestUtils;
+import org.onap.vid.utils.Logging;
 import org.springframework.http.HttpMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
@@ -56,19 +57,20 @@ public class AAIServiceIntegrativeTest extends TestWithAaiClient {
 
     private AAIRestInterface aaiRestInterface;
     private AaiServiceImpl aaiServiceWithoutMocks;
+    private Logging logging = new Logging();
 
     private AaiServiceImpl createAaiServiceWithoutMocks(AAIRestInterface aaiRestInterface, CacheProvider cacheProvider) {
         AaiClient aaiClient = new AaiClient(aaiRestInterface, null, cacheProvider);
         ExecutorService executorService = MoreExecutors.newDirectExecutorService();
         AAIServiceTree aaiServiceTree = new AAIServiceTree(
                 aaiClient,
-                new AAITreeNodeBuilder(aaiClient),
+                new AAITreeNodeBuilder(aaiClient, logging),
                 new AAITreeConverter(),
                 null,
                 null,
                 executorService
         );
-        return new AaiServiceImpl(aaiClient, null, aaiServiceTree, executorService);
+        return new AaiServiceImpl(aaiClient, null, aaiServiceTree, executorService, logging);
     }
 
     @BeforeMethod
index a956468..0f9d6b4 100644 (file)
@@ -54,6 +54,7 @@ import org.onap.vid.model.aaiTree.FailureAAITreeNode;
 import org.onap.vid.model.aaiTree.ServiceInstance;
 import org.onap.vid.model.aaiTree.Vnf;
 import org.onap.vid.testUtils.TestUtils;
+import org.onap.vid.utils.Logging;
 import org.springframework.http.HttpMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -78,6 +79,7 @@ public class AAIServiceTreeIntegrativeTest {
     private AAITreeNodeBuilder aaiTreeNodeBuilder;
 
     private AAITreeConverter aaiTreeConverter = new AAITreeConverter();
+    private Logging logging = new Logging();
 
     private ExecutorService executorService = Executors.newFixedThreadPool(10);
 
@@ -292,7 +294,7 @@ public class AAIServiceTreeIntegrativeTest {
     @BeforeMethod
     public void initMocks() {
         TestUtils.initMockitoMocks(this);
-        aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClient);
+        aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClient, logging);
     }
 
     public void getServiceInstanceTreeAndAssert(boolean isDuplicatedKeysInTenantRelation) throws IOException, AsdcCatalogException {
index ada1f85..7457e48 100644 (file)
@@ -55,6 +55,7 @@ import org.onap.vid.model.aaiTree.AAITreeNode;
 import org.onap.vid.model.aaiTree.NodeType;
 import org.onap.vid.mso.model.CloudConfiguration;
 import org.onap.vid.testUtils.TestUtils;
+import org.onap.vid.utils.Logging;
 import org.onap.vid.utils.Unchecked;
 import org.springframework.http.HttpMethod;
 import org.testng.annotations.BeforeTest;
@@ -199,7 +200,7 @@ public class AAIServiceTreeTest {
         ExecutorService executorService = MoreExecutors.newDirectExecutorService();
         AAIServiceTree aaiServiceTree = new AAIServiceTree(
                 aaiClientMock,
-                new AAITreeNodeBuilder(aaiClientMock),
+                new AAITreeNodeBuilder(aaiClientMock, new Logging()),
                 new AAITreeConverter(),
                 null,
                 null,
index c2a3f5d..2c954b2 100644 (file)
 
 package org.onap.vid.services;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
+import static java.util.Comparator.comparing;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
+import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS;
+import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -28,7 +41,14 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.MoreExecutors;
-
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import org.apache.commons.lang3.tuple.Pair;
 import org.jetbrains.annotations.NotNull;
 import org.mockito.Mock;
@@ -41,37 +61,15 @@ import org.onap.vid.exceptions.GenericUncheckedException;
 import org.onap.vid.model.aaiTree.AAITreeNode;
 import org.onap.vid.model.aaiTree.NodeType;
 import org.onap.vid.mso.model.CloudConfiguration;
+import org.onap.vid.testUtils.TestUtils;
+import org.onap.vid.utils.Logging;
 import org.onap.vid.utils.Tree;
 import org.onap.vid.utils.Unchecked;
-import org.onap.vid.testUtils.TestUtils;
 import org.springframework.http.HttpMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentSkipListSet;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import static java.util.Comparator.comparing;
-import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
-import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
-import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.empty;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.when;
-import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS;
-import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 public class AAITreeNodeBuilderTest {
 
     private AAITreeNodeBuilder aaiTreeNodeBuilder;
@@ -80,13 +78,14 @@ public class AAITreeNodeBuilderTest {
     private AaiClientInterface aaiClientMock;
 
     private ExecutorService executorService;
+    private Logging logging = new Logging();
 
     private static final ObjectMapper mapper = new ObjectMapper();
 
     @BeforeClass
     public void initMocks() {
         MockitoAnnotations.initMocks(this);
-        aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock);
+        aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock, logging);
         executorService = MoreExecutors.newDirectExecutorService();
     }
 
index 9df99fa..d3b2a48 100644 (file)
@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.function.Function;
 import javax.ws.rs.core.Response;
 import org.apache.http.HttpStatus;
 import org.jetbrains.annotations.NotNull;
@@ -88,6 +89,7 @@ import org.onap.vid.model.aaiTree.AAITreeNode;
 import org.onap.vid.model.aaiTree.RelatedVnf;
 import org.onap.vid.model.aaiTree.ServiceInstance;
 import org.onap.vid.roles.RoleValidator;
+import org.onap.vid.utils.Logging;
 import org.springframework.http.HttpMethod;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -131,6 +133,8 @@ public class AaiServiceImplTest {
     @Mock
     private AaiResponseTranslator aaiResponseTranslator;
     @Mock
+    private Logging logging;
+    @Mock
     private AAIServiceTree aaiServiceTree;
     @Spy
     private ExecutorService executorService = Executors.newFixedThreadPool(1);
@@ -504,6 +508,7 @@ public class AaiServiceImplTest {
         when(aaiServiceTree.buildAAITree(anyString(), isNull(), eq(HttpMethod.GET), any(), anyBoolean()))
             .thenReturn(Collections.singletonList(testedTree));
         when(aaiClient.getCloudRegionAndTenantByVnfId(anyString())).thenReturn(regionsAndTenants);
+        when(logging.withMDC(any(), any(Function.class))).thenAnswer(invocation -> invocation.getArgument(1));
 
         List<RelatedVnf> actualGroupMembers = aaiService.searchGroupMembers(GLOBAL_CUSTOMER_ID, SERVICE_TYPE,
             INVARIANT_ID, GROUP_TYPE_FAILING, GROUP_ROLE_FAILING);
diff --git a/vid-app-common/src/test/java/org/onap/vid/utils/LoggingTest.java b/vid-app-common/src/test/java/org/onap/vid/utils/LoggingTest.java
deleted file mode 100644 (file)
index 87fe363..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * VID
- * ================================================================================
- * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.vid.utils;
-
-import com.att.eelf.configuration.EELFLogger;
-import org.junit.Test;
-
-public class LoggingTest {
-
-    @Test
-    public void testGetMethodName() throws Exception {
-        String result;
-
-        // default test
-        result = Logging.getMethodName();
-    }
-
-    @Test
-    public void testGetMethodCallerName() throws Exception {
-        String result;
-
-        // default test
-        result = Logging.getMethodCallerName();
-    }
-
-    @Test
-    public void testGetRequestsLogger() throws Exception {
-        String serverName = "";
-        EELFLogger result;
-
-        // default test
-        result = Logging.getRequestsLogger(serverName);
-    }
-
-
-}
index 6cbb14a..c2a1f28 100644 (file)
 package org.onap.vid.utils;
 
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.sameInstance;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasEntry;
 import static org.hamcrest.Matchers.matchesPattern;
 import static org.mockito.ArgumentMatchers.contains;
 import static org.mockito.Mockito.mock;
@@ -33,12 +37,15 @@ import com.att.eelf.configuration.EELFLogger;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.databind.JsonMappingException;
+import com.google.common.collect.ImmutableMap;
 import io.joshworks.restclient.http.HttpResponse;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
+import java.util.concurrent.Callable;
+import java.util.function.Function;
 import javax.crypto.BadPaddingException;
 import javax.net.ssl.SSLHandshakeException;
 import javax.ws.rs.ProcessingException;
@@ -46,6 +53,7 @@ import org.apache.commons.io.IOUtils;
 import org.mockito.ArgumentCaptor;
 import org.onap.vid.exceptions.GenericUncheckedException;
 import org.onap.vid.testUtils.TestUtils;
+import org.slf4j.MDC;
 import org.springframework.http.HttpMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
@@ -196,6 +204,71 @@ public class LoggingUtilsTest {
         assertThat(Logging.exceptionToDescription(exceptionToDescribe), matchesRegEx(expectedButDotsEscaped));
     }
 
+    @Test
+    public void testWithMDCInternal_whenGivenProvider_functionShouldBeExtractedWithMdc() {
+        Object myAnything = new Object();
+
+        Object result = logginService.withMDCInternal(ImmutableMap.of("my key", "my value"),
+            () -> {
+                assertThat("MDC values should be installed when extracting the supplier",
+                    MDC.getCopyOfContextMap(), hasEntry("my key", "my value"));
+                return myAnything;
+            }
+        );
+
+        assertThat("withMDCInternal should extract my function", result, is(sameInstance(myAnything)));
+        assertThat("MDC values should be removed", MDC.getCopyOfContextMap(), not(hasEntry("k", "v")));
+    }
+
+    @Test
+    public void testWithMDC_whenGivenFunction_functionShouldBeEncapsulated() {
+        // Given
+        String[] stringsArray = {"before"};
+
+        Function<String, Integer> myFunction = s -> {
+            assertThat("MDC values should be installed when inside myFunction",
+                MDC.getCopyOfContextMap(), hasEntry("my key", "my value"));
+            stringsArray[0] = s;
+            return 42;
+        };
+
+        // When
+        Function<String, Integer> functionWithMDC =
+            logginService.withMDC(ImmutableMap.of("my key", "my value"), myFunction);
+
+
+        assertThat("invocation of function must not happen yet", stringsArray[0], is("before"));
+
+        Integer result = functionWithMDC.apply("after");
+
+        assertThat("invocation of my function should have been deferred", stringsArray[0], is("after"));
+        assertThat("apply should return function's value", result, is(42));
+    }
+
+    @Test
+    public void testWithMDC_whenGivenCallable_callableShouldBeEncapsulated() throws Exception {
+        // Given
+        String[] stringsArray = {"before"};
+
+        Callable<Integer> myCallable = () -> {
+            assertThat("MDC values should be installed when inside myCallable",
+                MDC.getCopyOfContextMap(), hasEntry("my key", "my value"));
+            stringsArray[0] = "after";
+            return 42;
+        };
+
+        // When
+        Callable<Integer> callableWithMDC = logginService.withMDC(ImmutableMap.of("my key", "my value"), myCallable);
+
+
+        assertThat("invocation of callable must not happen yet", stringsArray[0], is("before"));
+
+        Integer result = callableWithMDC.call();
+
+        assertThat("invocation of my callable should have been deferred", stringsArray[0], is("after"));
+        assertThat("apply should return function's value", result, is(42));
+    }
+
     private static String escapeBrackets(String in) {
         return in.replaceAll("[\\(\\[\\{\\)]", "\\\\$0");
     }
index 66bde72..5e13105 100644 (file)
@@ -1,8 +1,34 @@
 package org.onap.vid.api;
 
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static java.util.Collections.emptyList;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toMap;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.hasSize;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection;
+
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.Uninterruptibles;
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
@@ -38,33 +64,6 @@ import vid.automation.test.model.ServiceAction;
 import vid.automation.test.services.AsyncJobsService;
 import vid.automation.test.services.SimulatorApi;
 
-import java.time.Instant;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import static java.lang.Boolean.FALSE;
-import static java.lang.Boolean.TRUE;
-import static java.util.Collections.emptyList;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toMap;
-import static org.hamcrest.CoreMatchers.hasItem;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.hasSize;
-import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertTrue;
-import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection;
-
 public class AsyncInstantiationBase extends BaseMsoApiTest {
 
     public static final String CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF = "asyncInstantiation/vidRequestCreateALaCarteWithVnf.json";
@@ -507,7 +506,7 @@ public class AsyncInstantiationBase extends BaseMsoApiTest {
                     .filter(serviceInfo -> serviceInfo.jobId.equals(jobId))
                     .findFirst().orElse(null);
             Assert.assertNotNull(serviceInfoFromDB);
-            Assert.assertEquals(serviceInfoDataReflected(expectedServiceInfo), serviceInfoDataReflected(serviceInfoFromDB));
+            Assert.assertEquals(serviceInfoDataReflected(serviceInfoFromDB), serviceInfoDataReflected(expectedServiceInfo));
             assertTrue("actual service instance doesn't contain template service name:" + expectedServiceInfo.serviceInstanceName,
                     serviceInfoFromDB.serviceInstanceName.contains(expectedServiceInfo.serviceInstanceName));
 
index f8bdc97..5d07a4e 100644 (file)
@@ -39,6 +39,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import org.testng.util.RetryAnalyzerCount;
 import vid.automation.test.services.SimulatorApi;
+import vid.automation.test.services.SimulatorApi.RegistrationStrategy;
 
 public class ServiceTreeApiTest extends BaseApiTest {
 
@@ -179,7 +180,12 @@ public class ServiceTreeApiTest extends BaseApiTest {
                 .replace("VNF4_INSTANCE_TYPE", vnfPreset4.getInstanceType());
 
         assertJsonEquals(response, expected);
+
+        SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), RegistrationStrategy.APPEND);
         LoggerFormatTest.assertHeadersAndMetricLogs(restTemplate, uri, echoedRequestId(responseEntity),  "/network/generic-vnfs/generic-vnf/", 5);
+        // org.onap.vid.aai.AaiClient.getCloudRegionAndTenantByVnfId for presets PresetAAIGetCloudRegionFromVnf is
+        // PUTing to AAI, so path is just /aai/v../query
+        LoggerFormatTest.assertHeadersAndMetricLogs(restTemplate, uri, echoedRequestId(responseEntity),  "/query", 4);
     }
 
     @Test