diff --git a/src/Client/Grpc/GrpcDurableTaskClient.cs b/src/Client/Grpc/GrpcDurableTaskClient.cs index 398bc6e6..92292218 100644 --- a/src/Client/Grpc/GrpcDurableTaskClient.cs +++ b/src/Client/Grpc/GrpcDurableTaskClient.cs @@ -124,12 +124,9 @@ public override async Task ScheduleNewOrchestrationInstanceAsync( } // Set orchestration ID reuse policy for deduplication support - // Note: This requires the protobuf to support OrchestrationIdReusePolicy field - // If the protobuf doesn't support it yet, this will need to be updated when the protobuf is updated - if (options?.DedupeStatuses != null && options.DedupeStatuses.Count > 0) - { - // Parse and validate all status strings to enum first - ImmutableHashSet dedupeStatuses = options.DedupeStatuses + ImmutableHashSet dedupeStatuses = options?.DedupeStatuses is null + ? [] + : [.. options.DedupeStatuses .Select(s => { if (!System.Enum.TryParse(s, ignoreCase: true, out OrchestrationRuntimeStatus status)) @@ -139,17 +136,11 @@ public override async Task ScheduleNewOrchestrationInstanceAsync( } return status; - }).ToImmutableHashSet(); - - // Convert dedupe statuses to protobuf statuses and create reuse policy - IEnumerable dedupeStatusesProto = dedupeStatuses.Select(s => s.ToGrpcStatus()); - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatusesProto); + })]; - if (policy != null) - { - request.OrchestrationIdReusePolicy = policy; - } - } + // Convert dedupe statuses to protobuf statuses and create reuse policy + IEnumerable dedupeStatusesProto = dedupeStatuses.Select(s => s.ToGrpcStatus()); + request.OrchestrationIdReusePolicy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatusesProto); using Activity? newActivity = TraceHelper.StartActivityForNewOrchestration(request); diff --git a/src/Client/Grpc/ProtoUtils.cs b/src/Client/Grpc/ProtoUtils.cs index f307f43f..1a83d1f2 100644 --- a/src/Client/Grpc/ProtoUtils.cs +++ b/src/Client/Grpc/ProtoUtils.cs @@ -13,18 +13,22 @@ namespace Microsoft.DurableTask.Client.Grpc; public static class ProtoUtils { /// - /// Gets the terminal orchestration statuses that are commonly used for deduplication. + /// Gets an array of all orchestration statuses. /// These are the statuses that can be used in OrchestrationIdReusePolicy. /// - /// An immutable array of terminal orchestration statuses. - public static ImmutableArray GetTerminalStatuses() + /// An immutable array of all orchestration statuses. + public static ImmutableArray GetAllStatuses() { -#pragma warning disable CS0618 // Type or member is obsolete - Canceled is intentionally included for compatibility +#pragma warning disable CS0618 // Type or member is obsolete - Canceled is intentionally included for compatibility + // compatibility with what? return ImmutableArray.Create( P.OrchestrationStatus.Completed, P.OrchestrationStatus.Failed, - P.OrchestrationStatus.Terminated, - P.OrchestrationStatus.Canceled); + P.OrchestrationStatus.Terminated, + P.OrchestrationStatus.Canceled, + P.OrchestrationStatus.Pending, + P.OrchestrationStatus.Running, + P.OrchestrationStatus.Suspended); #pragma warning restore CS0618 } @@ -33,28 +37,27 @@ public static class ProtoUtils /// with replaceable statuses (statuses that CAN be replaced). /// /// The orchestration statuses that should NOT be replaced. These are statuses for which an exception should be thrown if an orchestration already exists. - /// An OrchestrationIdReusePolicy with replaceable statuses set, or null if all terminal statuses are dedupe statuses. + /// An OrchestrationIdReusePolicy with replaceable statuses set. /// /// The policy uses "replaceableStatus" - these are statuses that CAN be replaced. /// dedupeStatuses are statuses that should NOT be replaced. - /// So replaceableStatus = all terminal statuses MINUS dedupeStatuses. + /// So replaceableStatus = all statuses MINUS dedupeStatuses. /// - public static P.OrchestrationIdReusePolicy? ConvertDedupeStatusesToReusePolicy( + public static P.OrchestrationIdReusePolicy ConvertDedupeStatusesToReusePolicy( IEnumerable? dedupeStatuses) { - ImmutableArray terminalStatuses = GetTerminalStatuses(); + ImmutableArray statuses = GetAllStatuses(); ImmutableHashSet dedupeStatusSet = dedupeStatuses?.ToImmutableHashSet() ?? ImmutableHashSet.Empty; P.OrchestrationIdReusePolicy policy = new(); - // Add terminal statuses that are NOT in dedupeStatuses as replaceable - foreach (P.OrchestrationStatus terminalStatus in terminalStatuses.Where(status => !dedupeStatusSet.Contains(status))) + // Add statuses that are NOT in dedupeStatuses as replaceable + foreach (P.OrchestrationStatus status in statuses.Where(status => !dedupeStatusSet.Contains(status))) { - policy.ReplaceableStatus.Add(terminalStatus); + policy.ReplaceableStatus.Add(status); } - // Only return policy if we have replaceable statuses - return policy.ReplaceableStatus.Count > 0 ? policy : null; + return policy; } /// @@ -62,26 +65,21 @@ public static class ProtoUtils /// (statuses that should NOT be replaced). /// /// The OrchestrationIdReusePolicy containing replaceable statuses. - /// An array of orchestration statuses that should NOT be replaced, or null if all terminal statuses are replaceable. + /// An array of orchestration statuses that should NOT be replaced, or null if all statuses are replaceable. /// /// The policy uses "replaceableStatus" - these are statuses that CAN be replaced. /// dedupeStatuses are statuses that should NOT be replaced (should throw exception). - /// So dedupeStatuses = all terminal statuses MINUS replaceableStatus. + /// So dedupeStatuses = all statuses MINUS replaceableStatus. /// public static P.OrchestrationStatus[]? ConvertReusePolicyToDedupeStatuses( - P.OrchestrationIdReusePolicy? policy) + P.OrchestrationIdReusePolicy policy) { - if (policy == null || policy.ReplaceableStatus.Count == 0) - { - return null; - } - - ImmutableArray terminalStatuses = GetTerminalStatuses(); + ImmutableArray allStatuses = GetAllStatuses(); ImmutableHashSet replaceableStatusSet = policy.ReplaceableStatus.ToImmutableHashSet(); - // Calculate dedupe statuses = terminal statuses - replaceable statuses - P.OrchestrationStatus[] dedupeStatuses = terminalStatuses - .Where(terminalStatus => !replaceableStatusSet.Contains(terminalStatus)) + // Calculate dedupe statuses = all statuses - replaceable statuses + P.OrchestrationStatus[] dedupeStatuses = allStatuses + .Where(status => !replaceableStatusSet.Contains(status)) .ToArray(); // Only return if there are dedupe statuses diff --git a/src/InProcessTestHost/Sidecar/Grpc/TaskHubGrpcServer.cs b/src/InProcessTestHost/Sidecar/Grpc/TaskHubGrpcServer.cs index bbb162c3..ca2207f4 100644 --- a/src/InProcessTestHost/Sidecar/Grpc/TaskHubGrpcServer.cs +++ b/src/InProcessTestHost/Sidecar/Grpc/TaskHubGrpcServer.cs @@ -208,7 +208,7 @@ async Task WaitForWorkItemClientConnection() // Convert OrchestrationIdReusePolicy to dedupeStatuses // The policy uses "replaceableStatus" - these are statuses that CAN be replaced // dedupeStatuses are statuses that should NOT be replaced (should throw exception) - // So dedupeStatuses = all terminal statuses MINUS replaceableStatus + // So dedupeStatuses = all statuses MINUS replaceableStatus OrchestrationStatus[]? dedupeStatuses = null; P.OrchestrationStatus[]? dedupeStatusesProto = ProtoUtils.ConvertReusePolicyToDedupeStatuses(request.OrchestrationIdReusePolicy); if (dedupeStatusesProto != null) diff --git a/test/Client/Grpc.Tests/ProtoUtilsTests.cs b/test/Client/Grpc.Tests/ProtoUtilsTests.cs index 4db7a884..ee571e3a 100644 --- a/test/Client/Grpc.Tests/ProtoUtilsTests.cs +++ b/test/Client/Grpc.Tests/ProtoUtilsTests.cs @@ -9,100 +9,111 @@ namespace Microsoft.DurableTask.Client.Grpc.Tests; public class ProtoUtilsTests { [Fact] - public void GetTerminalStatuses_ReturnsExpectedStatuses() + public void GetAllStatuses_ReturnsExpectedStatuses() { // Act - ImmutableArray terminalStatuses = ProtoUtils.GetTerminalStatuses(); + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); // Assert - terminalStatuses.Should().HaveCount(4); - terminalStatuses.Should().Contain(P.OrchestrationStatus.Completed); - terminalStatuses.Should().Contain(P.OrchestrationStatus.Failed); - terminalStatuses.Should().Contain(P.OrchestrationStatus.Terminated); + allStatuses.Should().HaveCount(7); + allStatuses.Should().Contain(P.OrchestrationStatus.Completed); + allStatuses.Should().Contain(P.OrchestrationStatus.Failed); + allStatuses.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete - terminalStatuses.Should().Contain(P.OrchestrationStatus.Canceled); + allStatuses.Should().Contain(P.OrchestrationStatus.Canceled); + allStatuses.Should().Contain(P.OrchestrationStatus.Pending); + allStatuses.Should().Contain(P.OrchestrationStatus.Running); + allStatuses.Should().Contain(P.OrchestrationStatus.Suspended); + #pragma warning restore CS0618 } [Fact] - public void GetTerminalStatuses_ReturnsImmutableArray() + public void GetAllStatuses_ReturnsImmutableArray() { // Act - ImmutableArray terminalStatuses = ProtoUtils.GetTerminalStatuses(); + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); // Assert - terminalStatuses.IsDefault.Should().BeFalse(); - terminalStatuses.IsEmpty.Should().BeFalse(); + allStatuses.IsDefault.Should().BeFalse(); + allStatuses.IsEmpty.Should().BeFalse(); } [Fact] - public void ConvertDedupeStatusesToReusePolicy_EmptyArray_ReturnsPolicyWithAllTerminalStatuses() + public void ConvertDedupeStatusesToReusePolicy_EmptyArray_ReturnsPolicyWithAllStatuses() { // Arrange var dedupeStatuses = Array.Empty(); // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert - // Empty array means no dedupe statuses, so all terminal statuses are replaceable + // Empty array means no dedupe statuses, so all statuses are replaceable result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(4); + result!.ReplaceableStatus.Should().HaveCount(7); } [Fact] - public void ConvertDedupeStatusesToReusePolicy_AllTerminalStatuses_ReturnsNull() + public void ConvertDedupeStatusesToReusePolicy_AllStatuses_ReturnsPolicyWithNoReplaceableStatuses() { // Arrange - ImmutableArray allTerminalStatuses = ProtoUtils.GetTerminalStatuses(); - var dedupeStatuses = allTerminalStatuses.ToArray(); + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); + var dedupeStatuses = allStatuses.ToArray(); // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert - result.Should().BeNull(); + result.ReplaceableStatus.Should().BeEmpty(); } [Fact] - public void ConvertDedupeStatusesToReusePolicy_NoDedupeStatuses_ReturnsPolicyWithAllTerminalStatuses() + public void ConvertDedupeStatusesToReusePolicy_NoDedupeStatuses_ReturnsPolicyWithAllStatuses() { // Arrange var dedupeStatuses = Array.Empty(); // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert - // When no dedupe statuses, all terminal statuses should be replaceable + // When no dedupe statuses, all statuses should be replaceable result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(4); + result!.ReplaceableStatus.Should().HaveCount(7); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Completed); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Failed); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete - result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); +#pragma warning restore CS0618 + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Pending); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Running); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Suspended); } [Fact] public void ConvertDedupeStatusesToReusePolicy_SingleDedupeStatus_ReturnsPolicyWithRemainingStatuses() { // Arrange - var dedupeStatuses = new[] { P.OrchestrationStatus.Completed }; + var dedupeStatuses = new[] { P.OrchestrationStatus.Running }; // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(3); + result!.ReplaceableStatus.Should().HaveCount(6); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Failed); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); #pragma warning restore CS0618 - result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Completed); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Completed); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Pending); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Suspended); + result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Running); + } [Fact] @@ -112,21 +123,25 @@ public void ConvertDedupeStatusesToReusePolicy_MultipleDedupeStatuses_ReturnsPol var dedupeStatuses = new[] { P.OrchestrationStatus.Completed, - P.OrchestrationStatus.Failed + P.OrchestrationStatus.Failed, + P.OrchestrationStatus.Pending }; // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(2); + result!.ReplaceableStatus.Should().HaveCount(4); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 +#pragma warning restore CS0618 + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Running); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Suspended); result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Completed); - result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Failed); + result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Failed); + result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Pending); } [Fact] @@ -141,57 +156,22 @@ public void ConvertDedupeStatusesToReusePolicy_DuplicateDedupeStatuses_HandlesDu }; // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(2); + result!.ReplaceableStatus.Should().HaveCount(5); result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 +#pragma warning restore CS0618 + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Pending); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Running); + result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Suspended); } [Fact] - public void ConvertDedupeStatusesToReusePolicy_NonTerminalStatus_IgnoresNonTerminalStatus() - { - // Arrange - var dedupeStatuses = new[] - { - P.OrchestrationStatus.Completed, - P.OrchestrationStatus.Running, // Non-terminal status - P.OrchestrationStatus.Pending // Non-terminal status - }; - - // Act - P.OrchestrationIdReusePolicy? result = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); - - // Assert - result.Should().NotBeNull(); - result!.ReplaceableStatus.Should().HaveCount(3); - result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Failed); - result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Terminated); -#pragma warning disable CS0618 // Type or member is obsolete - result.ReplaceableStatus.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 - result.ReplaceableStatus.Should().NotContain(P.OrchestrationStatus.Completed); - } - - [Fact] - public void ConvertReusePolicyToDedupeStatuses_NullPolicy_ReturnsNull() - { - // Arrange - P.OrchestrationIdReusePolicy? policy = null; - - // Act - P.OrchestrationStatus[]? result = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); - - // Assert - result.Should().BeNull(); - } - - [Fact] - public void ConvertReusePolicyToDedupeStatuses_EmptyPolicy_ReturnsNull() + public void ConvertReusePolicyToDedupeStatuses_EmptyPolicy_ReturnsAllStatuses() { // Arrange var policy = new P.OrchestrationIdReusePolicy(); @@ -200,16 +180,16 @@ public void ConvertReusePolicyToDedupeStatuses_EmptyPolicy_ReturnsNull() P.OrchestrationStatus[]? result = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert - result.Should().BeNull(); + result.Should().Equal(ProtoUtils.GetAllStatuses()); } [Fact] - public void ConvertReusePolicyToDedupeStatuses_AllTerminalStatusesReplaceable_ReturnsNull() + public void ConvertReusePolicyToDedupeStatuses_AllStatusesReplaceable_ReturnsNull() { // Arrange var policy = new P.OrchestrationIdReusePolicy(); - ImmutableArray terminalStatuses = ProtoUtils.GetTerminalStatuses(); - foreach (var status in terminalStatuses) + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); + foreach (var status in allStatuses) { policy.ReplaceableStatus.Add(status); } @@ -233,12 +213,15 @@ public void ConvertReusePolicyToDedupeStatuses_SingleReplaceableStatus_ReturnsRe // Assert result.Should().NotBeNull(); - result!.Should().HaveCount(3); + result!.Should().HaveCount(6); result.Should().Contain(P.OrchestrationStatus.Failed); result.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete result.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 +#pragma warning restore CS0618 + result.Should().Contain(P.OrchestrationStatus.Running); + result.Should().Contain(P.OrchestrationStatus.Pending); + result.Should().Contain(P.OrchestrationStatus.Suspended); result.Should().NotContain(P.OrchestrationStatus.Completed); } @@ -255,38 +238,18 @@ public void ConvertReusePolicyToDedupeStatuses_MultipleReplaceableStatuses_Retur // Assert result.Should().NotBeNull(); - result!.Should().HaveCount(2); + result!.Should().HaveCount(5); result.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete - result.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 + result.Should().Contain(P.OrchestrationStatus.Canceled); +#pragma warning restore CS0618 + result.Should().Contain(P.OrchestrationStatus.Running); + result.Should().Contain(P.OrchestrationStatus.Pending); + result.Should().Contain(P.OrchestrationStatus.Suspended); result.Should().NotContain(P.OrchestrationStatus.Completed); result.Should().NotContain(P.OrchestrationStatus.Failed); } - [Fact] - public void ConvertReusePolicyToDedupeStatuses_NonTerminalStatusInPolicy_IgnoresNonTerminalStatus() - { - // Arrange - var policy = new P.OrchestrationIdReusePolicy(); - policy.ReplaceableStatus.Add(P.OrchestrationStatus.Completed); - policy.ReplaceableStatus.Add(P.OrchestrationStatus.Running); // Non-terminal status - policy.ReplaceableStatus.Add(P.OrchestrationStatus.Pending); // Non-terminal status - - // Act - P.OrchestrationStatus[]? result = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); - - // Assert - result.Should().NotBeNull(); - result!.Should().HaveCount(3); - result.Should().Contain(P.OrchestrationStatus.Failed); - result.Should().Contain(P.OrchestrationStatus.Terminated); -#pragma warning disable CS0618 // Type or member is obsolete - result.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 - result.Should().NotContain(P.OrchestrationStatus.Completed); - } - [Fact] public void ConvertReusePolicyToDedupeStatuses_DuplicateReplaceableStatuses_HandlesDuplicates() { @@ -301,11 +264,14 @@ public void ConvertReusePolicyToDedupeStatuses_DuplicateReplaceableStatuses_Hand // Assert result.Should().NotBeNull(); - result!.Should().HaveCount(2); + result!.Should().HaveCount(5); result.Should().Contain(P.OrchestrationStatus.Terminated); #pragma warning disable CS0618 // Type or member is obsolete - result.Should().Contain(P.OrchestrationStatus.Canceled); -#pragma warning restore CS0618 + result.Should().Contain(P.OrchestrationStatus.Canceled); +#pragma warning restore CS0618 + result.Should().Contain(P.OrchestrationStatus.Running); + result.Should().Contain(P.OrchestrationStatus.Pending); + result.Should().Contain(P.OrchestrationStatus.Suspended); } [Fact] @@ -319,7 +285,7 @@ public void ConvertDedupeStatusesToReusePolicy_ThenConvertBack_ReturnsOriginalDe }; // Act - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(originalDedupeStatuses); + P.OrchestrationIdReusePolicy policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(originalDedupeStatuses); P.OrchestrationStatus[]? convertedBack = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert @@ -345,19 +311,20 @@ public void ConvertReusePolicyToDedupeStatuses_ThenConvertBack_ReturnsOriginalPo } [Fact] - public void ConvertDedupeStatusesToReusePolicy_AllStatuses_ThenConvertBack_ReturnsNull() + public void ConvertDedupeStatusesToReusePolicy_AllStatuses_ThenConvertBack_IsOriginal() { // Arrange - ImmutableArray allTerminalStatuses = ProtoUtils.GetTerminalStatuses(); - var dedupeStatuses = allTerminalStatuses.ToArray(); + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); + var dedupeStatuses = allStatuses.ToArray(); // Act - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); P.OrchestrationStatus[]? convertedBack = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert - policy.Should().BeNull(); - convertedBack.Should().BeNull(); + policy.ReplaceableStatus.Should().BeEmpty(); + convertedBack.Should().NotBeNull(); + convertedBack.Should().Equal(dedupeStatuses); } [Fact] @@ -365,22 +332,22 @@ public void ConvertReusePolicyToDedupeStatuses_AllStatuses_ThenConvertBack_Retur { // Arrange var policy = new P.OrchestrationIdReusePolicy(); - ImmutableArray terminalStatuses = ProtoUtils.GetTerminalStatuses(); - foreach (var status in terminalStatuses) + ImmutableArray allStatuses = ProtoUtils.GetAllStatuses(); + foreach (var status in allStatuses) { policy.ReplaceableStatus.Add(status); } // Act P.OrchestrationStatus[]? dedupeStatuses = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); - P.OrchestrationIdReusePolicy? convertedBack = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy convertedBack = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert // Policy with all statuses -> no dedupe statuses -> null // null dedupe statuses -> all are replaceable -> policy with all statuses dedupeStatuses.Should().BeNull(); convertedBack.Should().NotBeNull(); - convertedBack!.ReplaceableStatus.Should().HaveCount(4); + convertedBack!.ReplaceableStatus.Should().HaveCount(7); convertedBack.ReplaceableStatus.Should().BeEquivalentTo(policy.ReplaceableStatus); } @@ -391,11 +358,11 @@ public void ConvertDedupeStatusesToReusePolicy_EmptyArray_ThenConvertBack_Return var dedupeStatuses = Array.Empty(); // Act - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); P.OrchestrationStatus[]? convertedBack = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert - // Empty dedupe statuses -> all terminal statuses are replaceable -> policy with all statuses + // Empty dedupe statuses -> all statuses are replaceable -> policy with all statuses // Policy with all statuses -> no dedupe statuses -> null policy.Should().NotBeNull(); convertedBack.Should().BeNull(); @@ -409,20 +376,22 @@ public void ConvertReusePolicyToDedupeStatuses_EmptyPolicy_ThenConvertBack_Retur // Act P.OrchestrationStatus[]? dedupeStatuses = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); - P.OrchestrationIdReusePolicy? convertedBack = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy convertedBack = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); // Assert - // Empty policy (no replaceable statuses) -> ConvertReusePolicyToDedupeStatuses returns null - // null dedupe statuses -> all terminal statuses are replaceable -> policy with all statuses - dedupeStatuses.Should().BeNull(); - convertedBack.Should().NotBeNull(); - convertedBack!.ReplaceableStatus.Should().HaveCount(4); + // Empty policy (no replaceable statuses) -> ConvertReusePolicyToDedupeStatuses returns all statuses + // all statuses deduped -> no statuses are replaceable -> policy with no statuses + dedupeStatuses.Should().Equal(ProtoUtils.GetAllStatuses()); + convertedBack.ReplaceableStatus.Should().BeEmpty(); } [Theory] [InlineData(P.OrchestrationStatus.Completed)] [InlineData(P.OrchestrationStatus.Failed)] - [InlineData(P.OrchestrationStatus.Terminated)] + [InlineData(P.OrchestrationStatus.Terminated)] + [InlineData(P.OrchestrationStatus.Pending)] + [InlineData(P.OrchestrationStatus.Running)] + [InlineData(P.OrchestrationStatus.Suspended)] public void ConvertDedupeStatusesToReusePolicy_SingleStatus_ThenConvertBack_ReturnsOriginal( P.OrchestrationStatus dedupeStatus) { @@ -430,7 +399,7 @@ public void ConvertDedupeStatusesToReusePolicy_SingleStatus_ThenConvertBack_Retu var dedupeStatuses = new[] { dedupeStatus }; // Act - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); P.OrchestrationStatus[]? convertedBack = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert @@ -451,7 +420,7 @@ public void ConvertDedupeStatusesToReusePolicy_ThreeOutOfFourStatuses_ThenConver }; // Act - P.OrchestrationIdReusePolicy? policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); + P.OrchestrationIdReusePolicy policy = ProtoUtils.ConvertDedupeStatusesToReusePolicy(dedupeStatuses); P.OrchestrationStatus[]? convertedBack = ProtoUtils.ConvertReusePolicyToDedupeStatuses(policy); // Assert