diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc1d06f852..e3cb1edc66 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -125,6 +125,12 @@ Or all through `Re-run failed checks` on the top right corner: ![Re-run all failures](docs/images/contributing-rerunall.png) +## Usage of Cosmos DB Emulator for running unit tests + +- - The same version of the emulator used in the CI pipelines can be downloaded [here](https://aka.ms/cosmosdb-emulator) +- More information about how ro use the emulator for development is documented [here](https://github.com/Azure/azure-documentdb-dotnet/blob/master/docs/documentdb-nosql-local-emulator.md) +- You can start the emulator with same parameters as the emulator unit tests in the CI pipeline via `.\CosmosDB.Emulator.exe /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint` + ## Troubleshooting - [General .NET SDK Troubleshooting](https://docs.microsoft.com/azure/cosmos-db/sql/troubleshoot-dot-net-sdk) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs new file mode 100644 index 0000000000..a3dcb8b52a --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs @@ -0,0 +1,16 @@ +namespace Microsoft.Azure.Cosmos +{ + using Microsoft.Azure.Cosmos.Fluent; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + + [TestClass] + public class ComputeGatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase + { + protected override string AccountEndpointOverride => Utils.ConfigurationManager.AppSettings["ComputeGatewayEndpoint"]; + + protected override void ConfigureClientBuilder(CosmosClientBuilder builder) + { + builder.WithConnectionModeGateway(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs index 36be8df06d..aef4323045 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs @@ -19,9 +19,13 @@ public abstract class CosmosItemIdEncodingTestsBase : BaseCosmosClientHelper encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + private static readonly int computeGatewayPort = Int32.Parse(Utils.ConfigurationManager.AppSettings["ComputeGatewayPort"]); + private Container Container = null; private ContainerProperties containerSettings = null; + protected virtual String AccountEndpointOverride => null; + protected abstract void ConfigureClientBuilder(CosmosClientBuilder builder); [TestInitialize] @@ -29,7 +33,8 @@ public async Task TestInitialize() { await base.TestInit( validateSinglePartitionKeyRangeCacheCall: true, - customizeClientBuilder: this.ConfigureClientBuilder); + customizeClientBuilder: this.ConfigureClientBuilder, + accountEndpointOverride: this.AccountEndpointOverride); string PartitionKey = "/pk"; this.containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: PartitionKey); @@ -483,9 +488,17 @@ public async Task IdWithCarriageReturn() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -511,9 +524,17 @@ public async Task IdWithTab() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -539,9 +560,17 @@ public async Task IdWithLineFeed() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -559,8 +588,10 @@ public async Task IdWithLineFeed() private async Task ExecuteTestCase(TestScenario scenario) { TestScenarioExpectations expected = - this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? - scenario.Gateway : scenario.Direct; + this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Direct ? + scenario.Direct : + this.cosmosClient.Endpoint.Port == computeGatewayPort ? + scenario.ComputeGateway ?? scenario.Gateway : scenario.Gateway; Console.WriteLine($"Scenario: {scenario.Name}, Id: \"{scenario.Id}\""); @@ -671,6 +702,8 @@ private class TestScenario public TestScenarioExpectations Gateway { get; set; } + public TestScenarioExpectations ComputeGateway { get; set; } + public TestScenarioExpectations Direct { get; set; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs similarity index 63% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs index 5cd9e53a37..5052e629f5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs @@ -4,11 +4,12 @@ using Microsoft.Azure.Cosmos.SDK.EmulatorTests; [TestClass] - public class GatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase + public class RoutingGatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase { protected override void ConfigureClientBuilder(CosmosClientBuilder builder) { - builder.WithConnectionModeGateway(); + builder + .WithConnectionModeGateway(); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs index ab4027925a..20f083d85d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs @@ -18,12 +18,16 @@ public abstract class BaseCosmosClientHelper public async Task TestInit( bool validateSinglePartitionKeyRangeCacheCall = false, - Action customizeClientBuilder = null) + Action customizeClientBuilder = null, + string accountEndpointOverride = null) { this.cancellationTokenSource = new CancellationTokenSource(); this.cancellationToken = this.cancellationTokenSource.Token; - this.cosmosClient = TestCommon.CreateCosmosClient(validatePartitionKeyRangeCalls: validateSinglePartitionKeyRangeCacheCall, customizeClientBuilder: customizeClientBuilder); + this.cosmosClient = TestCommon.CreateCosmosClient( + validatePartitionKeyRangeCalls: validateSinglePartitionKeyRangeCacheCall, + customizeClientBuilder: customizeClientBuilder, + accountEndpointOverride: accountEndpointOverride); this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: this.cancellationToken); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index e85f9c565c..265e9542ef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -75,10 +75,13 @@ internal static (string endpoint, string authKey) GetAccountInfo() internal static CosmosClientBuilder GetDefaultConfiguration( bool useCustomSeralizer = true, - bool validatePartitionKeyRangeCalls = false) + bool validatePartitionKeyRangeCalls = false, + string accountEndpointOverride = null) { (string endpoint, string authKey) = TestCommon.GetAccountInfo(); - CosmosClientBuilder clientBuilder = new CosmosClientBuilder(accountEndpoint: endpoint, authKeyOrResourceToken: authKey); + CosmosClientBuilder clientBuilder = new CosmosClientBuilder( + accountEndpoint: accountEndpointOverride ?? endpoint, + authKeyOrResourceToken: authKey); if (useCustomSeralizer) { clientBuilder.WithCustomSerializer(new CosmosJsonDotNetSerializer()); @@ -95,9 +98,10 @@ internal static CosmosClientBuilder GetDefaultConfiguration( internal static CosmosClient CreateCosmosClient( Action customizeClientBuilder = null, bool useCustomSeralizer = true, - bool validatePartitionKeyRangeCalls = false) + bool validatePartitionKeyRangeCalls = false, + string accountEndpointOverride = null) { - CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(useCustomSeralizer, validatePartitionKeyRangeCalls); + CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(useCustomSeralizer, validatePartitionKeyRangeCalls, accountEndpointOverride); customizeClientBuilder?.Invoke(cosmosClientBuilder); CosmosClient client = cosmosClientBuilder.Build(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json index 31350d975b..51ecc8a707 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json @@ -1,6 +1,8 @@ { "AppSettings": { "GatewayEndpoint": "https://127.0.0.1:8081/", + "ComputeGatewayEndpoint": "https://localhost:8903/", + "ComputeGatewayPort": "8903", "Location": "South Central US", "Location2": "West US", "GlobalDatabaseAccountId": "globaldb", diff --git a/templates/emulator-setup.yml b/templates/emulator-setup.yml index 533e07a19d..10b5664d82 100644 --- a/templates/emulator-setup.yml +++ b/templates/emulator-setup.yml @@ -11,7 +11,7 @@ steps: mkdir "$env:temp\Azure Cosmos DB Emulator" lessmsi x "$env:temp\azure-cosmosdb-emulator.msi" "$env:temp\Azure Cosmos DB Emulator\" Write-Host "Starting Comsos DB Emulator" -ForegroundColor green - Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication" -Verb RunAs + Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint" -Verb RunAs Import-Module "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" Get-Item env:* | Sort-Object -Property Name for ($i=0; $i -lt 10; $i++) {