diff --git a/.github/workflows/validate-build.yml b/.github/workflows/validate-build.yml index 497ceac7..0cc79a16 100644 --- a/.github/workflows/validate-build.yml +++ b/.github/workflows/validate-build.yml @@ -28,6 +28,16 @@ jobs: with: dotnet-version: '6.0.x' + - name: Setup .NET 8.0 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Setup .NET 10.0 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '10.0.x' + - name: Setup .NET from global.json uses: actions/setup-dotnet@v3 with: diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f7dbaae0..b1dbbb64 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -38,7 +38,7 @@ "type": "func", "dependsOn": "build (AzureFunctionsApp)", "options": { - "cwd": "${workspaceFolder}/out/samples/bin/Debug/AzureFunctionsApp/net6.0" + "cwd": "${workspaceFolder}/out/samples/bin/Debug/AzureFunctionsApp/net8.0" }, "command": "host start", "isBackground": true, diff --git a/Directory.Packages.props b/Directory.Packages.props index a3e580b8..b3945014 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,23 +9,22 @@ - - - - - - - - - - + + + + + + + + + - - - + + + @@ -41,20 +40,20 @@ - - + + - - + + - - - - - + + + + + @@ -63,27 +62,28 @@ - - - - - + + + + + - - + + - + - - - + + + + - - + + diff --git a/global.json b/global.json index 4ac08fda..4b560e68 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + "version": "10.0.100", "rollForward": "latestFeature" }, "msbuild-sdks": { diff --git a/samples/AzureFunctionsApp/AzureFunctionsApp.csproj b/samples/AzureFunctionsApp/AzureFunctionsApp.csproj index 1e56f9fd..8531f38a 100644 --- a/samples/AzureFunctionsApp/AzureFunctionsApp.csproj +++ b/samples/AzureFunctionsApp/AzureFunctionsApp.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0 v4 Exe enable diff --git a/samples/AzureFunctionsUnitTests/AzureFunctionsApp.Tests.csproj b/samples/AzureFunctionsUnitTests/AzureFunctionsApp.Tests.csproj index faa8299a..e1e548ad 100644 --- a/samples/AzureFunctionsUnitTests/AzureFunctionsApp.Tests.csproj +++ b/samples/AzureFunctionsUnitTests/AzureFunctionsApp.Tests.csproj @@ -1,7 +1,7 @@  - net8.0 + net6.0;net8.0 enable enable diff --git a/samples/ConsoleApp/ConsoleApp.csproj b/samples/ConsoleApp/ConsoleApp.csproj index 36bad25c..5de1fbdf 100644 --- a/samples/ConsoleApp/ConsoleApp.csproj +++ b/samples/ConsoleApp/ConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net6.0;net8.0;net10.0 enable diff --git a/samples/ConsoleAppMinimal/ConsoleAppMinimal.csproj b/samples/ConsoleAppMinimal/ConsoleAppMinimal.csproj index 36bad25c..5de1fbdf 100644 --- a/samples/ConsoleAppMinimal/ConsoleAppMinimal.csproj +++ b/samples/ConsoleAppMinimal/ConsoleAppMinimal.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net6.0;net8.0;net10.0 enable diff --git a/samples/LargePayloadConsoleApp/LargePayloadConsoleApp.csproj b/samples/LargePayloadConsoleApp/LargePayloadConsoleApp.csproj index b0f2914c..c7ac5d2e 100644 --- a/samples/LargePayloadConsoleApp/LargePayloadConsoleApp.csproj +++ b/samples/LargePayloadConsoleApp/LargePayloadConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net8.0;net10.0 enable diff --git a/samples/ScheduleConsoleApp/ScheduleConsoleApp.csproj b/samples/ScheduleConsoleApp/ScheduleConsoleApp.csproj index 7efdf0fc..5c356d93 100644 --- a/samples/ScheduleConsoleApp/ScheduleConsoleApp.csproj +++ b/samples/ScheduleConsoleApp/ScheduleConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net8.0;net10.0 enable diff --git a/samples/ScheduleWebApp/ScheduleWebApp.csproj b/samples/ScheduleWebApp/ScheduleWebApp.csproj index 8206fa42..a505e3df 100644 --- a/samples/ScheduleWebApp/ScheduleWebApp.csproj +++ b/samples/ScheduleWebApp/ScheduleWebApp.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0;net10.0 enable enable true diff --git a/samples/WebAPI/WebAPI.csproj b/samples/WebAPI/WebAPI.csproj index 2ee98470..84680817 100644 --- a/samples/WebAPI/WebAPI.csproj +++ b/samples/WebAPI/WebAPI.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0;net10.0 enable enable true diff --git a/src/Client/AzureManaged/Client.AzureManaged.csproj b/src/Client/AzureManaged/Client.AzureManaged.csproj index 087f60f8..78fa3ad5 100644 --- a/src/Client/AzureManaged/Client.AzureManaged.csproj +++ b/src/Client/AzureManaged/Client.AzureManaged.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0;net10.0 Azure Managed extensions for the Durable Task Framework client. true diff --git a/src/Client/Grpc/Client.Grpc.csproj b/src/Client/Grpc/Client.Grpc.csproj index fe13b9df..a266287d 100644 --- a/src/Client/Grpc/Client.Grpc.csproj +++ b/src/Client/Grpc/Client.Grpc.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0;net10.0 The gRPC client for the Durable Task Framework. true diff --git a/src/Extensions/AzureBlobPayloads/AzureBlobPayloads.csproj b/src/Extensions/AzureBlobPayloads/AzureBlobPayloads.csproj index 58e039a5..0a524ed6 100644 --- a/src/Extensions/AzureBlobPayloads/AzureBlobPayloads.csproj +++ b/src/Extensions/AzureBlobPayloads/AzureBlobPayloads.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0;net10.0 Azure Blob Storage externalized payload support for Durable Task. Microsoft.DurableTask.Extensions.AzureBlobPayloads Microsoft.DurableTask diff --git a/src/Generators/DurableTaskSourceGenerator.cs b/src/Generators/DurableTaskSourceGenerator.cs index 4ad0eb2d..32821c93 100644 --- a/src/Generators/DurableTaskSourceGenerator.cs +++ b/src/Generators/DurableTaskSourceGenerator.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Immutable; using System.Diagnostics; using System.Text; using Microsoft.CodeAnalysis; @@ -15,7 +16,7 @@ namespace Microsoft.DurableTask.Generators /// Generator for DurableTask. /// [Generator] - public class DurableTaskSourceGenerator : ISourceGenerator + public class DurableTaskSourceGenerator : IIncrementalGenerator { /* Example input: * @@ -39,32 +40,150 @@ public class DurableTaskSourceGenerator : ISourceGenerator */ /// - public void Initialize(GeneratorInitializationContext context) + public void Initialize(IncrementalGeneratorInitializationContext context) { - context.RegisterForSyntaxNotifications(() => new DurableTaskSyntaxReceiver()); + // Create providers for DurableTask attributes + IncrementalValuesProvider durableTaskAttributes = context.SyntaxProvider + .CreateSyntaxProvider( + predicate: static (node, _) => node is AttributeSyntax, + transform: static (ctx, _) => GetDurableTaskTypeInfo(ctx)) + .Where(static info => info != null)!; + + // Create providers for Durable Functions + IncrementalValuesProvider durableFunctions = context.SyntaxProvider + .CreateSyntaxProvider( + predicate: static (node, _) => node is MethodDeclarationSyntax, + transform: static (ctx, _) => GetDurableFunction(ctx)) + .Where(static func => func != null)!; + + // Collect all results and check if Durable Functions is referenced + IncrementalValueProvider<(Compilation, ImmutableArray, ImmutableArray)> compilationAndTasks = + durableTaskAttributes.Collect() + .Combine(durableFunctions.Collect()) + .Combine(context.CompilationProvider) + .Select((x, _) => (x.Right, x.Left.Left, x.Left.Right)); + + // Generate the source + context.RegisterSourceOutput(compilationAndTasks, static (spc, source) => Execute(spc, source.Item1, source.Item2, source.Item3)); } - /// - public void Execute(GeneratorExecutionContext context) + static DurableTaskTypeInfo? GetDurableTaskTypeInfo(GeneratorSyntaxContext context) + { + AttributeSyntax attribute = (AttributeSyntax)context.Node; + + ITypeSymbol? attributeType = context.SemanticModel.GetTypeInfo(attribute.Name).Type; + if (attributeType?.ToString() != "Microsoft.DurableTask.DurableTaskAttribute") + { + return null; + } + + if (attribute.Parent is not AttributeListSyntax list || list.Parent is not ClassDeclarationSyntax classDeclaration) + { + return null; + } + + // Verify that the attribute is being used on a non-abstract class + if (classDeclaration.Modifiers.Any(SyntaxKind.AbstractKeyword)) + { + return null; + } + + if (context.SemanticModel.GetDeclaredSymbol(classDeclaration) is not ITypeSymbol classType) + { + return null; + } + + string className = classType.ToDisplayString(); + INamedTypeSymbol? taskType = null; + bool isActivity = false; + + INamedTypeSymbol? baseType = classType.BaseType; + while (baseType != null) + { + if (baseType.ContainingAssembly.Name == "Microsoft.DurableTask.Abstractions") + { + if (baseType.Name == "TaskActivity") + { + taskType = baseType; + isActivity = true; + break; + } + else if (baseType.Name == "TaskOrchestrator") + { + taskType = baseType; + isActivity = false; + break; + } + } + + baseType = baseType.BaseType; + } + + if (taskType == null || taskType.TypeParameters.Length <= 1) + { + return null; + } + + ITypeSymbol inputType = taskType.TypeArguments.First(); + ITypeSymbol outputType = taskType.TypeArguments.Last(); + + string taskName = classType.Name; + if (attribute.ArgumentList?.Arguments.Count > 0) + { + ExpressionSyntax expression = attribute.ArgumentList.Arguments[0].Expression; + taskName = context.SemanticModel.GetConstantValue(expression).ToString(); + } + + return new DurableTaskTypeInfo(className, taskName, inputType, outputType, isActivity); + } + + static DurableFunction? GetDurableFunction(GeneratorSyntaxContext context) + { + MethodDeclarationSyntax method = (MethodDeclarationSyntax)context.Node; + + if (DurableFunction.TryParse(context.SemanticModel, method, out DurableFunction? function)) + { + return function; + } + + return null; + } + + static void Execute( + SourceProductionContext context, + Compilation compilation, + ImmutableArray allTasks, + ImmutableArray allFunctions) { + if (allTasks.IsDefaultOrEmpty && allFunctions.IsDefaultOrEmpty) + { + return; + } + // This generator also supports Durable Functions for .NET isolated, but we only generate Functions-specific // code if we find the Durable Functions extension listed in the set of referenced assembly names. - bool isDurableFunctions = context.Compilation.ReferencedAssemblyNames.Any( + bool isDurableFunctions = compilation.ReferencedAssemblyNames.Any( assembly => assembly.Name.Equals("Microsoft.Azure.Functions.Worker.Extensions.DurableTask", StringComparison.OrdinalIgnoreCase)); - // Enumerate all the activities in the project - // the generator infrastructure will create a receiver and populate it - // we can retrieve the populated instance via the context - if (context.SyntaxContextReceiver is not DurableTaskSyntaxReceiver receiver) + // Separate tasks into orchestrators and activities + List orchestrators = new(); + List activities = new(); + + foreach (DurableTaskTypeInfo task in allTasks) { - // Unexpected receiver came back? - return; + if (task.IsActivity) + { + activities.Add(task); + } + else + { + orchestrators.Add(task); + } } - int found = receiver.Activities.Count + receiver.Orchestrators.Count + receiver.DurableFunctions.Count; + int found = activities.Count + orchestrators.Count + allFunctions.Length; if (found == 0) { - // Didn't find anything return; } @@ -92,14 +211,14 @@ public static class GeneratedDurableTaskExtensions if (isDurableFunctions) { // Generate a singleton orchestrator object instance that can be reused for all invocations. - foreach (DurableTaskTypeInfo orchestrator in receiver.Orchestrators) + foreach (DurableTaskTypeInfo orchestrator in orchestrators) { sourceBuilder.AppendLine($@" static readonly ITaskOrchestrator singleton{orchestrator.TaskName} = new {orchestrator.TypeName}();"); } } - foreach (DurableTaskTypeInfo orchestrator in receiver.Orchestrators) + foreach (DurableTaskTypeInfo orchestrator in orchestrators) { if (isDurableFunctions) { @@ -111,7 +230,7 @@ public static class GeneratedDurableTaskExtensions AddSubOrchestratorCallMethod(sourceBuilder, orchestrator); } - foreach (DurableTaskTypeInfo activity in receiver.Activities) + foreach (DurableTaskTypeInfo activity in activities) { AddActivityCallMethod(sourceBuilder, activity); @@ -123,7 +242,7 @@ public static class GeneratedDurableTaskExtensions } // Activity function triggers are supported for code-gen (but not orchestration triggers) - IEnumerable activityTriggers = receiver.DurableFunctions.Where( + IEnumerable activityTriggers = allFunctions.Where( df => df.Kind == DurableFunctionKind.Activity); foreach (DurableFunction function in activityTriggers) { @@ -132,7 +251,7 @@ public static class GeneratedDurableTaskExtensions if (isDurableFunctions) { - if (receiver.Activities.Count > 0) + if (activities.Count > 0) { // Functions-specific helper class, which is only needed when // using the class-based syntax. @@ -144,8 +263,8 @@ public static class GeneratedDurableTaskExtensions // ASP.NET Core-specific service registration methods AddRegistrationMethodForAllTasks( sourceBuilder, - receiver.Orchestrators, - receiver.Activities); + orchestrators, + activities); } sourceBuilder.AppendLine(" }").AppendLine("}"); @@ -273,124 +392,14 @@ internal static DurableTaskRegistry AddAllGeneratedTasks(this DurableTaskRegistr }}"); } - class DurableTaskSyntaxReceiver : ISyntaxContextReceiver - { - readonly List orchestrators = new(); - readonly List activities = new(); - readonly List durableFunctions = new(); - - public IReadOnlyList Orchestrators => this.orchestrators; - public IReadOnlyList Activities => this.activities; - public IReadOnlyList DurableFunctions => this.durableFunctions; - - public void OnVisitSyntaxNode(GeneratorSyntaxContext context) - { - // Check for Azure Functions syntax - if (context.Node is MethodDeclarationSyntax method && - DurableFunction.TryParse(context.SemanticModel, method, out DurableFunction? function) && - function != null) - { - Debug.WriteLine($"Adding {function.Kind} function '{function.Name}'"); - this.durableFunctions.Add(function); - return; - } - - // Check for class-based syntax - if (context.Node is not AttributeSyntax attribute) - { - return; - } - - ITypeSymbol? attributeType = context.SemanticModel.GetTypeInfo(attribute.Name).Type; - if (attributeType?.ToString() != "Microsoft.DurableTask.DurableTaskAttribute") - { - return; - } - - if (attribute.Parent is not AttributeListSyntax list || list.Parent is not ClassDeclarationSyntax classDeclaration) - { - // TODO: Issue a warning that the [DurableTask] attribute was found in a place it wasn't expected. - return; - } - - // Verify that the attribute is being used on a non-abstract class - if (classDeclaration.Modifiers.Any(SyntaxKind.AbstractKeyword)) - { - // TODO: Issue a warning that you can't use [DurableTask] on abstract classes - return; - } - - if (context.SemanticModel.GetDeclaredSymbol(classDeclaration) is not ITypeSymbol classType) - { - // Invalid type declaration? - return; - } - - string className = classType.ToDisplayString(); - - List? taskList = null; - INamedTypeSymbol? taskType = null; - - INamedTypeSymbol? baseType = classType.BaseType; - while (baseType != null) - { - if (baseType.ContainingAssembly.Name == "Microsoft.DurableTask.Abstractions") - { - if (baseType.Name == "TaskActivity") - { - taskList = this.activities; - taskType = baseType; - break; - } - else if (baseType.Name == "TaskOrchestrator") - { - taskList = this.orchestrators; - taskType = baseType; - break; - } - } - - baseType = baseType.BaseType; - } - - if (taskList == null || taskType == null) - { - // TODO: Issue a warning that [DurableTask] can only be used with activity and orchestration-derived classes - return; - } - - if (taskType.TypeParameters.Length <= 1) - { - // We expect that the base class will always have at least two type parameters - return; - } - - ITypeSymbol inputType = taskType.TypeArguments.First(); - ITypeSymbol outputType = taskType.TypeArguments.Last(); - - // By default, the task name is the class name. - string taskName = classType.Name; // TODO: What if the class has generic type parameters? - if (attribute.ArgumentList?.Arguments.Count > 0) - { - ExpressionSyntax expression = attribute.ArgumentList.Arguments[0].Expression; - taskName = context.SemanticModel.GetConstantValue(expression).ToString(); - } - - taskList.Add(new DurableTaskTypeInfo( - className, - taskName, - inputType, - outputType)); - } - } - class DurableTaskTypeInfo { public DurableTaskTypeInfo( string taskType, string taskName, ITypeSymbol? inputType, - ITypeSymbol? outputType) + ITypeSymbol? outputType, + bool isActivity) { this.TypeName = taskType; this.TaskName = taskName; @@ -402,6 +411,7 @@ public DurableTaskTypeInfo( } this.OutputType = GetRenderedTypeExpression(outputType); + this.IsActivity = isActivity; } public string TypeName { get; } @@ -409,6 +419,7 @@ public DurableTaskTypeInfo( public string InputType { get; } public string InputParameter { get; } public string OutputType { get; } + public bool IsActivity { get; } static string GetRenderedTypeExpression(ITypeSymbol? symbol) { diff --git a/src/Grpc/Grpc.csproj b/src/Grpc/Grpc.csproj index 4839af20..e433e01e 100644 --- a/src/Grpc/Grpc.csproj +++ b/src/Grpc/Grpc.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0;net10.0 The gRPC Protobuf .NET services for Durable Task Framework. @@ -13,7 +13,7 @@ - + diff --git a/src/InProcessTestHost/InProcessTestHost.csproj b/src/InProcessTestHost/InProcessTestHost.csproj index 8839ef0f..45c263e7 100644 --- a/src/InProcessTestHost/InProcessTestHost.csproj +++ b/src/InProcessTestHost/InProcessTestHost.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 Microsoft.DurableTask.Testing Microsoft.DurableTask.InProcessTestHost Microsoft.DurableTask.InProcessTestHost diff --git a/src/ScheduledTasks/ScheduledTasks.csproj b/src/ScheduledTasks/ScheduledTasks.csproj index 7283fb12..5971a560 100644 --- a/src/ScheduledTasks/ScheduledTasks.csproj +++ b/src/ScheduledTasks/ScheduledTasks.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0;net10.0 Durable Task Scheduled Tasks Client true preview.1 diff --git a/src/Worker/AzureManaged/Worker.AzureManaged.csproj b/src/Worker/AzureManaged/Worker.AzureManaged.csproj index 890da014..0eea5a5d 100644 --- a/src/Worker/AzureManaged/Worker.AzureManaged.csproj +++ b/src/Worker/AzureManaged/Worker.AzureManaged.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0;net10.0 Azure Managed extensions for the Durable Task Framework worker. true diff --git a/src/Worker/Grpc/Worker.Grpc.csproj b/src/Worker/Grpc/Worker.Grpc.csproj index 991fef8f..52ea3954 100644 --- a/src/Worker/Grpc/Worker.Grpc.csproj +++ b/src/Worker/Grpc/Worker.Grpc.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0;net10.0 The gRPC worker for the Durable Task Framework. true diff --git a/test/Abstractions.Tests/Abstractions.Tests.csproj b/test/Abstractions.Tests/Abstractions.Tests.csproj index e4cf7da9..1e10da3c 100644 --- a/test/Abstractions.Tests/Abstractions.Tests.csproj +++ b/test/Abstractions.Tests/Abstractions.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Abstractions.Tests/PageableTests.cs b/test/Abstractions.Tests/PageableTests.cs index 8fb03645..9b20d201 100644 --- a/test/Abstractions.Tests/PageableTests.cs +++ b/test/Abstractions.Tests/PageableTests.cs @@ -23,7 +23,7 @@ public async Task Create_Func_Enumerable() List expected = CreateSource(15); AsyncPageable pageable = CreatePageable(expected, counter); - List actual = await pageable.ToListAsync(); + List actual = await pageable.ToListAsync(CancellationToken.None); actual.Should().BeEquivalentTo(expected); counter.Callbacks.Should().Be(5); // 15 / 3 = 5. } @@ -41,7 +41,7 @@ public async Task Create_Func_AsPages(int? start, int? pageSize) AsyncPageable pageable = CreatePageable(source, counter); List expected = source.Skip(start ?? 0).ToList(); - List> pages = await pageable.AsPages(start?.ToString(), pageSize).ToListAsync(); + List> pages = await pageable.AsPages(start?.ToString(), pageSize).ToListAsync(CancellationToken.None); pages.Should().HaveCount((int)Math.Ceiling((15.0 - (start ?? 0)) / (pageSize ?? 3))); pages.SelectMany(x => x.Values).Should().BeEquivalentTo(expected); counter.Callbacks.Should().Be(pages.Count); diff --git a/test/Analyzers.Tests/Analyzers.Tests.csproj b/test/Analyzers.Tests/Analyzers.Tests.csproj index a43fbdd0..e93d9c6d 100644 --- a/test/Analyzers.Tests/Analyzers.Tests.csproj +++ b/test/Analyzers.Tests/Analyzers.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Benchmarks/Benchmarks.csproj b/test/Benchmarks/Benchmarks.csproj index 58504ddf..b7657682 100644 --- a/test/Benchmarks/Benchmarks.csproj +++ b/test/Benchmarks/Benchmarks.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0;net10.0 Exe Benchmarks @@ -11,7 +11,6 @@ - diff --git a/test/Client/AzureManaged.Tests/Client.AzureManaged.Tests.csproj b/test/Client/AzureManaged.Tests/Client.AzureManaged.Tests.csproj index 4d43922f..77928b51 100644 --- a/test/Client/AzureManaged.Tests/Client.AzureManaged.Tests.csproj +++ b/test/Client/AzureManaged.Tests/Client.AzureManaged.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0;net10.0 diff --git a/test/Client/Core.Tests/Client.Tests.csproj b/test/Client/Core.Tests/Client.Tests.csproj index 29966adc..a8790ba5 100644 --- a/test/Client/Core.Tests/Client.Tests.csproj +++ b/test/Client/Core.Tests/Client.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Client/Grpc.Tests/Client.Grpc.Tests.csproj b/test/Client/Grpc.Tests/Client.Grpc.Tests.csproj index 6d3dba79..41c0667a 100644 --- a/test/Client/Grpc.Tests/Client.Grpc.Tests.csproj +++ b/test/Client/Grpc.Tests/Client.Grpc.Tests.csproj @@ -1,7 +1,7 @@  - net6.0;net48 + net6.0;net8.0;net10.0;net48 diff --git a/test/Client/OrchestrationServiceClientShim.Tests/Client.OrchestrationServiceClientShim.Tests.csproj b/test/Client/OrchestrationServiceClientShim.Tests/Client.OrchestrationServiceClientShim.Tests.csproj index f24130cb..c0899d09 100644 --- a/test/Client/OrchestrationServiceClientShim.Tests/Client.OrchestrationServiceClientShim.Tests.csproj +++ b/test/Client/OrchestrationServiceClientShim.Tests/Client.OrchestrationServiceClientShim.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableEntityClientTests.cs b/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableEntityClientTests.cs index a4c32f77..55c6e0a2 100644 --- a/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableEntityClientTests.cs +++ b/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableEntityClientTests.cs @@ -120,7 +120,7 @@ public async Task GetAllEntitiesAsync_NoFilter_ReturnsExpectedResult() } ShimDurableEntityClient client = this.CreateEntityClient(); - List actualEntities = await client.GetAllEntitiesAsync().ToListAsync(); + List actualEntities = await client.GetAllEntitiesAsync().ToListAsync(CancellationToken.None); using AssertionScope scope = new(); actualEntities.Should().HaveCount(entities.Count); @@ -164,7 +164,7 @@ public async Task GetAllEntitiesAsync_WithFilter_ReturnsExpectedResult() } ShimDurableEntityClient client = this.CreateEntityClient(); - List actualEntities = await client.GetAllEntitiesAsync(query).ToListAsync(); + List actualEntities = await client.GetAllEntitiesAsync(query).ToListAsync(CancellationToken.None); using AssertionScope scope = new(); actualEntities.Should().HaveCount(entities.Count); @@ -207,7 +207,7 @@ public async Task GetAllEntitiesAsyncOfT_NoFilter_ReturnsExpectedResult() } ShimDurableEntityClient client = this.CreateEntityClient(); - List> actualEntities = await client.GetAllEntitiesAsync().ToListAsync(); + List> actualEntities = await client.GetAllEntitiesAsync().ToListAsync(CancellationToken.None); using AssertionScope scope = new(); actualEntities.Should().HaveCount(entities.Count); @@ -251,7 +251,7 @@ public async Task GetAllEntitiesAsyncOfT_WithFilter_ReturnsExpectedResult() } ShimDurableEntityClient client = this.CreateEntityClient(); - List> actualEntities = await client.GetAllEntitiesAsync(query).ToListAsync(); + List> actualEntities = await client.GetAllEntitiesAsync(query).ToListAsync(CancellationToken.None); using AssertionScope scope = new(); actualEntities.Should().HaveCount(entities.Count); @@ -274,7 +274,7 @@ public async Task GetEntityAsync_Success(bool includeState) entity.Should().NotBeNull(); VerifyEntity(entity!, expected); entity!.IncludesState.Should().Be(includeState); - + if (includeState) { entity!.State.Value.Should().Be("\"state\""); @@ -294,7 +294,7 @@ public async Task GetEntityAsyncOfT_Success(bool includeState) entity.Should().NotBeNull(); VerifyEntity(entity!, expected); entity!.IncludesState.Should().Be(includeState); - + if (includeState) { entity!.State.Should().Be("state"); diff --git a/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableTaskClientTests.cs b/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableTaskClientTests.cs index 588f59ac..0d14b396 100644 --- a/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableTaskClientTests.cs +++ b/test/Client/OrchestrationServiceClientShim.Tests/ShimDurableTaskClientTests.cs @@ -151,7 +151,7 @@ public async Task GetInstances_Results(bool getInputs) }; // act - List result = await this.client.GetAllInstancesAsync(query).ToListAsync(); + List result = await this.client.GetAllInstancesAsync(query).ToListAsync(CancellationToken.None); // assert this.orchestrationClient.VerifyAll(); @@ -373,7 +373,7 @@ public async Task RestartAsync_EndToEnd(bool restartWithNewInstanceId) // Verify the captured message details capturedMessage.Should().NotBeNull(); capturedMessage!.Event.Should().BeOfType(); - + var startedEvent = (ExecutionStartedEvent)capturedMessage.Event; startedEvent.Name.Should().Be(orchestratorName); startedEvent.Input.Should().Be(serializedInput); diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index 911567b5..8ee08d1d 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -12,7 +12,7 @@ - + diff --git a/test/Generators.Tests/Generators.Tests.csproj b/test/Generators.Tests/Generators.Tests.csproj index f805fecb..55aba3ea 100644 --- a/test/Generators.Tests/Generators.Tests.csproj +++ b/test/Generators.Tests/Generators.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0;net10.0 diff --git a/test/Generators.Tests/Utils/CSharpSourceGeneratorVerifier.cs b/test/Generators.Tests/Utils/CSharpSourceGeneratorVerifier.cs index 98233b8d..331ebd14 100644 --- a/test/Generators.Tests/Utils/CSharpSourceGeneratorVerifier.cs +++ b/test/Generators.Tests/Utils/CSharpSourceGeneratorVerifier.cs @@ -10,17 +10,17 @@ namespace Microsoft.DurableTask.Generators.Tests.Utils; // Mostly copy/pasted from the Microsoft Source Generators testing documentation -public static class CSharpSourceGeneratorVerifier where TSourceGenerator : ISourceGenerator, new() +public static class CSharpSourceGeneratorVerifier where TSourceGenerator : IIncrementalGenerator, new() { public class Test : CSharpSourceGeneratorTest { public Test() { - // See https://www.nuget.org/packages/Microsoft.NETCore.App.Ref/6.0.0 + // See https://www.nuget.org/packages/Microsoft.NETCore.App.Ref/8.0.22 this.ReferenceAssemblies = new ReferenceAssemblies( - targetFramework: "net6.0", - referenceAssemblyPackage: new PackageIdentity("Microsoft.NETCore.App.Ref", "6.0.0"), - referenceAssemblyPath: Path.Combine("ref", "net6.0")); + targetFramework: "net8.0", + referenceAssemblyPackage: new PackageIdentity("Microsoft.NETCore.App.Ref", "8.0.22"), + referenceAssemblyPath: Path.Combine("ref", "net8.0")); } public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.CSharp9; diff --git a/test/Generators.Tests/Utils/TestHelpers.cs b/test/Generators.Tests/Utils/TestHelpers.cs index 651d27b4..8b53462d 100644 --- a/test/Generators.Tests/Utils/TestHelpers.cs +++ b/test/Generators.Tests/Utils/TestHelpers.cs @@ -15,7 +15,7 @@ public static Task RunTestAsync( string expectedFileName, string inputSource, string expectedOutputSource, - bool isDurableFunctions) where TSourceGenerator : ISourceGenerator, new() + bool isDurableFunctions) where TSourceGenerator : IIncrementalGenerator, new() { CSharpSourceGeneratorVerifier.Test test = new() { @@ -43,7 +43,7 @@ public static Task RunTestAsync( // Assembly functionsWorkerCore = typeof(FunctionContext).Assembly; // test.TestState.AdditionalReferences.Add(functionsWorkerCore); - + // Assembly durableExtension = typeof(OrchestrationTriggerAttribute).Assembly; // test.TestState.AdditionalReferences.Add(durableExtension); @@ -134,7 +134,7 @@ static bool IsValueType(string typeExpression) Type? runtimeType = Type.GetType(typeExpression, throwOnError: false); return runtimeType != null && runtimeType.IsValueType; } - }; + } if (inputType.StartsWith("(") || inputType.EndsWith('?') || IsValueType(inputType)) { diff --git a/test/Grpc.IntegrationTests/Grpc.IntegrationTests.csproj b/test/Grpc.IntegrationTests/Grpc.IntegrationTests.csproj index 88ab0633..08ec22e1 100644 --- a/test/Grpc.IntegrationTests/Grpc.IntegrationTests.csproj +++ b/test/Grpc.IntegrationTests/Grpc.IntegrationTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Grpc.IntegrationTests/GrpcDurableTaskClientIntegrationTests.cs b/test/Grpc.IntegrationTests/GrpcDurableTaskClientIntegrationTests.cs index 63f92ef3..2d5df336 100644 --- a/test/Grpc.IntegrationTests/GrpcDurableTaskClientIntegrationTests.cs +++ b/test/Grpc.IntegrationTests/GrpcDurableTaskClientIntegrationTests.cs @@ -104,14 +104,14 @@ await ForEachOrchestrationAsync( AsyncPageable pageable = server.Client.GetAllInstancesAsync(query); await ForEachOrchestrationAsync(x => server.Client.WaitForInstanceStartAsync(x, default)); - List metadata = await pageable.ToListAsync(); + List metadata = await pageable.ToListAsync(CancellationToken.None); metadata.Should().HaveCount(2) .And.AllSatisfy(m => AssertMetadata(m, OrchestrationRuntimeStatus.Running)) .And.NotContain(x => string.Equals(x.InstanceId, notIncluded, StringComparison.OrdinalIgnoreCase)); await ForEachOrchestrationAsync(x => server.Client.RaiseEventAsync(x, "event", default)); await ForEachOrchestrationAsync(x => server.Client.WaitForInstanceCompletionAsync(x, default)); - metadata = await pageable.ToListAsync(); + metadata = await pageable.ToListAsync(CancellationToken.None); metadata.Should().HaveCount(2) .And.AllSatisfy(m => AssertMetadata(m, OrchestrationRuntimeStatus.Completed)) .And.NotContain(x => string.Equals(x.InstanceId, notIncluded, StringComparison.OrdinalIgnoreCase)); @@ -130,12 +130,12 @@ await server.Client.ScheduleNewOrchestrationInstanceAsync( } AsyncPageable pageable = server.Client.GetAllInstancesAsync(query); - List> pages = await pageable.AsPages(pageSizeHint: 5).ToListAsync(); + List> pages = await pageable.AsPages(pageSizeHint: 5).ToListAsync(CancellationToken.None); pages.Should().HaveCount(5); pages.ForEach(p => p.Values.Should().HaveCount(p.ContinuationToken is null ? 1 : 5)); List> resumedPages = await pageable.AsPages( - pages[1].ContinuationToken, pageSizeHint: 4).ToListAsync(); + pages[1].ContinuationToken, pageSizeHint: 4).ToListAsync(CancellationToken.None); resumedPages.Should().HaveCount(3); List left = resumedPages.SelectMany(p => p.Values).ToList(); @@ -145,7 +145,7 @@ await server.Client.ScheduleNewOrchestrationInstanceAsync( cfg => cfg.Including(x => x.InstanceId).Including(x => x.CreatedAt) .Using()); - Page page = await pageable.AsPages(pageSizeHint: 10).FirstAsync(); + Page page = await pageable.AsPages(pageSizeHint: 10).FirstAsync(CancellationToken.None); page.Values.Should().HaveCount(10); page.ContinuationToken.Should().NotBeNull(); } @@ -240,7 +240,7 @@ public async Task RestartAsync_EndToEnd(bool restartWithNewInstanceId) await server.Client.WaitForInstanceStartAsync(originalInstanceId, default); await server.Client.RaiseEventAsync(originalInstanceId, "event", default); await server.Client.WaitForInstanceCompletionAsync(originalInstanceId, cts.Token); - + // Verify the original orchestration completed OrchestrationMetadata? originalMetadata = await server.Client.GetInstanceAsync(originalInstanceId, true); originalMetadata.Should().NotBeNull(); @@ -261,7 +261,7 @@ public async Task RestartAsync_EndToEnd(bool restartWithNewInstanceId) // Complete the restarted orchestration await server.Client.RaiseEventAsync(restartedInstanceId, "event"); - + using var completionCts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); await server.Client.WaitForInstanceCompletionAsync(restartedInstanceId, completionCts.Token); diff --git a/test/Grpc.IntegrationTests/OrchestrationPatterns.cs b/test/Grpc.IntegrationTests/OrchestrationPatterns.cs index 500a1952..45fbd490 100644 --- a/test/Grpc.IntegrationTests/OrchestrationPatterns.cs +++ b/test/Grpc.IntegrationTests/OrchestrationPatterns.cs @@ -329,7 +329,7 @@ public async Task ActivityFanOut() Assert.Equal(OrchestrationRuntimeStatus.Completed, metadata.RuntimeStatus); string[] expected = new[] { "9", "8", "7", "6", "5", "4", "3", "2", "1", "0" }; - Assert.Equal(expected, metadata.ReadOutputAs()); + Assert.Equal((IEnumerable)expected, metadata.ReadOutputAs()); } [Theory] diff --git a/test/Grpc.IntegrationTests/PageableIntegrationTests.cs b/test/Grpc.IntegrationTests/PageableIntegrationTests.cs index 6d8d0727..c05010cf 100644 --- a/test/Grpc.IntegrationTests/PageableIntegrationTests.cs +++ b/test/Grpc.IntegrationTests/PageableIntegrationTests.cs @@ -41,7 +41,7 @@ public async Task PageableActivity_Enumerates() { int pageSize = input?.PageSize ?? 3; Page CreatePage(string? next) - => new (Enumerable.Range(0, pageSize).Select(x => $"item_{x}").ToList(), next); + => new(Enumerable.Range(0, pageSize).Select(x => $"item_{x}").ToList(), next); Page? page = input?.Continuation switch { null => CreatePage("1"), @@ -61,7 +61,7 @@ static async Task PageableOrchestrationAsync(TaskOrchestrationContext conte nameof(PageableActivityAsync), new PageRequest(continuation))!; }); - return await pageable.CountAsync(); + return await pageable.CountAsync(CancellationToken.None); } record PageRequest(string? Continuation, int? PageSize = null); diff --git a/test/InProcessTestHost.Tests/InProcessTestHost.Tests.csproj b/test/InProcessTestHost.Tests/InProcessTestHost.Tests.csproj index 479d88a1..e2dbbe5e 100644 --- a/test/InProcessTestHost.Tests/InProcessTestHost.Tests.csproj +++ b/test/InProcessTestHost.Tests/InProcessTestHost.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net6.0;net8.0;net10.0 enable enable diff --git a/test/ScheduledTasks.Tests/ScheduledTasks.Tests.csproj b/test/ScheduledTasks.Tests/ScheduledTasks.Tests.csproj index 33726a62..3f788c51 100644 --- a/test/ScheduledTasks.Tests/ScheduledTasks.Tests.csproj +++ b/test/ScheduledTasks.Tests/ScheduledTasks.Tests.csproj @@ -2,7 +2,7 @@ - net6.0 + net8.0;net10.0 enable enable false @@ -10,7 +10,6 @@ - diff --git a/test/Shared/AzureManaged.Tests/Shared.AzureManaged.Tests.csproj b/test/Shared/AzureManaged.Tests/Shared.AzureManaged.Tests.csproj index f9822995..efd29a70 100644 --- a/test/Shared/AzureManaged.Tests/Shared.AzureManaged.Tests.csproj +++ b/test/Shared/AzureManaged.Tests/Shared.AzureManaged.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/TestHelpers/TestHelpers.csproj b/test/TestHelpers/TestHelpers.csproj index 55514082..f522d518 100644 --- a/test/TestHelpers/TestHelpers.csproj +++ b/test/TestHelpers/TestHelpers.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;net10.0;netstandard2.0 diff --git a/test/Worker/AzureManaged.Tests/Worker.AzureManaged.Tests.csproj b/test/Worker/AzureManaged.Tests/Worker.AzureManaged.Tests.csproj index 4a5a7cc1..fc933611 100644 --- a/test/Worker/AzureManaged.Tests/Worker.AzureManaged.Tests.csproj +++ b/test/Worker/AzureManaged.Tests/Worker.AzureManaged.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0;net10.0 diff --git a/test/Worker/Core.Tests/Worker.Tests.csproj b/test/Worker/Core.Tests/Worker.Tests.csproj index 736986d4..b0fcd6bc 100644 --- a/test/Worker/Core.Tests/Worker.Tests.csproj +++ b/test/Worker/Core.Tests/Worker.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0;net10.0 diff --git a/test/Worker/Grpc.Tests/Worker.Grpc.Tests.csproj b/test/Worker/Grpc.Tests/Worker.Grpc.Tests.csproj index b3c7f9c1..32d83f45 100644 --- a/test/Worker/Grpc.Tests/Worker.Grpc.Tests.csproj +++ b/test/Worker/Grpc.Tests/Worker.Grpc.Tests.csproj @@ -1,7 +1,7 @@ - net6.0;net48 + net8.0;net10.0;net48 @@ -12,7 +12,7 @@ - +