Пример #1
0
        private async Task ValidateUserAgentStringAsync(
            CosmosClientOptions cosmosClientOptions,
            string userAgentContentToValidate,
            string databaseName,
            string containerName)
        {
            HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper()
            {
                RequestCallBack = (request, cancellationToken) =>
                {
                    string userAgent = request.Headers.UserAgent.ToString();
                    Assert.IsTrue(userAgent.Contains(userAgentContentToValidate));
                    return(null);
                }
            };

            cosmosClientOptions.HttpClientFactory = () => new HttpClient(httpClientHandlerHelper);

            using (CosmosClient client = TestCommon.CreateCosmosClient(cosmosClientOptions))
            {
                Cosmos.Database db = await client.CreateDatabaseIfNotExistsAsync(databaseName);

                await db.CreateContainerIfNotExistsAsync(containerName, "/pk");
            }
        }
        public async Task CreateAndInitializeWithCosmosClientBuilderTest()
        {
            int httpCallsMade = 0;
            HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper
            {
                RequestCallBack = (request, cancellationToken) =>
                {
                    httpCallsMade++;
                    return(null);
                }
            };

            (string endpoint, string authKey) = TestCommon.GetAccountInfo();
            List <(string, string)> containers = new List <(string, string)>
            {
                ("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer")
            };

            CosmosClientBuilder builder      = new CosmosClientBuilder(endpoint, authKey).WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper));
            CosmosClient        cosmosClient = await builder.BuildAndInitializeAsync(containers);

            Assert.IsNotNull(cosmosClient);
            int httpCallsMadeAfterCreation = httpCallsMade;

            ContainerInternal           container    = (ContainerInternal)cosmosClient.GetContainer("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer");
            ItemResponse <ToDoActivity> readResponse = await container.ReadItemAsync <ToDoActivity>("1", new Cosmos.PartitionKey("Status1"));

            Assert.AreEqual(httpCallsMade, httpCallsMadeAfterCreation);
            cosmosClient.Dispose();
        }
        public async Task GatewaySameSessionTokenTest()
        {
            string createSessionToken = null;

            GatewaySessionTokenTests.HttpClientHandlerHelper httpClientHandler = new HttpClientHandlerHelper
            {
                ResponseCallBack = (result) =>
                {
                    HttpResponseMessage response = result.Result;
                    if (response.StatusCode != HttpStatusCode.Created)
                    {
                        return(response);
                    }

                    response.Headers.TryGetValues("x-ms-session-token", out IEnumerable <string> sessionTokens);
                    foreach (string singleToken in sessionTokens)
                    {
                        createSessionToken = singleToken;
                        break;
                    }
                    return(response);
                }
            };

            using (CosmosClient client = TestCommon.CreateCosmosClient(builder => builder
                                                                       .WithConnectionModeGateway()
                                                                       .WithConsistencyLevel(Cosmos.ConsistencyLevel.Session)
                                                                       .WithHttpClientFactory(() => new HttpClient(httpClientHandler))))
            {
                Container container = client.GetContainer(this.database.Id, this.Container.Id);

                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity("Status1001", "1001");
                ItemResponse <ToDoActivity> itemResponse = await container.CreateItemAsync(item);

                // Read back the created Item and check if the session token is identical.
                string docLink = "dbs/" + this.database.Id + "/colls/" + this.Container.Id + "/docs/1001";
                Documents.Collections.INameValueCollection headers = new StoreRequestNameValueCollection();
                headers.Set(HttpConstants.HttpHeaders.PartitionKey, "[\"Status1001\"]");

                DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, ResourceType.Document, docLink, AuthorizationTokenType.PrimaryMasterKey, headers);
                await GatewayStoreModel.ApplySessionTokenAsync(request,
                                                               Cosmos.ConsistencyLevel.Session,
                                                               client.DocumentClient.sessionContainer,
                                                               await client.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton),
                                                               await client.DocumentClient.GetCollectionCacheAsync(NoOpTrace.Singleton));

                string readSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken];
                Assert.AreEqual(readSessionToken, createSessionToken);
            }
        }
Пример #4
0
        public void TestInitialize()
        {
            this.actualInfo = new List <ClientTelemetryProperties>();

            Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1");
            Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, telemetryEndpointUrl);

            HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper
            {
                RequestCallBack = (request, cancellation) =>
                {
                    if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri))
                    {
                        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                        string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                        lock (this.actualInfo)
                        {
                            this.actualInfo.Add(JsonConvert.DeserializeObject <ClientTelemetryProperties>(jsonObject));
                        }

                        return(Task.FromResult(result));
                    }
                    else if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetVmMetadataUrl().AbsoluteUri))
                    {
                        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                        object jsonObject = JsonConvert.DeserializeObject("{\"compute\":{\"azEnvironment\":\"AzurePublicCloud\",\"customData\":\"\",\"isHostCompatibilityLayerVm\":\"false\",\"licenseType\":\"\",\"location\":\"eastus\",\"name\":\"sourabh-testing\",\"offer\":\"UbuntuServer\",\"osProfile\":{\"adminUsername\":\"azureuser\",\"computerName\":\"sourabh-testing\"},\"osType\":\"Linux\",\"placementGroupId\":\"\",\"plan\":{\"name\":\"\",\"product\":\"\",\"publisher\":\"\"},\"platformFaultDomain\":\"0\",\"platformUpdateDomain\":\"0\",\"provider\":\"Microsoft.Compute\",\"publicKeys\":[{\"keyData\":\"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5uCeOAm3ehmhI+2PbMoMl17Eo\r\nqfHKCycSaBJsv9qxlmBOuFheSJc1XknJleXUSsuTO016/d1PyWpevnqOZNRksWoa\r\nJvQ23sDTxcK+X2OP3QlCUeX4cMjPXqlL8z1UYzU4Bx3fFvf8fs67G3N72sxWBw5P\r\nZyuXyhBm0NCe/2NYMKgEDT4ma8XszO0ikbhoPKbMbgHAQk/ktWQHNcqYOPQKEWqp\r\nEK1R0rjS2nmtovfScP/ZGXcvOpJ1/NDBo4dh1K+OxOGM/4PSH/F448J5Zy4eAyEk\r\nscys+IpeIOTOlRUy/703SNIX0LEWlnYqbyL9c1ypcYLQqF76fKkDfzzFI/OWVlGw\r\nhj/S9uP8iMsR+fhGIbn6MAa7O4DWPWLuedSp7KDYyjY09gqNJsfuaAJN4LiC6bPy\r\nhknm0PVLK3ux7EUOt+cZrHCdIFWbdOtxiPNIl1tkv9kV5aE5Aj2gJm4MeB9uXYhS\r\nOuksboBc0wyUGrl9+XZJ1+NlZOf7IjVi86CieK8= generated-by-azure\r\n\",\"path\":\"/home/azureuser/.ssh/authorized_keys\"}],\"publisher\":\"Canonical\",\"resourceGroupName\":\"sourabh-telemetry-sdk\",\"resourceId\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/virtualMachines/sourabh-testing\",\"securityProfile\":{\"secureBootEnabled\":\"false\",\"virtualTpmEnabled\":\"false\"},\"sku\":\"18.04-LTS\",\"storageProfile\":{\"dataDisks\":[],\"imageReference\":{\"id\":\"\",\"offer\":\"UbuntuServer\",\"publisher\":\"Canonical\",\"sku\":\"18.04-LTS\",\"version\":\"latest\"},\"osDisk\":{\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\",\"diffDiskSettings\":{\"option\":\"\"},\"diskSizeGB\":\"30\",\"encryptionSettings\":{\"enabled\":\"false\"},\"image\":{\"uri\":\"\"},\"managedDisk\":{\"id\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/disks/sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"storageAccountType\":\"Premium_LRS\"},\"name\":\"sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"osType\":\"Linux\",\"vhd\":{\"uri\":\"\"},\"writeAcceleratorEnabled\":\"false\"}},\"subscriptionId\":\"8fba6d4f-7c37-4d13-9063-fd58ad2b86e2\",\"tags\":\"azsecpack:nonprod;platformsettings.host_environment.service.platform_optedin_for_rootcerts:true\",\"tagsList\":[{\"name\":\"azsecpack\",\"value\":\"nonprod\"},{\"name\":\"platformsettings.host_environment.service.platform_optedin_for_rootcerts\",\"value\":\"true\"}],\"version\":\"18.04.202103250\",\"vmId\":\"d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd\",\"vmScaleSetName\":\"\",\"vmSize\":\"Standard_D2s_v3\",\"zone\":\"1\"},\"network\":{\"interface\":[{\"ipv4\":{\"ipAddress\":[{\"privateIpAddress\":\"10.0.7.5\",\"publicIpAddress\":\"\"}],\"subnet\":[{\"address\":\"10.0.7.0\",\"prefix\":\"24\"}]},\"ipv6\":{\"ipAddress\":[]},\"macAddress\":\"000D3A8F8BA0\"}]}}");
                        string payload    = JsonConvert.SerializeObject(jsonObject);
                        result.Content = new StringContent(payload, Encoding.UTF8, "application/json");

                        return(Task.FromResult(result));
                    }
                    return(null);
                }
            };

            List <string> preferredRegionList = new List <string>
            {
                "region1",
                "region2"
            };

            this.cosmosClientBuilder = TestCommon.GetDefaultConfiguration()
                                       .WithApplicationPreferredRegions(preferredRegionList)
                                       .WithTelemetryEnabled()
                                       .WithHttpClientFactory(() => new HttpClient(httpHandler));
        }
Пример #5
0
        private async Task <Container> CreateContainer(bool isLocalQuorumConsistency)
        {
            HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper
            {
                ResponseIntercepter = async(response) =>
                {
                    string responseString = await response.Content.ReadAsStringAsync();

                    if (responseString.Contains("databaseAccountEndpoint"))
                    {
                        AccountProperties accountProperties =
                            JsonConvert.DeserializeObject <AccountProperties>(responseString);
                        accountProperties.Consistency.DefaultConsistencyLevel = Cosmos.ConsistencyLevel.Eventual;
                        response.Content = new StringContent(JsonConvert.SerializeObject(accountProperties), Encoding.UTF8, "application/json");
                    }
                    return(response);
                }
            };

            RequestHandlerHelper handlerHelper = new RequestHandlerHelper
            {
                UpdateRequestMessage = (request) =>
                {
                    if (request.OperationType == Documents.OperationType.Read)
                    {
                        Assert.AreEqual(Cosmos.ConsistencyLevel.Strong.ToString(), request.Headers[Documents.HttpConstants.HttpHeaders.ConsistencyLevel]);
                    }
                }
            };

            this.cosmosClient = TestCommon.CreateCosmosClient(x =>
            {
                CosmosClientBuilder builder = x.AddCustomHandlers(handlerHelper)
                                              .WithHttpClientFactory(() => new HttpClient(httpHandler));
                if (isLocalQuorumConsistency)
                {
                    builder.AllowUpgradeConsistencyToLocalQuorum();
                }
            });

            Database database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(),
                                                                            cancellationToken : new CancellationTokenSource().Token);

            return(await database.CreateContainerAsync(id : Guid.NewGuid().ToString(),
                                                       partitionKeyPath : "/pk"));
        }
Пример #6
0
        public async Task QueryPlanRetryTimeoutTestAsync()
        {
            HttpClientHandlerHelper httpClientHandler = new HttpClientHandlerHelper();

            using (CosmosClient client = TestCommon.CreateCosmosClient(builder => builder
                                                                       .WithConnectionModeGateway()
                                                                       .WithHttpClientFactory(() => new HttpClient(httpClientHandler))))
            {
                Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString());

                ContainerInternal container = (ContainerInternal)await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk");

                Container gatewayQueryPlanContainer = new ContainerInlineCore(
                    client.ClientContext,
                    (DatabaseInternal)database,
                    container.Id,
                    new DisableServiceInterop(client.ClientContext, container));

                bool isQueryRequestFound = false;
                httpClientHandler.RequestCallBack = (request, cancellationToken) =>
                {
                    if (request.Headers.TryGetValues(HttpConstants.HttpHeaders.IsQueryPlanRequest, out IEnumerable <string> isQueryPlan) &&
                        isQueryPlan.FirstOrDefault() == bool.TrueString)
                    {
                        Assert.IsFalse(isQueryRequestFound, "Should only call get query plan once.");
                        Assert.AreNotEqual(cancellationToken, default);
                        isQueryRequestFound = true;
                    }
                };

                using FeedIterator <JObject> iterator = gatewayQueryPlanContainer.GetItemQueryIterator <JObject>("select * From T order by T.status");
                FeedResponse <JObject> response       = await iterator.ReadNextAsync();

                Assert.IsTrue(isQueryRequestFound, "Query plan call back was not called.");

                string  diagnostics       = response.Diagnostics.ToString();
                JObject parsedDiagnostics = JObject.Parse(diagnostics);
                JToken  contextList       = parsedDiagnostics["Context"];

                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "CreateQueryPipeline"));
                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "Microsoft.Azure.Cosmos.GatewayStoreModel"));
                Assert.IsNotNull(contextList.First(x => x["Id"]?.ToString() == "SendHttpHelperAsync:" + nameof(HttpTimeoutPolicyControlPlaneRetriableHotPath)));
                await database.DeleteStreamAsync();
            }
        }
Пример #7
0
        public void TestInitialize()
        {
            this.actualInfo = new List <ClientTelemetryProperties>();

            HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper
            {
                RequestCallBack = (request, cancellation) =>
                {
                    if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri))
                    {
                        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                        string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                        lock (this.actualInfo)
                        {
                            this.actualInfo.Add(JsonConvert.DeserializeObject <ClientTelemetryProperties>(jsonObject));
                        }

                        return(Task.FromResult(result));
                    }
                    else if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetVmMetadataUrl().AbsoluteUri))
                    {
                        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                        string payload = JsonConvert.SerializeObject(ClientTelemetryTests.jsonObject);
                        result.Content = new StringContent(payload, Encoding.UTF8, "application/json");

                        return(Task.FromResult(result));
                    }
                    return(null);
                }
            };

            this.preferredRegionList = new List <string>
            {
                "region1",
                "region2"
            };

            this.cosmosClientBuilder = TestCommon.GetDefaultConfiguration()
                                       .WithApplicationPreferredRegions(this.preferredRegionList)
                                       .WithHttpClientFactory(() => new HttpClient(httpHandler));
        }
Пример #8
0
        public async Task ValidateExceptionOnInitTask()
        {
            int httpCallCount = 0;
            HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper()
            {
                RequestCallBack = (request, cancellToken) =>
                {
                    Interlocked.Increment(ref httpCallCount);
                    return(null);
                }
            };

            using CosmosClient cosmosClient = new CosmosClient(
                      accountEndpoint: "https://localhost:8081",
                      authKeyOrResourceToken: Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())),
                      clientOptions: new CosmosClientOptions()
            {
                HttpClientFactory = () => new HttpClient(httpClientHandlerHelper),
            });

            CosmosException cosmosException1 = null;

            try
            {
                await cosmosClient.GetContainer("db", "c").ReadItemAsync <JObject>("Random", new Cosmos.PartitionKey("DoesNotExist"));
            }
            catch (CosmosException ex)
            {
                cosmosException1 = ex;
                Assert.IsTrue(httpCallCount > 0);
            }

            httpCallCount = 0;
            try
            {
                await cosmosClient.GetContainer("db", "c").ReadItemAsync <JObject>("Random2", new Cosmos.PartitionKey("DoesNotExist2"));
            }
            catch (CosmosException ex)
            {
                Assert.IsFalse(object.ReferenceEquals(ex, cosmosException1));
                Assert.IsTrue(httpCallCount > 0);
            }
        }
Пример #9
0
        public async Task TestHeadersPassedinByClient()
        {
            int httpCallCount = 0;
            IEnumerable <string>    sdkSupportedCapabilities = null;
            HttpClientHandlerHelper httpClientHandlerHelper  = new HttpClientHandlerHelper()
            {
                RequestCallBack = (request, cancellToken) =>
                {
                    Interlocked.Increment(ref httpCallCount);
                    request.Headers.TryGetValues(HttpConstants.HttpHeaders.SDKSupportedCapabilities, out sdkSupportedCapabilities);
                    return(null);
                }
            };

            using CosmosClient cosmosClient = new CosmosClient(
                      accountEndpoint: "https://localhost:8081",
                      authKeyOrResourceToken: Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())),
                      clientOptions: new CosmosClientOptions()
            {
                HttpClientFactory = () => new HttpClient(httpClientHandlerHelper),
            });

            CosmosException cosmosException1 = null;

            try
            {
                await cosmosClient.GetContainer("db", "c").ReadItemAsync <JObject>("Random", new Cosmos.PartitionKey("DoesNotExist"));
            }
            catch (CosmosException ex)
            {
                cosmosException1 = ex;
                Assert.IsTrue(httpCallCount > 0);
            }

            Assert.IsNotNull(sdkSupportedCapabilities);
            Assert.AreEqual(1, sdkSupportedCapabilities.Count());

            string sdkSupportedCapability = sdkSupportedCapabilities.Single();
            ulong  capability             = ulong.Parse(sdkSupportedCapability);

            Assert.AreEqual((ulong)SDKSupportedCapabilities.PartitionMerge, capability & (ulong)SDKSupportedCapabilities.PartitionMerge, $" received header value as {sdkSupportedCapability}");
        }
Пример #10
0
        public async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode)
        {
            HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper();
            HttpClient httpClient = new HttpClient(httpHandler);

            httpHandler.RequestCallBack = (request, cancellation) =>
            {
                if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri))
                {
                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                    string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                    lock (this.actualInfo)
                    {
                        this.actualInfo.Add(JsonConvert.DeserializeObject <ClientTelemetryProperties>(jsonObject));
                    }

                    return(Task.FromResult(result));
                }
                else if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetVmMetadataUrl().AbsoluteUri))
                {
                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                    string payload = JsonConvert.SerializeObject(ClientTelemetryTests.jsonObject);
                    result.Content = new StringContent(payload, Encoding.UTF8, "application/json");

                    return(Task.FromResult(result));
                }
                else if (request.Method == HttpMethod.Get && request.RequestUri.AbsolutePath == "//addresses/")
                {
                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Forbidden);

                    // Add a substatus code that is not part of the enum.
                    // This ensures that if the backend adds a enum the status code is not lost.
                    result.Headers.Add(WFConstants.BackendHeaders.SubStatus, 999999.ToString(CultureInfo.InvariantCulture));

                    string payload = JsonConvert.SerializeObject(new Error()
                    {
                        Message = "test message"
                    });
                    result.Content = new StringContent(payload, Encoding.UTF8, "application/json");

                    return(Task.FromResult(result));
                }

                return(null);
            };

            // Replacing originally initialized cosmos Builder with this one with new handler
            this.cosmosClientBuilder = this.cosmosClientBuilder
                                       .WithHttpClientFactory(() => new HttpClient(httpHandler));

            Container container = await this.CreateClientAndContainer(mode);

            try
            {
                ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue");
                ItemResponse <ToDoActivity> createResponse = await container.CreateItemAsync <ToDoActivity>(testItem);

                Assert.Fail("Request should throw exception.");
            }
            catch (CosmosException ce) when(ce.StatusCode == HttpStatusCode.Forbidden)
            {
                Assert.AreEqual(999999, ce.SubStatusCode);
            }

            IDictionary <string, long> expectedRecordCountInOperation = new Dictionary <string, long>
            {
                { Documents.OperationType.Create.ToString(), 1 }
            };

            await this.WaitAndAssert(expectedOperationCount : 2,
                                     expectedOperationRecordCountMap : expectedRecordCountInOperation,
                                     expectedSubstatuscode : "999999");
        }
Пример #11
0
        public async Task InitTaskThreadSafe()
        {
            int  httpCallCount     = 0;
            int  metadataCallCount = 0;
            bool delayCallBack     = true;

            var isInitializedField = typeof(VmMetadataApiHandler).GetField("isInitialized",
                                                                           BindingFlags.Static |
                                                                           BindingFlags.NonPublic);

            isInitializedField.SetValue(null, false);

            var azMetadataField = typeof(VmMetadataApiHandler).GetField("azMetadata",
                                                                        BindingFlags.Static |
                                                                        BindingFlags.NonPublic);

            azMetadataField.SetValue(null, null);

            HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper()
            {
                RequestCallBack = async(request, cancellToken) =>
                {
                    if (request.RequestUri.AbsoluteUri == VmMetadataApiHandler.vmMetadataEndpointUrl.AbsoluteUri)
                    {
                        Interlocked.Increment(ref metadataCallCount);
                    }
                    else
                    {
                        Interlocked.Increment(ref httpCallCount);
                    }

                    while (delayCallBack)
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(100));
                    }

                    return(null);
                }
            };

            using CosmosClient cosmosClient = new CosmosClient(
                      accountEndpoint: "https://localhost:8081",
                      authKeyOrResourceToken: Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())),
                      clientOptions: new CosmosClientOptions()
            {
                HttpClientFactory = () => new HttpClient(httpClientHandlerHelper),
            });

            List <Task> tasks = new List <Task>();

            Container container = cosmosClient.GetContainer("db", "c");

            for (int loop = 0; loop < 3; loop++)
            {
                for (int i = 0; i < 10; i++)
                {
                    tasks.Add(this.ReadNotFound(container));
                }

                ValueStopwatch sw = ValueStopwatch.StartNew();
                while (this.TaskStartedCount < 10 && sw.Elapsed.TotalSeconds < 2)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(50));
                }

                Assert.AreEqual(10, this.TaskStartedCount, "Tasks did not start");
                delayCallBack = false;

                await Task.WhenAll(tasks);

                Assert.AreEqual(1, metadataCallCount, "Only one call for VM Metadata call with be made");
                Assert.AreEqual(1, httpCallCount, "Only the first task should do the http call. All other should wait on the first task");

                // Reset counters and retry the client to verify a new http call is done for new requests
                tasks.Clear();
                delayCallBack         = true;
                this.TaskStartedCount = 0;
                httpCallCount         = 0;
            }
        }