Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add orchestration query tests #3029

Merged
merged 5 commits into from
Feb 5, 2025
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
61 changes: 61 additions & 0 deletions test/e2e/Apps/BasicDotNetIsolated/OrchestrationQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Net;
using Grpc.Core;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask.Client;

namespace Microsoft.Azure.Durable.Tests.E2E;
public static class OrchestrationQueryFunctions
{
[Function(nameof(GetAllInstances))]
public static async Task<HttpResponseData> GetAllInstances(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client)
{
try
{
var instances = client.GetAllInstancesAsync();

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(instances);
return response;
}
catch (RpcException ex)
{
var response = req.CreateResponse(HttpStatusCode.BadRequest);
response.Headers.Add("Content-Type", "text/plain");
await response.WriteStringAsync(ex.Message);
return response;
}
}

[Function(nameof(GetRunningInstances))]
public static async Task<HttpResponseData> GetRunningInstances(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client)
{
try
{
OrchestrationQuery filter = new OrchestrationQuery(Statuses: new List<OrchestrationRuntimeStatus> {
OrchestrationRuntimeStatus.Running,
OrchestrationRuntimeStatus.Pending,
OrchestrationRuntimeStatus.Suspended
});
var instances = client.GetAllInstancesAsync(filter);

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(instances);
return response;
}
catch (RpcException ex)
{
var response = req.CreateResponse(HttpStatusCode.BadRequest);
response.Headers.Add("Content-Type", "text/plain");
await response.WriteStringAsync(ex.Message);
return response;
}
}
}
10 changes: 8 additions & 2 deletions test/e2e/Tests/Fixtures/FixtureHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,14 @@ public static Process GetFuncHostProcess(string appPath, bool enableAuth = false

public static void StartProcessWithLogging(Process funcProcess, ILogger logger)
{
funcProcess.ErrorDataReceived += (sender, e) => logger.LogError(e?.Data);
funcProcess.OutputDataReceived += (sender, e) => logger.LogInformation(e?.Data);
funcProcess.ErrorDataReceived += (sender, e) => {
try { logger.LogError(e?.Data); }
catch (InvalidOperationException) { }
};
funcProcess.OutputDataReceived += (sender, e) => {
try { logger.LogInformation(e?.Data); }
catch (InvalidOperationException) { }
};

funcProcess.Start();

Expand Down
83 changes: 83 additions & 0 deletions test/e2e/Tests/Tests/OrchestrationQueryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Net;
using System.Text.Json.Nodes;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Azure.Durable.Tests.DotnetIsolatedE2E;

[Collection(Constants.FunctionAppCollectionName)]
public class OrchestrationQueryTests
{
private readonly FunctionAppFixture _fixture;
private readonly ITestOutputHelper _output;

public OrchestrationQueryTests(FunctionAppFixture fixture, ITestOutputHelper testOutputHelper)
{
_fixture = fixture;
_fixture.TestLogs.UseTestLogger(testOutputHelper);
_output = testOutputHelper;
}


[Fact]
public async Task ListAllOrchestrations_ShouldSucceed()
{
using HttpResponseMessage statusResponse = await HttpHelpers.InvokeHttpTrigger("GetAllInstances", "");

Assert.Equal(HttpStatusCode.OK, statusResponse.StatusCode);

string? statusResponseMessage = await statusResponse.Content.ReadAsStringAsync();
Assert.NotNull(statusResponseMessage);

JsonNode? statusResponseJsonNode = JsonNode.Parse(statusResponseMessage);
Assert.NotNull(statusResponseJsonNode);
}


[Fact]
public async Task ListRunningOrchestrations_ShouldContainRunningOrchestration()
{
using HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("LongOrchestrator_HttpStart", "");

Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
string instanceId = await DurableHelpers.ParseInstanceIdAsync(response);
string statusQueryGetUri = await DurableHelpers.ParseStatusQueryGetUriAsync(response);

Thread.Sleep(1000);

try
{
var orchestrationDetails = await DurableHelpers.GetRunningOrchestrationDetailsAsync(statusQueryGetUri);
Assert.Equal("Running", orchestrationDetails.RuntimeStatus);

using HttpResponseMessage statusResponse = await HttpHelpers.InvokeHttpTrigger("GetRunningInstances", "");

Assert.Equal(HttpStatusCode.OK, statusResponse.StatusCode);
string? statusResponseMessage = await statusResponse.Content.ReadAsStringAsync();
Assert.NotNull(statusResponseMessage);

JsonNode? statusResponseJsonNode = JsonNode.Parse(statusResponseMessage);
Assert.NotNull(statusResponseJsonNode);

Assert.Contains(statusResponseJsonNode.AsArray(), x => x?["InstanceId"]?.ToString() == instanceId);
}
finally
{
await TryTerminateInstanceAsync(instanceId);
}
}
private static async Task<bool> TryTerminateInstanceAsync(string instanceId)
{
try
{
// Clean up the instance by terminating it - no-op if this fails
using HttpResponseMessage terminateResponse = await HttpHelpers.InvokeHttpTrigger("TerminateInstance", $"?instanceId={instanceId}");
return true;
}
catch (Exception) { }
return false;
}
}
Loading