From 2c3513364e2f2cab58d0526d3e28c1c95b396477 Mon Sep 17 00:00:00 2001 From: Jake Willey Date: Mon, 8 Feb 2021 07:29:55 -0800 Subject: [PATCH 1/2] Fixes client option ConsistentPrefix mapping --- .../src/CosmosClientOptions.cs | 16 +----- .../CosmosItemTests.cs | 27 ++++++++++ .../CosmosClientOptionsUnitTests.cs | 49 ++++++++++++++++++- .../HandlerTests.cs | 43 ++++++++-------- 4 files changed, 99 insertions(+), 36 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 05855d970e..7d4472fff2 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -715,21 +715,7 @@ internal ConnectionPolicy GetConnectionPolicy() return null; } - switch (this.ConsistencyLevel.Value) - { - case Cosmos.ConsistencyLevel.BoundedStaleness: - return Documents.ConsistencyLevel.BoundedStaleness; - case Cosmos.ConsistencyLevel.ConsistentPrefix: - return Documents.ConsistencyLevel.BoundedStaleness; - case Cosmos.ConsistencyLevel.Eventual: - return Documents.ConsistencyLevel.Eventual; - case Cosmos.ConsistencyLevel.Session: - return Documents.ConsistencyLevel.Session; - case Cosmos.ConsistencyLevel.Strong: - return Documents.ConsistencyLevel.Strong; - default: - throw new ArgumentException($"Unsupported ConsistencyLevel {this.ConsistencyLevel.Value}"); - } + return (Documents.ConsistencyLevel)this.ConsistencyLevel.Value; } internal static string GetAccountEndpoint(string connectionString) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index 9c298e0a1c..c26c3b326b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -149,6 +149,33 @@ public async Task CreateDropItemTest() Assert.IsTrue(response.Diagnostics.GetClientElapsedTime() > TimeSpan.Zero); } + [TestMethod] + public async Task ClientConsistencyTestAsync() + { + List cosmosLevels = Enum.GetValues(typeof(Cosmos.ConsistencyLevel)).Cast().ToList(); + + foreach(Cosmos.ConsistencyLevel consistencyLevel in cosmosLevels) + { + RequestHandlerHelper handlerHelper = new RequestHandlerHelper(); + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient(x => + x.WithConsistencyLevel(consistencyLevel).AddCustomHandlers(handlerHelper)); + Container consistencyContainer = cosmosClient.GetContainer(this.database.Id, this.Container.Id); + + int requestCount = 0; + handlerHelper.UpdateRequestMessage = (request) => + { + Assert.AreEqual(consistencyLevel.ToString(), request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]); + requestCount++; + }; + + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); + ItemResponse response = await consistencyContainer.CreateItemAsync(item: testItem); + response = await consistencyContainer.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.pk)); + + Assert.AreEqual(2, requestCount); + } + } + [TestMethod] public async Task NegativeCreateItemTest() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 3c2d071c88..14aca88f80 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; + using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -50,6 +51,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() int maxTcpConnectionsPerEndpoint = 65535; Cosmos.PortReuseMode portReuseMode = Cosmos.PortReuseMode.PrivatePortPool; IWebProxy webProxy = new TestWebProxy(); + Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder( accountEndpoint: endpoint, @@ -77,6 +79,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsFalse(clientOptions.LimitToEndpoint); Assert.IsFalse(clientOptions.EnableTcpConnectionEndpointRediscovery); Assert.IsNull(clientOptions.HttpClientFactory); + Assert.AreNotEqual(consistencyLevel, clientOptions.ConsistencyLevel); //Verify GetConnectionPolicy returns the correct values for default ConnectionPolicy policy = clientOptions.GetConnectionPolicy(); @@ -91,6 +94,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(policy.EnableEndpointDiscovery); Assert.IsFalse(policy.EnableTcpConnectionEndpointRediscovery); Assert.IsNull(policy.HttpClientFactory); + Assert.AreNotEqual(Cosmos.ConsistencyLevel.Session, clientOptions.ConsistencyLevel); cosmosClientBuilder.WithApplicationRegion(region) .WithConnectionModeGateway(maxConnections, webProxy) @@ -100,7 +104,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() .WithApiType(apiType) .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithBulkExecution(true) - .WithSerializerOptions(cosmosSerializerOptions); + .WithSerializerOptions(cosmosSerializerOptions) + .WithConsistencyLevel(consistencyLevel); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); clientOptions = cosmosClient.ClientOptions; @@ -121,6 +126,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(cosmosSerializerOptions.Indented, clientOptions.SerializerOptions.Indented); Assert.IsTrue(object.ReferenceEquals(webProxy, clientOptions.WebProxy)); Assert.IsTrue(clientOptions.AllowBulkExecution); + Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); //Verify GetConnectionPolicy returns the correct values policy = clientOptions.GetConnectionPolicy(); @@ -133,6 +139,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(policy.UseMultipleWriteLocations); Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, policy.RetryOptions.MaxRetryAttemptsOnThrottledRequests); Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds); + Assert.AreEqual(ConsistencyLevel.Eventual, clientOptions.GetDocumentsConsistencyLevel()); IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; //Verify Direct Mode settings @@ -170,6 +177,32 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); } + [TestMethod] + public void VerifyConsisentencyLevels() + { + List cosmosLevels = Enum.GetValues(typeof(Cosmos.ConsistencyLevel)).Cast().ToList(); + List documentLevels = Enum.GetValues(typeof(Documents.ConsistencyLevel)).Cast().ToList(); + CollectionAssert.AreEqual(cosmosLevels, documentLevels, new EnumComparer(), "Document consistency level is different from cosmos consistency level"); + + foreach (Cosmos.ConsistencyLevel consistencyLevel in cosmosLevels) + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConsistencyLevel = consistencyLevel + }; + + Assert.AreEqual((int)consistencyLevel, (int)cosmosClientOptions.GetDocumentsConsistencyLevel()); + Assert.AreEqual(consistencyLevel.ToString(), cosmosClientOptions.GetDocumentsConsistencyLevel().ToString()); + } + + CosmosClientOptions cosmosClientOptionsNull = new CosmosClientOptions() + { + ConsistencyLevel = null + }; + + Assert.IsNull(cosmosClientOptionsNull.GetDocumentsConsistencyLevel()); + } + [TestMethod] public void VerifyPortReuseModeIsSyncedWithDirect() { @@ -442,5 +475,19 @@ public bool IsBypassed(Uri host) return false; } } + + private class EnumComparer : IComparer + { + public int Compare(object x, object y) + { + if ((int)x == (int)y && + string.Equals(x.ToString(), y.ToString())) + { + return 0; + } + + return 1; + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs index 18eeb1e58b..864d963ab8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs @@ -222,30 +222,33 @@ public async Task QueryRequestOptionsSessionToken() [TestMethod] public async Task ConsistencyLevelClient() { - Cosmos.ConsistencyLevel clientLevel = Cosmos.ConsistencyLevel.Eventual; - using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( - accountConsistencyLevel: Cosmos.ConsistencyLevel.Strong, - customizeClientBuilder: builder => builder.WithConsistencyLevel(clientLevel)); - - TestHandler testHandler = new TestHandler((request, cancellationToken) => + List cosmosLevels = Enum.GetValues(typeof(Cosmos.ConsistencyLevel)).Cast().ToList(); + foreach(Cosmos.ConsistencyLevel clientLevel in cosmosLevels) { - Assert.AreEqual(clientLevel.ToString(), request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]); - return TestHandler.ReturnSuccess(); - }); + using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( + accountConsistencyLevel: Cosmos.ConsistencyLevel.Strong, + customizeClientBuilder: builder => builder.WithConsistencyLevel(clientLevel)); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: client.ClientOptions.ConsistencyLevel) - { - InnerHandler = testHandler - }; + TestHandler testHandler = new TestHandler((request, cancellationToken) => + { + Assert.AreEqual(clientLevel.ToString(), request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]); + return TestHandler.ReturnSuccess(); + }); - RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")) - { - ResourceType = ResourceType.Document - }; - requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); - requestMessage.OperationType = OperationType.Read; + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: client.ClientOptions.ConsistencyLevel) + { + InnerHandler = testHandler + }; - await invoker.SendAsync(requestMessage, new CancellationToken()); + RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")) + { + ResourceType = ResourceType.Document + }; + requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); + requestMessage.OperationType = OperationType.Read; + + await invoker.SendAsync(requestMessage, new CancellationToken()); + } } [TestMethod] From 2e0106cfc8509713b3b37f0e9b2507e4934506d9 Mon Sep 17 00:00:00 2001 From: Jake Willey Date: Mon, 8 Feb 2021 08:34:31 -0800 Subject: [PATCH 2/2] Fixed unit test --- .../CosmosClientOptionsUnitTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 14aca88f80..748dc8ae9c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -139,7 +139,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(policy.UseMultipleWriteLocations); Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, policy.RetryOptions.MaxRetryAttemptsOnThrottledRequests); Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds); - Assert.AreEqual(ConsistencyLevel.Eventual, clientOptions.GetDocumentsConsistencyLevel()); + Assert.AreEqual((Documents.ConsistencyLevel)consistencyLevel, clientOptions.GetDocumentsConsistencyLevel()); IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; //Verify Direct Mode settings