diff --git a/eng/ci/templates/official/jobs/run-non-e2e-tests.yml b/eng/ci/templates/official/jobs/run-non-e2e-tests.yml index 6e4e6e93b8..9818918cba 100644 --- a/eng/ci/templates/official/jobs/run-non-e2e-tests.yml +++ b/eng/ci/templates/official/jobs/run-non-e2e-tests.yml @@ -33,6 +33,17 @@ jobs: targetType: inline script: 'Install-Module -Name Az.Storage -RequiredVersion 1.11.0 -Scope CurrentUser -Force -AllowClobber' + - task: PowerShell@2 + displayName: Start CosmosDB Emulator + inputs: + targetType: inline + script: | + Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" + Start-CosmosDbEmulator -NoFirewall -NoUI + + # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="public emulator key, not confidential")] + Write-Host "##vso[task.setvariable variable=CosmosDB]AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;" + - task: AzurePowerShell@5 displayName: Checkout secrets inputs: diff --git a/src/WebJobs.Script/runtimeassemblies.json b/src/WebJobs.Script/runtimeassemblies.json index 51426dbdff..18607fa611 100644 --- a/src/WebJobs.Script/runtimeassemblies.json +++ b/src/WebJobs.Script/runtimeassemblies.json @@ -479,6 +479,18 @@ "name": "Microsoft.Azure.AppService.Proxy.Runtime", "resolutionPolicy": "private" }, + { + "name": "Microsoft.Azure.Cosmos.Client", + "resolutionPolicy": "private" + }, + { + "name": "Microsoft.Azure.Cosmos.Core", + "resolutionPolicy": "private" + }, + { + "name": "Microsoft.Azure.Cosmos.Direct", + "resolutionPolicy": "private" + }, { "name": "Microsoft.Azure.Functions.Platform.Metrics.LinuxConsumption", "resolutionPolicy": "private" @@ -946,7 +958,7 @@ { "name": "OpenTelemetry.Api.ProviderBuilderExtensions", "resolutionPolicy": "private" - }, + }, { "name": "OpenTelemetry.Exporter.OpenTelemetryProtocol", "resolutionPolicy": "private" diff --git a/test/Directory.Packages.props b/test/Directory.Packages.props index 5149ee9c78..068803a4bb 100644 --- a/test/Directory.Packages.props +++ b/test/Directory.Packages.props @@ -18,7 +18,7 @@ - + diff --git a/test/Resources/TestScripts/CSharp/CosmosDBIn/function.json b/test/Resources/TestScripts/CSharp/CosmosDBIn/function.json deleted file mode 100644 index f3dbb7b3e5..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBIn/function.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "bindings": [ - { - "type": "queueTrigger", - "name": "input", - "queueName": "documentdb-input-csharp", - "direction": "in" - }, - { - "type": "cosmosDB", - "name": "item", - "direction": "in", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "id": "{documentId}" - }, - { - "type": "cosmosDB", - "name": "relatedItems", - "direction": "in", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "sqlQuery": "SELECT f.id, f.related FROM f WHERE f.related = {documentId}" - } - ] -} \ No newline at end of file diff --git a/test/Resources/TestScripts/CSharp/CosmosDBIn/run.csx b/test/Resources/TestScripts/CSharp/CosmosDBIn/run.csx deleted file mode 100644 index 87042cff4e..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBIn/run.csx +++ /dev/null @@ -1,22 +0,0 @@ -#r "Newtonsoft.Json" - -using System; -using System.Linq; -using Newtonsoft.Json.Linq; - -public static void Run(QueueInput input, JObject item, IEnumerable relatedItems) -{ - // throw if there's not 3 items - int count = relatedItems.Count(); - if (count != 3) - { - throw new InvalidOperationException($"Expected 3 documents. Found {count}."); - } - - item["text"] = "This was updated!"; -} - -public class QueueInput -{ - public string DocumentId { get; set; } -} \ No newline at end of file diff --git a/test/Resources/TestScripts/CSharp/CosmosDBOut/function.json b/test/Resources/TestScripts/CSharp/CosmosDBOut/function.json deleted file mode 100644 index bb61500834..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBOut/function.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "bindings": [ - { - "type": "manualTrigger", - "name": "input", - "direction": "in" - }, - { - "type": "cosmosDB", - "name": "relatedItems", - "direction": "out", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createIfNotExists": true - }, - { - "type": "cosmosDB", - "name": "$return", - "direction": "out", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createIfNotExists": true - } - ] -} diff --git a/test/Resources/TestScripts/CSharp/CosmosDBOut/run.csx b/test/Resources/TestScripts/CSharp/CosmosDBOut/run.csx deleted file mode 100644 index 5e6064feb7..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBOut/run.csx +++ /dev/null @@ -1,14 +0,0 @@ -public static object Run(string input, ICollector relatedItems) -{ - // a later stage of the test will query for these - for (int i = 0; i < 3; i++) - { - relatedItems.Add(new { related = input }); - } - - return new - { - id = input, - text = "Hello from C#!" - }; -} \ No newline at end of file diff --git a/test/Resources/TestScripts/CSharp/CosmosDBTrigger/function.json b/test/Resources/TestScripts/CSharp/CosmosDBTrigger/function.json deleted file mode 100644 index c01ff2c7d5..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBTrigger/function.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bindings": [ - { - "type": "cosmosDBTrigger", - "name": "input", - "direction": "in", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createLeaseCollectionIfNotExists": true - }, - { - "type": "blob", - "name": "completed", - "direction": "out", - "path": "test-output-csharp/cosmosdbtriggere2e-completed" - } - ] -} diff --git a/test/Resources/TestScripts/CSharp/CosmosDBTrigger/run.csx b/test/Resources/TestScripts/CSharp/CosmosDBTrigger/run.csx deleted file mode 100644 index 8ce08f4ca2..0000000000 --- a/test/Resources/TestScripts/CSharp/CosmosDBTrigger/run.csx +++ /dev/null @@ -1,10 +0,0 @@ -#r "Microsoft.Azure.DocumentDB.Core" - -using Microsoft.Azure.Documents; -using System.Collections.Generic; -using System; - -public static void Run(IReadOnlyList input, out string completed) -{ - completed = input[0].Id; -} \ No newline at end of file diff --git a/test/Resources/TestScripts/Node/CosmosDBIn/function.json b/test/Resources/TestScripts/Node/CosmosDBIn/function.json index 2576d537fd..e516fed3b7 100644 --- a/test/Resources/TestScripts/Node/CosmosDBIn/function.json +++ b/test/Resources/TestScripts/Node/CosmosDBIn/function.json @@ -1,4 +1,4 @@ -{ +{ "bindings": [ { "type": "queueTrigger", @@ -11,24 +11,18 @@ "name": "itemIn", "direction": "in", "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "id": "{documentId}" - }, - { - "type": "cosmosDB", - "name": "relatedItems", - "direction": "in", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "sqlQuery": "SELECT f.id, f.related FROM f WHERE f.related = {documentId}" + "containerName": "ItemCollection", + "partitionKey": "{id}", + "id": "{id}" }, { "type": "cosmosDB", "name": "itemOut", "direction": "out", "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createIfNotExists": true + "containerName": "ItemCollection", + "createIfNotExists": true, + "partitionKey": "{id}" } ] } diff --git a/test/Resources/TestScripts/Node/CosmosDBIn/index.js b/test/Resources/TestScripts/Node/CosmosDBIn/index.js index d62ee02d64..9b85398e6a 100644 --- a/test/Resources/TestScripts/Node/CosmosDBIn/index.js +++ b/test/Resources/TestScripts/Node/CosmosDBIn/index.js @@ -1,11 +1,11 @@ -module.exports = function (context, input) { +module.exports = function (context, input) { context.log(context.bindings); - var relatedCount = context.bindings.relatedItems.length; - if (relatedCount !== 3) { - throw Error("Expected 3 documents. Found " + relatedCount); - } + //var relatedCount = context.bindings.relatedItems.length; + //if (relatedCount !== 3) { + // throw Error("Expected 3 documents. Found " + relatedCount); + //} context.bindings.itemOut = context.bindings.itemIn; context.bindings.itemOut.text = "This was updated!"; diff --git a/test/Resources/TestScripts/Node/CosmosDBOut/function.json b/test/Resources/TestScripts/Node/CosmosDBOut/function.json index 7b2cd5fb3b..edc7031fcd 100644 --- a/test/Resources/TestScripts/Node/CosmosDBOut/function.json +++ b/test/Resources/TestScripts/Node/CosmosDBOut/function.json @@ -1,24 +1,16 @@ -{ +{ "bindings": [ { "type": "manualTrigger", "name": "input", "direction": "in" }, - { - "type": "cosmosDB", - "name": "relatedItems", - "direction": "out", - "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createIfNotExists": true - }, { "type": "cosmosDB", "name": "item", "direction": "out", "databaseName": "ItemDb", - "collectionName": "ItemCollection", + "containerName": "ItemCollection", "createIfNotExists": true } ] diff --git a/test/Resources/TestScripts/Node/CosmosDBOut/index.js b/test/Resources/TestScripts/Node/CosmosDBOut/index.js index c6a27912a2..c4fbbb12fd 100644 --- a/test/Resources/TestScripts/Node/CosmosDBOut/index.js +++ b/test/Resources/TestScripts/Node/CosmosDBOut/index.js @@ -1,12 +1,6 @@ -module.exports = function (context, input) { +module.exports = function (context, input) { context.log('Node.js function triggered with input', input); - context.bindings.relatedItems = [ - { related: input }, - { related: input }, - { related: input } - ]; - context.bindings.item = { id: input, text: "Hello from Node!" diff --git a/test/Resources/TestScripts/Node/CosmosDBTrigger/function.json b/test/Resources/TestScripts/Node/CosmosDBTrigger/function.json index 68e61c2b5b..316d64c967 100644 --- a/test/Resources/TestScripts/Node/CosmosDBTrigger/function.json +++ b/test/Resources/TestScripts/Node/CosmosDBTrigger/function.json @@ -1,16 +1,19 @@ -{ +{ "bindings": [ { "type": "cosmosDBTrigger", "name": "input", "direction": "in", "databaseName": "ItemDb", - "collectionName": "ItemCollection", - "createLeaseCollectionIfNotExists": true + "containerName": "ItemCollection", + "connection": "CosmosDB", + "leaseContainerName": "leases", + "createLeaseContainerIfNotExists": true }, { "type": "blob", "name": "blob", + "connection": "AzureWebJobsStorage", "direction": "out", "path": "test-output-node/cosmosdbtriggere2e-completed" } diff --git a/test/Resources/TestScripts/Node/CosmosDBTrigger/index.js b/test/Resources/TestScripts/Node/CosmosDBTrigger/index.js index b70d47b016..d91401fc1b 100644 --- a/test/Resources/TestScripts/Node/CosmosDBTrigger/index.js +++ b/test/Resources/TestScripts/Node/CosmosDBTrigger/index.js @@ -1,4 +1,4 @@ -module.exports = function (context, input) { +module.exports = function (context, input) { context.log('Document Id: ', input[0].id); context.bindings.blob = input[0].id; diff --git a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBCSharpEndToEndTests.cs b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBCSharpEndToEndTests.cs deleted file mode 100644 index 23201397a6..0000000000 --- a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBCSharpEndToEndTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using Microsoft.Azure.WebJobs.Script.Workers.Rpc; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Azure.WebJobs.Script.Tests.CosmosDB -{ - public class CosmosDBCSharpEndToEndTests : - CosmosDBEndToEndTestsBase - { - public CosmosDBCSharpEndToEndTests(TestFixture fixture) : base(fixture) - { - } - - [Fact] - public Task CosmosDBTrigger() - { - return CosmosDBTriggerToBlobTest(); - } - - [Fact] - public Task CosmosDB() - { - return CosmosDBTest(); - } - - public class TestFixture : CosmosDBTestFixture - { - private const string ScriptRoot = @"TestScripts\CSharp"; - - public TestFixture() : base(ScriptRoot, "csharp", RpcWorkerConstants.DotNetLanguageWorkerName) - { - } - } - } -} diff --git a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndToEndTestsBase.cs b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndToEndTestsBase.cs index 9e079fb217..8443edf94d 100644 --- a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndToEndTestsBase.cs +++ b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndToEndTestsBase.cs @@ -1,21 +1,16 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; -using System.Linq; using System.Threading.Tasks; -using Microsoft.Azure.Documents; -using Microsoft.Azure.Documents.Client; +using Microsoft.Azure.Cosmos; using Microsoft.Azure.Storage.Queue; -using Microsoft.Azure.WebJobs.Script.Models; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Microsoft.Azure.WebJobs.Script.Tests.CosmosDB { public abstract class CosmosDBEndToEndTestsBase : - EndToEndTestsBase where TTestFixture : CosmosDBTestFixture, new() + EndToEndTestsBase where TTestFixture : CosmosDBEndtoEndTestFixture, new() { public CosmosDBEndToEndTestsBase(TTestFixture fixture) : base(fixture) { @@ -23,151 +18,90 @@ public CosmosDBEndToEndTestsBase(TTestFixture fixture) : base(fixture) protected async Task CosmosDBTriggerToBlobTest() { - // CosmosDB tests need the following connection string: - // "ConnectionStrings:CosmosDB" -- the connection string to the account - // Waiting for the Processor to acquire leases await Task.Delay(10000); - await Fixture.InitializeDocumentClient(); - bool collectionsCreated = await Fixture.CreateDocumentCollections(); + bool collectionsCreated = await Fixture.CreateContainers(); var resultBlob = Fixture.TestOutputContainer.GetBlockBlobReference("cosmosdbtriggere2e-completed"); await resultBlob.DeleteIfExistsAsync(); string id = Guid.NewGuid().ToString(); - Document documentToTest = new Document() - { - Id = id - }; + var documentToTest = new { id }; - await Fixture.DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri("ItemDb", "ItemCollection"), documentToTest); + await Fixture.CosmosClient.GetContainer("ItemDb", "ItemCollection") + .CreateItemAsync(documentToTest, new PartitionKey(id)); // now wait for function to be invoked string result = await TestHelpers.WaitForBlobAndGetStringAsync(resultBlob, () => string.Join(Environment.NewLine, Fixture.Host.GetScriptHostLogMessages())); - if (collectionsCreated) - { - // cleanup collections - await Fixture.DeleteDocumentCollections(); - } + // cleanup collections + await Fixture.DeleteContainers(); Assert.False(string.IsNullOrEmpty(result)); } protected async Task CosmosDBTest() { - // DocumentDB tests need the following connection string: - // "ConnectionStrings:CosmosDB" -- the connection string to the account string id = Guid.NewGuid().ToString(); await Fixture.Host.BeginFunctionAsync("CosmosDBOut", id); - Document doc = await WaitForDocumentAsync(id); + dynamic doc = await WaitForItemAsync(id); - Assert.Equal(doc.Id, id); + Assert.Equal((string)doc.id, id); - // Now add that Id to a Queue, in an object to test binding var queue = await Fixture.GetNewQueue("documentdb-input"); - string messageContent = string.Format("{{ \"documentId\": \"{0}\" }}", id); + string messageContent = string.Format("{{ \"id\": \"{0}\" }}", id); await queue.AddMessageAsync(new CloudQueueMessage(messageContent)); // And wait for the text to be updated - Document updatedDoc = await WaitForDocumentAsync(id, "This was updated!"); + dynamic updatedDoc = await WaitForItemAsync(id, "This was updated!"); - Assert.Equal(updatedDoc.Id, doc.Id); - Assert.NotEqual(doc.ETag, updatedDoc.ETag); + Assert.Equal(updatedDoc.id, doc.id); + Assert.NotEqual(doc._etag, updatedDoc._etag); } - } - public abstract class CosmosDBTestFixture : EndToEndTestFixture - { - protected CosmosDBTestFixture(string rootPath, string testId, string language) : - base(rootPath, testId, language) + protected async Task WaitForItemAsync(string itemId, string textToMatch = null) { - } - - public DocumentClient DocumentClient { get; private set; } + var container = Fixture.CosmosClient.GetContainer("ItemDb", "ItemCollection"); - protected override ExtensionPackageReference[] GetExtensionsToInstall() - { - return new ExtensionPackageReference[] - { - new ExtensionPackageReference - { - Id = "Microsoft.Azure.WebJobs.Extensions.CosmosDB", - Version = "3.0.10" - } - }; - } + dynamic document = null; - public override void ConfigureScriptHost(IWebJobsBuilder webJobsBuilder) - { - webJobsBuilder.Services.Configure(o => + await TestHelpers.Await(async () => { - o.Functions = new[] - { - "CosmosDBTrigger", - "CosmosDBIn", - "CosmosDBOut" - }; - }); - } + bool result = false; - public async Task InitializeDocumentClient() - { - if (DocumentClient == null) - { - var builder = new System.Data.Common.DbConnectionStringBuilder + try { - ConnectionString = TestHelpers.GetTestConfiguration().GetConnectionString("CosmosDB") - }; + var response = await container.ReadItemAsync(itemId, new PartitionKey(itemId)); + document = response.Resource; - var serviceUri = new Uri(builder["AccountEndpoint"].ToString()); - - DocumentClient = new DocumentClient(serviceUri, builder["AccountKey"].ToString()); - await DocumentClient.OpenAsync(); - } - } - - public async Task CreateDocumentCollections() - { - bool willCreateCollection = false; - Database db = new Database() { Id = "ItemDb" }; - await DocumentClient.CreateDatabaseIfNotExistsAsync(db); - Uri dbUri = UriFactory.CreateDatabaseUri(db.Id); - - DocumentCollection collection = new DocumentCollection() { Id = "ItemCollection" }; - willCreateCollection = !DocumentClient.CreateDocumentCollectionQuery(dbUri).Where(x => x.Id == collection.Id).ToList().Any(); - await DocumentClient.CreateDocumentCollectionIfNotExistsAsync(dbUri, collection, - new RequestOptions() - { - OfferThroughput = 400 - }); - - Documents.DocumentCollection leasesCollection = new Documents.DocumentCollection() { Id = "leases" }; - await DocumentClient.CreateDocumentCollectionIfNotExistsAsync(dbUri, leasesCollection, - new RequestOptions() + if (textToMatch != null) + { + result = document.text == textToMatch; + } + else + { + result = true; + } + } + catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { - OfferThroughput = 400 - }); - - return willCreateCollection; - } + // Document not found, continue waiting + return false; + } - public async Task DeleteDocumentCollections() - { - Uri collectionsUri = UriFactory.CreateDocumentCollectionUri("ItemDb", "ItemCollection"); - Uri leasesCollectionsUri = UriFactory.CreateDocumentCollectionUri("ItemDb", "leases"); - await DocumentClient.DeleteDocumentCollectionAsync(collectionsUri); - await DocumentClient.DeleteDocumentCollectionAsync(leasesCollectionsUri); - } + return result; + }, + userMessageCallback: () => + { + var logs = string.Join(Environment.NewLine, Fixture.Host.GetScriptHostLogMessages()); + return logs; + }); - public override async Task DisposeAsync() - { - await base.DisposeAsync(); - DocumentClient?.Dispose(); + return document; } } } diff --git a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndtoEndTestFixture.cs b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndtoEndTestFixture.cs new file mode 100644 index 0000000000..2d56f79f4e --- /dev/null +++ b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBEndtoEndTestFixture.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using Microsoft.Azure.Cosmos; +using Microsoft.Azure.WebJobs.Script.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Microsoft.Azure.WebJobs.Script.Tests.CosmosDB +{ + public abstract class CosmosDBEndtoEndTestFixture : EndToEndTestFixture + { + [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification = "Well known account key for emulator. Used for testing.")] + private static string CosmosDBConnection => "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; + + protected CosmosDBEndtoEndTestFixture(string rootPath, string testId, string language) : + base(rootPath, testId, language) + { + } + + public CosmosClient CosmosClient { get; private set; } + + protected override ExtensionPackageReference[] GetExtensionsToInstall() + { + return new ExtensionPackageReference[] + { + new ExtensionPackageReference + { + Id = "Microsoft.Azure.WebJobs.Extensions.CosmosDB", + Version = "4.11.0" + } + }; + } + + public override void ConfigureScriptHost(IWebJobsBuilder webJobsBuilder) + { + webJobsBuilder.Services.Configure(o => + { + o.Functions = new[] + { + "CosmosDBTrigger", + "CosmosDBIn", + "CosmosDBOut" + }; + }); + } + + public override void ConfigureScriptHost(IConfigurationBuilder configBuilder) + { + base.ConfigureScriptHost(configBuilder); + } + + public void InitializeCosmosClient() + { + if (CosmosClient is null) + { + CosmosClient = new CosmosClient(CosmosDBConnection); + } + } + + public override async Task InitializeAsync() + { + InitializeCosmosClient(); + await base.InitializeAsync(); + } + + public override async Task DisposeAsync() + { + await base.DisposeAsync(); + CosmosClient?.Dispose(); + } + + public async Task CreateContainers() + { + bool collectionsCreated = false; + + DatabaseResponse databaseResponse = await CosmosClient.CreateDatabaseIfNotExistsAsync("ItemDb"); + Database database = databaseResponse.Database; + + ContainerProperties itemCollectionProperties = new ContainerProperties("ItemCollection", "/id"); + ContainerResponse itemCollectionResponse = await database.CreateContainerIfNotExistsAsync(itemCollectionProperties, throughput: 400); + + ContainerProperties leasesCollectionProperties = new ContainerProperties("leases", "/id"); + ContainerResponse leasesCollectionResponse = await database.CreateContainerIfNotExistsAsync(leasesCollectionProperties, throughput: 400); + + if ((itemCollectionResponse.StatusCode == System.Net.HttpStatusCode.Created || itemCollectionResponse.StatusCode == System.Net.HttpStatusCode.OK) && + (leasesCollectionResponse.StatusCode == System.Net.HttpStatusCode.Created || leasesCollectionResponse.StatusCode == System.Net.HttpStatusCode.OK)) + { + collectionsCreated = true; + } + + return collectionsCreated; + } + + public async Task DeleteContainers() + { + Database database = CosmosClient.GetDatabase("ItemDb"); + + // Delete the "ItemCollection" container + Container itemCollectionContainer = database.GetContainer("ItemCollection"); + await itemCollectionContainer.DeleteContainerAsync(); + + // Delete the "leases" container + Container leasesContainer = database.GetContainer("leases"); + await leasesContainer.DeleteContainerAsync(); + } + } +} diff --git a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBNodeEndToEndTests.cs b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBNodeEndToEndTests.cs index 4925dfc02d..843c88e5d0 100644 --- a/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBNodeEndToEndTests.cs +++ b/test/WebJobs.Script.Tests.Integration/CosmosDB/CosmosDBNodeEndToEndTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using Microsoft.Azure.WebJobs.Script.Workers.Rpc; @@ -26,7 +26,7 @@ public Task CosmosDB() return CosmosDBTest(); } - public class TestFixture : CosmosDBTestFixture + public class TestFixture : CosmosDBEndtoEndTestFixture { private const string ScriptRoot = @"TestScripts\Node"; diff --git a/test/WebJobs.Script.Tests.Integration/Fixtures/AzuriteFixture.cs b/test/WebJobs.Script.Tests.Integration/Fixtures/AzuriteFixture.cs index 5391520850..f8fc51a77b 100644 --- a/test/WebJobs.Script.Tests.Integration/Fixtures/AzuriteFixture.cs +++ b/test/WebJobs.Script.Tests.Integration/Fixtures/AzuriteFixture.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Net.Sockets; @@ -35,7 +35,7 @@ public string GetConnectionString() VerifyInitialized(); IEnumerable<(string Key, string Value)> properties = [ - ("DefaultEndpointsProtocol", Uri.UriSchemeHttps), + ("DefaultEndpointsProtocol", Uri.UriSchemeHttp), ("AccountName", AccountName), ("AccountKey", AccountKey), ("BlobEndpoint", GetBlobEndpoint()), @@ -121,9 +121,10 @@ private static int GetFreeTcpPort() private Task StartAzuriteAsync() { - _blobPort = GetFreeTcpPort(); - _queuePort = GetFreeTcpPort(); - _tablePort = GetFreeTcpPort(); + // TODO: For testing, remove later + _blobPort = 10000; // GetFreeTcpPort(); + _queuePort = 10001; // GetFreeTcpPort(); + _tablePort = 10002; // GetFreeTcpPort(); GetAzuriteCommand(out string process, out string arguments); ProcessStartInfo startInfo = new() { diff --git a/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs b/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs index 95884ca213..5f5c64a3e7 100644 --- a/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs +++ b/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs @@ -1,13 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; using Azure; using Azure.Data.Tables; using Microsoft.Azure.Storage.Blob; @@ -28,8 +21,15 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Moq; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; using Xunit; -using Xunit.Abstractions; using CloudStorageAccount = Microsoft.Azure.Storage.CloudStorageAccount; namespace Microsoft.Azure.WebJobs.Script.Tests @@ -44,6 +44,9 @@ public abstract class EndToEndTestFixture : IAsyncLifetime private string _functionsWorkerRuntimeVersion; private bool _addTestSettings; + [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification = "Well known account key for emulator. Used for testing.")] + private string CosmosDBConnectionString = "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; + protected EndToEndTestFixture( string rootPath, string testId, @@ -168,6 +171,7 @@ string GetDestPath(int counter) { { "AzureWebJobsStorage", azuriteConnectionString }, { "ConnectionStrings:AzureWebJobsStorage", azuriteConnectionString }, + { "ConnectionStrings:CosmosDB", CosmosDBConnectionString} }); ConfigureScriptHost(configBuilder); @@ -178,6 +182,7 @@ string GetDestPath(int counter) // Flow this env variable to out of proc workers. s.Configure(o => o.Features["AzureWebJobsStorage"] = azuriteConnectionString); + s.Configure(o => o.Features["ConnectionStrings:CosmosDB"] = CosmosDBConnectionString); ConfigureWebHost(s); }, configureWebHostAppConfiguration: configBuilder => diff --git a/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestsBase.cs b/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestsBase.cs index a3be885428..0cc1ef8687 100644 --- a/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestsBase.cs +++ b/test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestsBase.cs @@ -1,15 +1,12 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.Collections.Generic; -using System.Data.Common; using System.Linq; using System.Net; using System.Threading.Tasks; using Azure.Data.Tables; -using Microsoft.Azure.Documents; -using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Storage.Blob; using Microsoft.Azure.Storage.Queue; using Microsoft.Azure.WebJobs.Host; @@ -279,55 +276,6 @@ protected async Task GetEmptyContainer(string containerName) return container; } - protected async Task WaitForDocumentAsync(string itemId, string textToMatch = null) - { - var docUri = UriFactory.CreateDocumentUri("ItemDb", "ItemCollection", itemId); - - // We know the tests are using the default connection string. - var connectionString = _configuration.GetConnectionString("CosmosDB"); - var builder = new DbConnectionStringBuilder - { - ConnectionString = connectionString - }; - var serviceUri = new Uri(builder["AccountEndpoint"].ToString()); - var client = new DocumentClient(serviceUri, builder["AccountKey"].ToString()); - - Document doc = null; - await TestHelpers.Await(async () => - { - bool result = false; - - try - { - var response = await client.ReadDocumentAsync(docUri); - doc = response.Resource; - } - catch (DocumentClientException ex) when (ex.Error.Code == "NotFound") - { - return false; - } - - if (textToMatch != null) - { - result = doc.GetPropertyValue("text") == textToMatch; - } - else - { - result = true; - } - - return result; - }, - userMessageCallback: () => - { - // AppVeyor only shows 4096 chars - var s = string.Join(Environment.NewLine, Fixture.Host.GetScriptHostLogMessages()); - return s.Length < 4096 ? s : s.Substring(s.Length - 4096); - }); - - return doc; - } - protected static bool VerifyNotificationHubExceptionMessage(Exception exception) { if ((exception.Source == "Microsoft.Azure.NotificationHubs") diff --git a/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj b/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj index 466fdcb7e5..bf26363f56 100644 --- a/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj +++ b/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -11,9 +11,9 @@ + -