Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions extensions/Worker.Extensions.CosmosDB/src/CosmosDBConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,12 @@ private async Task<object> CreatePOCOCollectionAsync<T>(Container container, Cos
}
}

PartitionKey partitionKey = String.IsNullOrEmpty(cosmosAttribute.PartitionKey)
? PartitionKey.None
: new PartitionKey(cosmosAttribute.PartitionKey);

QueryRequestOptions queryRequestOptions = new() { PartitionKey = partitionKey };
QueryRequestOptions queryRequestOptions = new();
if (!String.IsNullOrEmpty(cosmosAttribute.PartitionKey))
{
var partitionKey = new PartitionKey(cosmosAttribute.PartitionKey);
queryRequestOptions = new() { PartitionKey = partitionKey };
}

using (var iterator = container.GetItemQueryIterator<T>(queryDefinition: queryDefinition, requestOptions: queryRequestOptions))
{
Expand Down
142 changes: 132 additions & 10 deletions test/E2ETests/E2EApps/E2EApp/Cosmos/CosmosFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,30 @@

using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;

namespace Microsoft.Azure.Functions.Worker.E2EApp
{
public static class CosmosFunction
public class CosmosFunction
{
private readonly ILogger<CosmosFunction> _logger;

public CosmosFunction(ILogger<CosmosFunction> logger)
{
_logger = logger;
}

[Function(nameof(CosmosTrigger))]
[CosmosDBOutput(
databaseName: "%CosmosDb%",
containerName: "%CosmosCollOut%",
Connection = "CosmosConnection",
CreateIfNotExists = true)]
public static object CosmosTrigger([CosmosDBTrigger(
public object CosmosTrigger([CosmosDBTrigger(
databaseName: "%CosmosDb%",
containerName: "%CosmosCollIn%",
Connection = "CosmosConnection",
Expand All @@ -27,24 +37,136 @@ public static object CosmosTrigger([CosmosDBTrigger(
{
foreach (var doc in input)
{
context.GetLogger("Function.CosmosTrigger").LogInformation($"id: {doc.Id}");
context.GetLogger("Function.CosmosTrigger").LogInformation($"id: {doc.Text}");
}

return input.Select(p => new { id = p.Id });
return input.Select(p => new { id = p.Text });
}

return null;
}

public class MyDocument
[Function(nameof(DocsByUsingCosmosClient))]
public async Task<HttpResponseData> DocsByUsingCosmosClient(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[CosmosDBInput("", "", Connection = "CosmosConnection")] CosmosClient client)
{
public string Id { get; set; }
var container = client.GetContainer("ItemDb", "ItemCollectionIn");
var iterator = container.GetItemQueryIterator<MyDocument>("SELECT * FROM c");

public string Text { get; set; }
var output = "";

while (iterator.HasMoreResults)
{
var documents = await iterator.ReadNextAsync();
foreach (dynamic d in documents)
{
output += $"{(string)d.Text}, ";
}
}

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(output);
return response;
}

[Function(nameof(DocsByUsingDatabaseClient))]
public async Task<HttpResponseData> DocsByUsingDatabaseClient(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[CosmosDBInput("%CosmosDb%", "", Connection = "CosmosConnection")] Database database)
{
var container = database.GetContainer("ItemCollectionIn");;
var iterator = container.GetItemQueryIterator<MyDocument>("SELECT * FROM c");

var output = "";

while (iterator.HasMoreResults)
{
var documents = await iterator.ReadNextAsync();
foreach (dynamic d in documents)
{
output += $"{(string)d.Text}, ";
}
}

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(output);
return response;
}

[Function(nameof(DocsByUsingContainerClient))]
public async Task<HttpResponseData> DocsByUsingContainerClient(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[CosmosDBInput("%CosmosDb%", "%CosmosCollIn%", Connection = "CosmosConnection")] Container container)
{
var iterator = container.GetItemQueryIterator<MyDocument>("SELECT * FROM c");

var output = "";

while (iterator.HasMoreResults)
{
var documents = await iterator.ReadNextAsync();
foreach (dynamic d in documents)
{
output += $"{(string)d.Text}, ";
}
}

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(output);
return response;
}

public int Number { get; set; }
[Function(nameof(DocByIdFromRouteData))]
public async Task<HttpResponseData> DocByIdFromRouteData(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "docsbyroute/{partitionKey}/{id}")] HttpRequestData req,
[CosmosDBInput(
databaseName: "%CosmosDb%",
containerName: "%CosmosCollIn%",
Connection = "CosmosConnection",
Id = "{id}",
PartitionKey = "{partitionKey}")] MyDocument doc)
{
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(doc.Text);
return response;
}

[Function(nameof(DocByIdFromRouteDataUsingSqlQuery))]
public async Task<HttpResponseData> DocByIdFromRouteDataUsingSqlQuery(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "docsbysql/{id}")] HttpRequestData req,
[CosmosDBInput(
databaseName: "%CosmosDb%",
containerName: "%CosmosCollIn%",
Connection = "CosmosConnection",
SqlQuery = "SELECT * FROM ItemDb t where t.id = {id}")]
IEnumerable<MyDocument> myDocs)
{
var output = myDocs.FirstOrDefault().Text;
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(output);
return response;
}

public bool Boolean { get; set; }
[Function(nameof(DocByIdFromQueryStringUsingSqlQuery))]
public async Task<HttpResponseData> DocByIdFromQueryStringUsingSqlQuery(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[CosmosDBInput(
databaseName: "%CosmosDb%",
containerName: "%CosmosCollIn%",
Connection = "CosmosConnection",
SqlQuery = "SELECT * FROM ItemDb t where t.id = {id}")]
IEnumerable<MyDocument> myDocs)
{
var output = myDocs.FirstOrDefault().Text;
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(output);
return response;
}

public class MyDocument
{
public string Text { get; set; }
}
}
}
5 changes: 2 additions & 3 deletions test/E2ETests/E2EApps/E2EApp/E2EApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>

<PropertyGroup Condition="$(FunctionsRuntimeVersion) == '3'">
<TargetFramework>net7.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
Expand Down Expand Up @@ -46,7 +46,6 @@
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Condition="$(TestBuild) == 'true'" Include="Microsoft.Azure.Functions.Worker" Version="1.12.1-preview1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.11.0-preview1" />

<PackageReference Condition="$(FunctionsRuntimeVersion) != '3'" Include="System.Text.Json" Version="6.0.5" />
<PackageReference Condition="$(FunctionsRuntimeVersion) == '3'" Include="System.Text.Json" Version="5.0.2" />
</ItemGroup>
Expand Down
115 changes: 114 additions & 1 deletion test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -27,7 +29,7 @@ public async Task CosmosDBTriggerAndOutput_Succeeds()
try
{
//Trigger
await CosmosDBHelpers.CreateDocument(expectedDocId);
await CosmosDBHelpers.CreateDocument(expectedDocId, expectedDocId);

//Read
var documentId = await CosmosDBHelpers.ReadDocument(expectedDocId);
Expand All @@ -40,6 +42,117 @@ public async Task CosmosDBTriggerAndOutput_Succeeds()
}
}

[Theory]
[InlineData("DocsByUsingCosmosClient")]
[InlineData("DocsByUsingDatabaseClient")]
[InlineData("DocsByUsingContainerClient")]
public async Task CosmosInput_ClientBinding_Succeeds(string functionName)
{
string expectedDocId = Guid.NewGuid().ToString();
try
{
//Setup
await CosmosDBHelpers.CreateDocument(expectedDocId, expectedDocId);

//Trigger
HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionName);
string actualMessage = await response.Content.ReadAsStringAsync();

//Verify
HttpStatusCode expectedStatusCode = HttpStatusCode.OK;

Assert.Equal(expectedStatusCode, response.StatusCode);
Assert.Contains(expectedDocId, actualMessage);
}
finally
{
//Clean up
await CosmosDBHelpers.DeleteTestDocuments(expectedDocId);
}
}

[Fact]
public async Task CosmosInput_DocByIdFromRouteData_Succeeds()
{
string expectedDocId = Guid.NewGuid().ToString();
string functionPath = $"docsbyroute/{expectedDocId}/{expectedDocId}";
try
{
//Setup
await CosmosDBHelpers.CreateDocument(expectedDocId, "DocByIdFromRouteData");

//Trigger
HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionPath);
string actualMessage = await response.Content.ReadAsStringAsync();

//Verify
HttpStatusCode expectedStatusCode = HttpStatusCode.OK;

Assert.Equal(expectedStatusCode, response.StatusCode);
Assert.Contains("DocByIdFromRouteData", actualMessage);
}
finally
{
//Clean up
await CosmosDBHelpers.DeleteTestDocuments(expectedDocId);
}
}

[Fact]
public async Task CosmosInput_DocByIdFromRouteDataUsingSqlQuery_Succeeds()
{
string expectedDocId = Guid.NewGuid().ToString();
string functionPath = $"docsbysql/{expectedDocId}";
try
{
//Setup
await CosmosDBHelpers.CreateDocument(expectedDocId, "DocByIdFromRouteDataUsingSqlQuery");

//Trigger
HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionPath);
string actualMessage = await response.Content.ReadAsStringAsync();

//Verify
HttpStatusCode expectedStatusCode = HttpStatusCode.OK;

Assert.Equal(expectedStatusCode, response.StatusCode);
Assert.Contains("DocByIdFromRouteDataUsingSqlQuery", actualMessage);
}
finally
{
//Clean up
await CosmosDBHelpers.DeleteTestDocuments(expectedDocId);
}
}

[Fact]
public async Task CosmosInput_DocByIdFromQueryStringUsingSqlQuery_Succeeds()
{
string expectedDocId = Guid.NewGuid().ToString();
string functionName = "DocByIdFromQueryStringUsingSqlQuery";
string requestBody = @$"{{ ""id"": ""{expectedDocId}"" }}";
try
{
//Setup
await CosmosDBHelpers.CreateDocument(expectedDocId, functionName);

//Trigger
HttpResponseMessage response = await HttpHelpers.InvokeHttpTriggerWithBody(functionName, requestBody, "application/json");
string actualMessage = await response.Content.ReadAsStringAsync();

//Verify
HttpStatusCode expectedStatusCode = HttpStatusCode.OK;

Assert.Equal(expectedStatusCode, response.StatusCode);
Assert.Contains(functionName, actualMessage);
}
finally
{
//Clean up
await CosmosDBHelpers.DeleteTestDocuments(expectedDocId);
}
}

public void Dispose()
{
_disposeLog?.Dispose();
Expand Down
2 changes: 1 addition & 1 deletion test/E2ETests/E2ETests/E2ETests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Data.Tables" Version="12.8.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.13.1" />
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.13.1" />
Expand All @@ -19,7 +20,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Azure.Data.Tables" Version="12.8.0" />
</ItemGroup>

<ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ await TestUtility.RetryAsync(async () =>
}
catch
{
if (_funcProcess.HasExited)
{
// Something went wrong starting the host - check the logs
_logger.LogInformation($" Current state: process exited - something may have gone wrong.");
return false;
}

// Can get exceptions before host is running.
_logger.LogInformation($" Current state: process starting");
return false;
Expand Down
Loading